Juan Lang : userenv: Implement GetProfilesDirectory.

Alexandre Julliard julliard at winehq.org
Fri Aug 27 11:11:20 CDT 2010


Module: wine
Branch: master
Commit: e5394c6ce562104a5fc5a34c787396363b61a281
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e5394c6ce562104a5fc5a34c787396363b61a281

Author: Juan Lang <juan.lang at 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 )




More information about the wine-cvs mailing list