@@ -1296,7 +1296,8 @@ static Handle<Value> CwdForDrive(const Arguments& args) {
1296
1296
env_key[1 ] = (WCHAR) drive;
1297
1297
1298
1298
DWORD len = GetEnvironmentVariableW (env_key, NULL , 0 );
1299
- if (len == 0 && GetLastError () == ERROR_ENVVAR_NOT_FOUND) {
1299
+ if (len == 0 && (GetLastError () == ERROR_ENVVAR_NOT_FOUND ||
1300
+ GetLastError () == ERROR_SUCCESS)) {
1300
1301
// There is no current directory for that drive. Default to drive + ":\".
1301
1302
Local<String> cwd = String::Concat (String::New (&drive, 1 ),
1302
1303
String::New (" :\\ " ));
@@ -1317,7 +1318,7 @@ static Handle<Value> CwdForDrive(const Arguments& args) {
1317
1318
}
1318
1319
1319
1320
DWORD len2 = GetEnvironmentVariableW (env_key, buffer, len);
1320
- if (len2 == 0 || len2 >= len) {
1321
+ if (( len2 == 0 && GetLastError () != ERROR_SUCCESS) || len2 >= len) {
1321
1322
// Error
1322
1323
delete[] buffer;
1323
1324
Local<Value> exception = Exception::Error (
@@ -1869,12 +1870,28 @@ static void ProcessTitleSetter(Local<String> property,
1869
1870
1870
1871
static Handle <Value> EnvGetter (Local<String> property,
1871
1872
const AccessorInfo& info) {
1873
+ HandleScope scope;
1874
+ #ifdef __POSIX__
1872
1875
String::Utf8Value key (property);
1873
1876
const char * val = getenv (*key);
1874
1877
if (val) {
1875
- HandleScope scope;
1876
1878
return scope.Close (String::New (val));
1877
1879
}
1880
+ #else // _WIN32
1881
+ String::Value key (property);
1882
+ WCHAR buffer[32767 ]; // The maximum size allowed for environment variables.
1883
+ DWORD result = GetEnvironmentVariableW (reinterpret_cast <WCHAR*>(*key),
1884
+ buffer,
1885
+ ARRAY_SIZE (buffer));
1886
+ // If result >= sizeof buffer the buffer was too small. That should never
1887
+ // happen. If result == 0 and result != ERROR_SUCCESS the variable was not
1888
+ // not found.
1889
+ if ((result > 0 || GetLastError () == ERROR_SUCCESS) &&
1890
+ result < ARRAY_SIZE (buffer)) {
1891
+ return scope.Close (String::New (reinterpret_cast <uint16_t *>(buffer), result));
1892
+ }
1893
+ #endif
1894
+ // Not found
1878
1895
return Undefined ();
1879
1896
}
1880
1897
@@ -1883,66 +1900,82 @@ static Handle<Value> EnvSetter(Local<String> property,
1883
1900
Local<Value> value,
1884
1901
const AccessorInfo& info) {
1885
1902
HandleScope scope;
1903
+ #ifdef __POSIX__
1886
1904
String::Utf8Value key (property);
1887
1905
String::Utf8Value val (value);
1888
-
1889
- #ifdef __POSIX__
1890
1906
setenv (*key, *val, 1 );
1891
- #else // __WIN32__
1892
- int n = key. length () + val. length () + 2 ;
1893
- char * pair = new char [n] ;
1894
- snprintf (pair, n, " %s=%s " , *key, *val );
1895
- int r = _putenv (pair);
1896
- if (r ) {
1897
- fprintf (stderr, " error putenv: '%s' \n " , pair );
1907
+ #else // _WIN32
1908
+ String::Value key (property) ;
1909
+ String::Value val (value) ;
1910
+ WCHAR* key_ptr = reinterpret_cast <WCHAR*>(*key );
1911
+ // Environment variables that start with '=' are read-only.
1912
+ if (key_ptr[ 0 ] != L ' = ' ) {
1913
+ SetEnvironmentVariableW (key_ptr, reinterpret_cast <WCHAR*>(*val) );
1898
1914
}
1899
- delete [] pair;
1900
1915
#endif
1901
-
1902
- return value;
1916
+ // Whether it worked or not, always return rval.
1917
+ return scope. Close ( value) ;
1903
1918
}
1904
1919
1905
1920
1906
1921
static Handle <Integer> EnvQuery (Local<String> property,
1907
1922
const AccessorInfo& info) {
1923
+ HandleScope scope;
1924
+ #ifdef __POSIX__
1908
1925
String::Utf8Value key (property);
1909
1926
if (getenv (*key)) {
1910
- HandleScope scope;
1911
1927
return scope.Close (Integer::New (None));
1912
1928
}
1913
- return Handle <Integer>();
1929
+ #else // _WIN32
1930
+ String::Value key (property);
1931
+ WCHAR* key_ptr = reinterpret_cast <WCHAR*>(*key);
1932
+ if (GetEnvironmentVariableW (key_ptr, NULL , 0 ) > 0 ||
1933
+ GetLastError () == ERROR_SUCCESS) {
1934
+ if (key_ptr[0 ] == L' =' ) {
1935
+ // Environment variables that start with '=' are hidden and read-only.
1936
+ return scope.Close (Integer::New (v8::ReadOnly ||
1937
+ v8::DontDelete ||
1938
+ v8::DontEnum));
1939
+ } else {
1940
+ return scope.Close (Integer::New (None));
1941
+ }
1942
+ }
1943
+ #endif
1944
+ // Not found
1945
+ return scope.Close (Handle <Integer>());
1914
1946
}
1915
1947
1916
1948
1917
1949
static Handle <Boolean > EnvDeleter (Local<String> property,
1918
1950
const AccessorInfo& info) {
1919
1951
HandleScope scope;
1920
-
1921
- String::Utf8Value key (property);
1922
-
1923
- if (getenv (*key)) {
1924
1952
#ifdef __POSIX__
1925
- unsetenv (*key); // prototyped as `void unsetenv(const char*)` on some platforms
1953
+ String::Utf8Value key (property);
1954
+ // prototyped as `void unsetenv(const char*)` on some platforms
1955
+ if (unsetenv (*key) < 0 ) {
1956
+ // Deletion failed. Return true if the key wasn't there in the first place,
1957
+ // false if it is still there.
1958
+ return scope.Close (Boolean::New (getenv (*key) == NULL ));
1959
+ };
1926
1960
#else
1927
- int n = key.length () + 2 ;
1928
- char * pair = new char [n];
1929
- snprintf (pair, n, " %s=" , *key);
1930
- int r = _putenv (pair);
1931
- if (r) {
1932
- fprintf (stderr, " error unsetenv: '%s'\n " , pair);
1933
- }
1934
- delete [] pair;
1935
- #endif
1936
- return True ();
1961
+ String::Value key (property);
1962
+ WCHAR* key_ptr = reinterpret_cast <WCHAR*>(*key);
1963
+ if (key_ptr[0 ] == L' =' || !SetEnvironmentVariableW (key_ptr, NULL )) {
1964
+ // Deletion failed. Return true if the key wasn't there in the first place,
1965
+ // false if it is still there.
1966
+ bool rv = GetEnvironmentVariableW (key_ptr, NULL , NULL ) == 0 &&
1967
+ GetLastError () != ERROR_SUCCESS;
1968
+ return scope.Close (Boolean::New (rv));
1937
1969
}
1938
-
1939
- return False ();
1970
+ #endif
1971
+ // It worked
1972
+ return v8::True ();
1940
1973
}
1941
1974
1942
1975
1943
1976
static Handle <Array> EnvEnumerator (const AccessorInfo& info) {
1944
1977
HandleScope scope;
1945
-
1978
+ # ifdef __POSIX__
1946
1979
int size = 0 ;
1947
1980
while (environ[size]) size++;
1948
1981
@@ -1954,7 +1987,32 @@ static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
1954
1987
const int length = s ? s - var : strlen (var);
1955
1988
env->Set (i, String::New (var, length));
1956
1989
}
1957
-
1990
+ #else // _WIN32
1991
+ WCHAR* environment = GetEnvironmentStringsW ();
1992
+ if (environment == NULL ) {
1993
+ // This should not happen.
1994
+ return scope.Close (Handle <Array>());
1995
+ }
1996
+ Local<Array> env = Array::New ();
1997
+ WCHAR* p = environment;
1998
+ int i = 0 ;
1999
+ while (*p != NULL ) {
2000
+ WCHAR *s;
2001
+ if (*p == L' =' ) {
2002
+ // If the key starts with '=' it is a hidden environment variable.
2003
+ p += wcslen (p) + 1 ;
2004
+ continue ;
2005
+ } else {
2006
+ s = wcschr (p, L' =' );
2007
+ }
2008
+ if (!s) {
2009
+ s = p + wcslen (p);
2010
+ }
2011
+ env->Set (i++, String::New (reinterpret_cast <uint16_t *>(p), s - p));
2012
+ p = s + wcslen (s) + 1 ;
2013
+ }
2014
+ FreeEnvironmentStringsW (environment);
2015
+ #endif
1958
2016
return scope.Close (env);
1959
2017
}
1960
2018
0 commit comments