From a0c8815294faeec87b5f65e84fb8b3a4230af9bc Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 28 May 2015 21:53:18 -0400 Subject: [PATCH] win: add XP support to uv_os_homedir() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous Windows implementation used SHGetKnownFolderPath(), which is only supported on Vista and up. This commit switches to GetUserProfileDirectoryW(), which returns the same information, but is supported back to Windows 2000, and is not deprecated. PR-URL: https://github.com/libuv/libuv/pull/375 Reviewed-By: Saúl Ibarra Corretgé --- Makefile.am | 2 +- docs/src/misc.rst | 2 +- src/win/util.c | 71 +++++++++++++++++++++++------------------------ uv.gyp | 2 +- 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/Makefile.am b/Makefile.am index 41a94045..e9814d7b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,7 +45,7 @@ include_HEADERS += include/uv-win.h include/tree.h AM_CPPFLAGS += -I$(top_srcdir)/src/win \ -DWIN32_LEAN_AND_MEAN \ -D_WIN32_WINNT=0x0600 -LIBS += -lws2_32 -lpsapi -liphlpapi -lole32 -lshell32 +LIBS += -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv libuv_la_SOURCES += src/win/async.c \ src/win/atomicops-inl.h \ src/win/core.c \ diff --git a/docs/src/misc.rst b/docs/src/misc.rst index fb5a8a40..9708c5de 100644 --- a/docs/src/misc.rst +++ b/docs/src/misc.rst @@ -272,7 +272,7 @@ API Gets the current user's home directory. On Windows, `uv_os_homedir()` first checks the `USERPROFILE` environment variable using `GetEnvironmentVariableW()`. If `USERPROFILE` is not set, - `SHGetKnownFolderPath()` is called. On all other operating systems, + `GetUserProfileDirectoryW()` is called. On all other operating systems, `uv_os_homedir()` first checks the `HOME` environment variable using :man:`getenv(3)`. If `HOME` is not set, :man:`getpwuid_r(3)` is called. The user's home directory is stored in `buffer`. When `uv_os_homedir()` is diff --git a/src/win/util.c b/src/win/util.c index 2e6015f8..58e42bbd 100644 --- a/src/win/util.c +++ b/src/win/util.c @@ -36,8 +36,7 @@ #include #include #include -#include -#include +#include /* @@ -1158,7 +1157,8 @@ int uv_getrusage(uv_rusage_t *uv_rusage) { int uv_os_homedir(char* buffer, size_t* size) { - wchar_t* path; + HANDLE token; + wchar_t path[MAX_PATH]; size_t bufsize; size_t len; int r; @@ -1167,55 +1167,54 @@ int uv_os_homedir(char* buffer, size_t* size) { return UV_EINVAL; /* Check if the USERPROFILE environment variable is set first */ - path = uv__malloc(*size * sizeof(WCHAR)); - - if (path == NULL) - return UV_ENOMEM; - - len = GetEnvironmentVariableW(L"USERPROFILE", path, *size); + len = GetEnvironmentVariableW(L"USERPROFILE", path, MAX_PATH); if (len == 0) { r = GetLastError(); - uv__free(path); - + /* Don't return an error if USERPROFILE was not found */ if (r != ERROR_ENVVAR_NOT_FOUND) return uv_translate_sys_error(r); + } else if (len > MAX_PATH) { + /* This should not be possible */ + return UV_EIO; } else { - if (len > *size) { - uv__free(path); - *size = len - 1; - return UV_ENOBUFS; - } - - bufsize = uv_utf16_to_utf8(path, -1, buffer, *size); - assert(len + 1 == bufsize); - uv__free(path); - *size = len; - - return 0; + goto convert_buffer; } - /* USERPROFILE is not set, so call SHGetKnownFolderPath() */ - if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, &path) != S_OK) + /* USERPROFILE is not set, so call GetUserProfileDirectoryW() */ + if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0) return uv_translate_sys_error(GetLastError()); - bufsize = uv_utf16_to_utf8(path, -1, buffer, *size); - - if (bufsize == 0) { + bufsize = MAX_PATH; + if (!GetUserProfileDirectoryW(token, path, &bufsize)) { r = GetLastError(); + CloseHandle(token); - if (r == ERROR_INSUFFICIENT_BUFFER) { - *size = wcslen(path); - CoTaskMemFree(path); - return UV_ENOBUFS; - } + /* This should not be possible */ + if (r == ERROR_INSUFFICIENT_BUFFER) + return UV_EIO; - CoTaskMemFree(path); return uv_translate_sys_error(r); } - CoTaskMemFree(path); - *size = bufsize - 1; + CloseHandle(token); +convert_buffer: + + /* Check how much space we need */ + bufsize = uv_utf16_to_utf8(path, -1, NULL, 0); + if (bufsize == 0) { + return uv_translate_sys_error(GetLastError()); + } else if (bufsize > *size) { + *size = bufsize - 1; + return UV_ENOBUFS; + } + + /* Convert to UTF-8 */ + bufsize = uv_utf16_to_utf8(path, -1, buffer, *size); + if (bufsize == 0) + return uv_translate_sys_error(GetLastError()); + + *size = bufsize - 1; return 0; } diff --git a/uv.gyp b/uv.gyp index cbd70abc..7173a827 100644 --- a/uv.gyp +++ b/uv.gyp @@ -108,9 +108,9 @@ 'libraries': [ '-ladvapi32', '-liphlpapi', - '-lole32', '-lpsapi', '-lshell32', + '-luserenv', '-lws2_32' ], },