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 \
|
AM_CPPFLAGS += -I$(top_srcdir)/src/win \
|
||||||
-DWIN32_LEAN_AND_MEAN \
|
-DWIN32_LEAN_AND_MEAN \
|
||||||
-D_WIN32_WINNT=0x0600
|
-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 \
|
libuv_la_SOURCES += src/win/async.c \
|
||||||
src/win/atomicops-inl.h \
|
src/win/atomicops-inl.h \
|
||||||
src/win/core.c \
|
src/win/core.c \
|
||||||
|
|||||||
@ -272,7 +272,7 @@ API
|
|||||||
Gets the current user's home directory. On Windows, `uv_os_homedir()` first
|
Gets the current user's home directory. On Windows, `uv_os_homedir()` first
|
||||||
checks the `USERPROFILE` environment variable using
|
checks the `USERPROFILE` environment variable using
|
||||||
`GetEnvironmentVariableW()`. If `USERPROFILE` is not set,
|
`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
|
`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
|
: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
|
user's home directory is stored in `buffer`. When `uv_os_homedir()` is
|
||||||
|
|||||||
@ -36,8 +36,7 @@
|
|||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
#include <tlhelp32.h>
|
#include <tlhelp32.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shlobj.h>
|
#include <userenv.h>
|
||||||
#include <objbase.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1158,7 +1157,8 @@ int uv_getrusage(uv_rusage_t *uv_rusage) {
|
|||||||
|
|
||||||
|
|
||||||
int uv_os_homedir(char* buffer, size_t* size) {
|
int uv_os_homedir(char* buffer, size_t* size) {
|
||||||
wchar_t* path;
|
HANDLE token;
|
||||||
|
wchar_t path[MAX_PATH];
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
size_t len;
|
size_t len;
|
||||||
int r;
|
int r;
|
||||||
@ -1167,55 +1167,54 @@ int uv_os_homedir(char* buffer, size_t* size) {
|
|||||||
return UV_EINVAL;
|
return UV_EINVAL;
|
||||||
|
|
||||||
/* Check if the USERPROFILE environment variable is set first */
|
/* Check if the USERPROFILE environment variable is set first */
|
||||||
path = uv__malloc(*size * sizeof(WCHAR));
|
len = GetEnvironmentVariableW(L"USERPROFILE", path, MAX_PATH);
|
||||||
|
|
||||||
if (path == NULL)
|
|
||||||
return UV_ENOMEM;
|
|
||||||
|
|
||||||
len = GetEnvironmentVariableW(L"USERPROFILE", path, *size);
|
|
||||||
|
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
r = GetLastError();
|
r = GetLastError();
|
||||||
uv__free(path);
|
/* Don't return an error if USERPROFILE was not found */
|
||||||
|
|
||||||
if (r != ERROR_ENVVAR_NOT_FOUND)
|
if (r != ERROR_ENVVAR_NOT_FOUND)
|
||||||
return uv_translate_sys_error(r);
|
return uv_translate_sys_error(r);
|
||||||
|
} else if (len > MAX_PATH) {
|
||||||
|
/* This should not be possible */
|
||||||
|
return UV_EIO;
|
||||||
} else {
|
} else {
|
||||||
if (len > *size) {
|
goto convert_buffer;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* USERPROFILE is not set, so call SHGetKnownFolderPath() */
|
/* USERPROFILE is not set, so call GetUserProfileDirectoryW() */
|
||||||
if (SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, &path) != S_OK)
|
if (OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token) == 0)
|
||||||
return uv_translate_sys_error(GetLastError());
|
return uv_translate_sys_error(GetLastError());
|
||||||
|
|
||||||
bufsize = uv_utf16_to_utf8(path, -1, buffer, *size);
|
bufsize = MAX_PATH;
|
||||||
|
if (!GetUserProfileDirectoryW(token, path, &bufsize)) {
|
||||||
if (bufsize == 0) {
|
|
||||||
r = GetLastError();
|
r = GetLastError();
|
||||||
|
CloseHandle(token);
|
||||||
|
|
||||||
if (r == ERROR_INSUFFICIENT_BUFFER) {
|
/* This should not be possible */
|
||||||
*size = wcslen(path);
|
if (r == ERROR_INSUFFICIENT_BUFFER)
|
||||||
CoTaskMemFree(path);
|
return UV_EIO;
|
||||||
return UV_ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoTaskMemFree(path);
|
|
||||||
return uv_translate_sys_error(r);
|
return uv_translate_sys_error(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoTaskMemFree(path);
|
CloseHandle(token);
|
||||||
*size = bufsize - 1;
|
|
||||||
|
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user