mirror of https://github.com/nodejs/node.git
Windows: use unicode environment
parent
0685707bc6
commit
077f9d7293
130
src/node.cc
130
src/node.cc
|
@ -1296,7 +1296,8 @@ static Handle<Value> CwdForDrive(const Arguments& args) {
|
|||
env_key[1] = (WCHAR) drive;
|
||||
|
||||
DWORD len = GetEnvironmentVariableW(env_key, NULL, 0);
|
||||
if (len == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
|
||||
if (len == 0 && (GetLastError() == ERROR_ENVVAR_NOT_FOUND ||
|
||||
GetLastError() == ERROR_SUCCESS)) {
|
||||
// There is no current directory for that drive. Default to drive + ":\".
|
||||
Local<String> cwd = String::Concat(String::New(&drive, 1),
|
||||
String::New(":\\"));
|
||||
|
@ -1317,7 +1318,7 @@ static Handle<Value> CwdForDrive(const Arguments& args) {
|
|||
}
|
||||
|
||||
DWORD len2 = GetEnvironmentVariableW(env_key, buffer, len);
|
||||
if (len2 == 0 || len2 >= len) {
|
||||
if ((len2 == 0 && GetLastError() != ERROR_SUCCESS) || len2 >= len) {
|
||||
// Error
|
||||
delete[] buffer;
|
||||
Local<Value> exception = Exception::Error(
|
||||
|
@ -1869,12 +1870,28 @@ static void ProcessTitleSetter(Local<String> property,
|
|||
|
||||
static Handle<Value> EnvGetter(Local<String> property,
|
||||
const AccessorInfo& info) {
|
||||
HandleScope scope;
|
||||
#ifdef __POSIX__
|
||||
String::Utf8Value key(property);
|
||||
const char* val = getenv(*key);
|
||||
if (val) {
|
||||
HandleScope scope;
|
||||
return scope.Close(String::New(val));
|
||||
}
|
||||
#else // _WIN32
|
||||
String::Value key(property);
|
||||
WCHAR buffer[32767]; // The maximum size allowed for environment variables.
|
||||
DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
|
||||
buffer,
|
||||
ARRAY_SIZE(buffer));
|
||||
// If result >= sizeof buffer the buffer was too small. That should never
|
||||
// happen. If result == 0 and result != ERROR_SUCCESS the variable was not
|
||||
// not found.
|
||||
if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
|
||||
result < ARRAY_SIZE(buffer)) {
|
||||
return scope.Close(String::New(reinterpret_cast<uint16_t*>(buffer), result));
|
||||
}
|
||||
#endif
|
||||
// Not found
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
|
@ -1883,66 +1900,82 @@ static Handle<Value> EnvSetter(Local<String> property,
|
|||
Local<Value> value,
|
||||
const AccessorInfo& info) {
|
||||
HandleScope scope;
|
||||
#ifdef __POSIX__
|
||||
String::Utf8Value key(property);
|
||||
String::Utf8Value val(value);
|
||||
|
||||
#ifdef __POSIX__
|
||||
setenv(*key, *val, 1);
|
||||
#else // __WIN32__
|
||||
int n = key.length() + val.length() + 2;
|
||||
char* pair = new char[n];
|
||||
snprintf(pair, n, "%s=%s", *key, *val);
|
||||
int r = _putenv(pair);
|
||||
if (r) {
|
||||
fprintf(stderr, "error putenv: '%s'\n", pair);
|
||||
#else // _WIN32
|
||||
String::Value key(property);
|
||||
String::Value val(value);
|
||||
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
|
||||
// Environment variables that start with '=' are read-only.
|
||||
if (key_ptr[0] != L'=') {
|
||||
SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
|
||||
}
|
||||
delete [] pair;
|
||||
#endif
|
||||
|
||||
return value;
|
||||
// Whether it worked or not, always return rval.
|
||||
return scope.Close(value);
|
||||
}
|
||||
|
||||
|
||||
static Handle<Integer> EnvQuery(Local<String> property,
|
||||
const AccessorInfo& info) {
|
||||
HandleScope scope;
|
||||
#ifdef __POSIX__
|
||||
String::Utf8Value key(property);
|
||||
if (getenv(*key)) {
|
||||
HandleScope scope;
|
||||
return scope.Close(Integer::New(None));
|
||||
}
|
||||
return Handle<Integer>();
|
||||
#else // _WIN32
|
||||
String::Value key(property);
|
||||
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
|
||||
if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 ||
|
||||
GetLastError() == ERROR_SUCCESS) {
|
||||
if (key_ptr[0] == L'=') {
|
||||
// Environment variables that start with '=' are hidden and read-only.
|
||||
return scope.Close(Integer::New(v8::ReadOnly ||
|
||||
v8::DontDelete ||
|
||||
v8::DontEnum));
|
||||
} else {
|
||||
return scope.Close(Integer::New(None));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Not found
|
||||
return scope.Close(Handle<Integer>());
|
||||
}
|
||||
|
||||
|
||||
static Handle<Boolean> EnvDeleter(Local<String> property,
|
||||
const AccessorInfo& info) {
|
||||
HandleScope scope;
|
||||
|
||||
String::Utf8Value key(property);
|
||||
|
||||
if (getenv(*key)) {
|
||||
#ifdef __POSIX__
|
||||
unsetenv(*key); // prototyped as `void unsetenv(const char*)` on some platforms
|
||||
String::Utf8Value key(property);
|
||||
// prototyped as `void unsetenv(const char*)` on some platforms
|
||||
if (unsetenv(*key) < 0) {
|
||||
// Deletion failed. Return true if the key wasn't there in the first place,
|
||||
// false if it is still there.
|
||||
return scope.Close(Boolean::New(getenv(*key) == NULL));
|
||||
};
|
||||
#else
|
||||
int n = key.length() + 2;
|
||||
char* pair = new char[n];
|
||||
snprintf(pair, n, "%s=", *key);
|
||||
int r = _putenv(pair);
|
||||
if (r) {
|
||||
fprintf(stderr, "error unsetenv: '%s'\n", pair);
|
||||
}
|
||||
delete [] pair;
|
||||
#endif
|
||||
return True();
|
||||
String::Value key(property);
|
||||
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
|
||||
if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) {
|
||||
// Deletion failed. Return true if the key wasn't there in the first place,
|
||||
// false if it is still there.
|
||||
bool rv = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 &&
|
||||
GetLastError() != ERROR_SUCCESS;
|
||||
return scope.Close(Boolean::New(rv));
|
||||
}
|
||||
|
||||
return False();
|
||||
#endif
|
||||
// It worked
|
||||
return v8::True();
|
||||
}
|
||||
|
||||
|
||||
static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
|
||||
HandleScope scope;
|
||||
|
||||
#ifdef __POSIX__
|
||||
int size = 0;
|
||||
while (environ[size]) size++;
|
||||
|
||||
|
@ -1954,7 +1987,32 @@ static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
|
|||
const int length = s ? s - var : strlen(var);
|
||||
env->Set(i, String::New(var, length));
|
||||
}
|
||||
|
||||
#else // _WIN32
|
||||
WCHAR* environment = GetEnvironmentStringsW();
|
||||
if (environment == NULL) {
|
||||
// This should not happen.
|
||||
return scope.Close(Handle<Array>());
|
||||
}
|
||||
Local<Array> env = Array::New();
|
||||
WCHAR* p = environment;
|
||||
int i = 0;
|
||||
while (*p != NULL) {
|
||||
WCHAR *s;
|
||||
if (*p == L'=') {
|
||||
// If the key starts with '=' it is a hidden environment variable.
|
||||
p += wcslen(p) + 1;
|
||||
continue;
|
||||
} else {
|
||||
s = wcschr(p, L'=');
|
||||
}
|
||||
if (!s) {
|
||||
s = p + wcslen(p);
|
||||
}
|
||||
env->Set(i++, String::New(reinterpret_cast<uint16_t*>(p), s - p));
|
||||
p = s + wcslen(s) + 1;
|
||||
}
|
||||
FreeEnvironmentStringsW(environment);
|
||||
#endif
|
||||
return scope.Close(env);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue