win: add XP support to uv_os_homedir()
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é <saghul@gmail.com>
This commit is contained in:
parent
d110a1b6c5
commit
a0c8815294
@ -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 \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -36,8 +36,7 @@
|
||||
#include <psapi.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <objbase.h>
|
||||
#include <userenv.h>
|
||||
|
||||
|
||||
/*
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user