Module: wine Branch: master Commit: e5394c6ce562104a5fc5a34c787396363b61a281 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e5394c6ce562104a5fc5a34c78...
Author: Juan Lang juan.lang@gmail.com Date: Thu Aug 26 17:17:44 2010 -0700
userenv: Implement GetProfilesDirectory.
---
dlls/userenv/Makefile.in | 1 + dlls/userenv/tests/userenv.c | 11 ++--- dlls/userenv/userenv_main.c | 120 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 121 insertions(+), 11 deletions(-)
diff --git a/dlls/userenv/Makefile.in b/dlls/userenv/Makefile.in index f3a4149..aaf0de1 100644 --- a/dlls/userenv/Makefile.in +++ b/dlls/userenv/Makefile.in @@ -3,6 +3,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = userenv.dll +IMPORTS = advapi32 IMPORTLIB = userenv
C_SRCS = \ diff --git a/dlls/userenv/tests/userenv.c b/dlls/userenv/tests/userenv.c index 790cc80..4fa257b 100644 --- a/dlls/userenv/tests/userenv.c +++ b/dlls/userenv/tests/userenv.c @@ -240,32 +240,29 @@ static void test_get_profiles_dir(void) SetLastError(0xdeadbeef); r = GetProfilesDirectoryA(NULL, NULL); expect(FALSE, r); - todo_wine expect_gle(ERROR_INVALID_PARAMETER); SetLastError(0xdeadbeef); r = GetProfilesDirectoryA(NULL, &cch); expect(FALSE, r); - todo_wine expect_gle(ERROR_INVALID_PARAMETER); SetLastError(0xdeadbeef); cch = 1; r = GetProfilesDirectoryA(small_buf, &cch); expect(FALSE, r); - todo_wine expect_gle(ERROR_INSUFFICIENT_BUFFER); /* MSDN claims the returned character count includes the NULL terminator * when the buffer is too small, but that's not in fact what gets returned. */ - todo_wine ok(cch == profiles_len - 1, "expected %d, got %d\n", profiles_len - 1, cch); - buf = HeapAlloc(GetProcessHeap(), 0, cch); + /* Allocate one more character than the return value to prevent a buffer + * overrun. + */ + buf = HeapAlloc(GetProcessHeap(), 0, cch + 1); r = GetProfilesDirectoryA(buf, &cch); /* Rather than a BOOL, the return value is also the number of characters * stored in the buffer. */ - todo_wine expect(profiles_len - 1, r); - todo_wine ok(!strcmp(buf, profiles_dir), "expected %s, got %s\n", profiles_dir, buf);
HeapFree(GetProcessHeap(), 0, buf); diff --git a/dlls/userenv/userenv_main.c b/dlls/userenv/userenv_main.c index ddf0e21..9247f44 100644 --- a/dlls/userenv/userenv_main.c +++ b/dlls/userenv/userenv_main.c @@ -114,16 +114,128 @@ BOOL WINAPI GetUserProfileDirectoryW( HANDLE hToken, LPWSTR lpProfileDir, return FALSE; }
+static const char ProfileListA[] = "Software\Microsoft\Windows NT\CurrentVersion\ProfileList"; + BOOL WINAPI GetProfilesDirectoryA( LPSTR lpProfilesDir, LPDWORD lpcchSize ) { - FIXME("%p %p\n", lpProfilesDir, lpcchSize ); - return FALSE; + static const char ProfilesDirectory[] = "ProfilesDirectory"; + LONG l; + HKEY key; + BOOL ret = FALSE; + DWORD len = 0, expanded_len; + LPSTR unexpanded_profiles_dir = NULL; + + TRACE("%p %p\n", lpProfilesDir, lpcchSize ); + + if (!lpProfilesDir || !lpcchSize) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + l = RegOpenKeyExA(HKEY_LOCAL_MACHINE, ProfileListA, 0, KEY_READ, &key); + if (l) + { + SetLastError(l); + return FALSE; + } + l = RegQueryValueExA(key, ProfilesDirectory, NULL, NULL, NULL, &len); + if (l) + { + SetLastError(l); + goto end; + } + unexpanded_profiles_dir = HeapAlloc(GetProcessHeap(), 0, len); + if (!unexpanded_profiles_dir) + { + SetLastError(ERROR_OUTOFMEMORY); + goto end; + } + l = RegQueryValueExA(key, ProfilesDirectory, NULL, NULL, + (BYTE *)unexpanded_profiles_dir, &len); + if (l) + { + SetLastError(l); + goto end; + } + expanded_len = ExpandEnvironmentStringsA(unexpanded_profiles_dir, NULL, 0); + /* The returned length doesn't include the NULL terminator. */ + if (*lpcchSize < expanded_len - 1) + { + *lpcchSize = expanded_len - 1; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto end; + } + *lpcchSize = expanded_len - 1; + /* The return value is also the expected length. */ + ret = ExpandEnvironmentStringsA(unexpanded_profiles_dir, lpProfilesDir, + expanded_len) - 1; +end: + HeapFree(GetProcessHeap(), 0, unexpanded_profiles_dir); + RegCloseKey(key); + return ret; }
+static const WCHAR ProfileListW[] = {'S','o','f','t','w','a','r','e','\','M','i','c','r','o','s','o','f','t','\','W','i','n','d','o','w','s',' ','N','T','\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\','P','r','o','f','i','l','e','L','i','s','t',0}; + BOOL WINAPI GetProfilesDirectoryW( LPWSTR lpProfilesDir, LPDWORD lpcchSize ) { - FIXME("%p %p\n", lpProfilesDir, lpcchSize ); - return FALSE; + static const WCHAR ProfilesDirectory[] = {'P','r','o','f','i','l','e','s','D','i','r','e','c','t','o','r','y',0}; + LONG l; + HKEY key; + BOOL ret = FALSE; + DWORD len = 0, expanded_len; + LPWSTR unexpanded_profiles_dir = NULL; + + TRACE("%p %p\n", lpProfilesDir, lpcchSize ); + + if (!lpProfilesDir || !lpcchSize) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + l = RegOpenKeyExW(HKEY_LOCAL_MACHINE, ProfileListW, 0, KEY_READ, &key); + if (l) + { + SetLastError(l); + return FALSE; + } + l = RegQueryValueExW(key, ProfilesDirectory, NULL, NULL, NULL, &len); + if (l) + { + SetLastError(l); + goto end; + } + unexpanded_profiles_dir = HeapAlloc(GetProcessHeap(), 0, len); + if (!unexpanded_profiles_dir) + { + SetLastError(ERROR_OUTOFMEMORY); + goto end; + } + l = RegQueryValueExW(key, ProfilesDirectory, NULL, NULL, + (BYTE *)unexpanded_profiles_dir, &len); + if (l) + { + SetLastError(l); + goto end; + } + expanded_len = ExpandEnvironmentStringsW(unexpanded_profiles_dir, NULL, 0); + /* The returned length doesn't include the NULL terminator. */ + if (*lpcchSize < expanded_len - 1) + { + *lpcchSize = expanded_len - 1; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto end; + } + *lpcchSize = expanded_len - 1; + /* The return value is also the expected length. */ + ret = ExpandEnvironmentStringsW(unexpanded_profiles_dir, lpProfilesDir, + expanded_len) - 1; +end: + HeapFree(GetProcessHeap(), 0, unexpanded_profiles_dir); + RegCloseKey(key); + return ret; }
BOOL WINAPI GetAllUsersProfileDirectoryA( LPSTR lpProfileDir, LPDWORD lpcchSize )