Piotr Caban : shlwapi: Improved SHGetShellKey implementation.

Alexandre Julliard julliard at winehq.org
Tue Oct 12 11:27:01 CDT 2010


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Tue Oct 12 16:35:35 2010 +0200

shlwapi: Improved SHGetShellKey implementation.

---

 dlls/shlwapi/ordinal.c       |  127 +++++++++++++++++++++++++++++++++++++-----
 dlls/shlwapi/tests/ordinal.c |   65 ++++++++++++++-------
 2 files changed, 156 insertions(+), 36 deletions(-)

diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c
index 3edb116..63fffb2 100644
--- a/dlls/shlwapi/ordinal.c
+++ b/dlls/shlwapi/ordinal.c
@@ -4406,36 +4406,135 @@ BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create)
 {
     enum _shellkey_flags {
-        SHKEY_Explorer  = 0x00,
-        SHKEY_Root_HKCU = 0x01
+        SHKEY_Root_HKCU = 0x1,
+        SHKEY_Root_HKLM = 0x2,
+        SHKEY_Key_Explorer  = 0x00,
+        SHKEY_Key_Shell = 0x10,
+        SHKEY_Key_ShellNoRoam = 0x20,
+        SHKEY_Key_Classes = 0x30,
+        SHKEY_Subkey_Default = 0x0000,
+        SHKEY_Subkey_ResourceName = 0x1000,
+        SHKEY_Subkey_Handlers = 0x2000,
+        SHKEY_Subkey_Associations = 0x3000,
+        SHKEY_Subkey_Volatile = 0x4000,
+        SHKEY_Subkey_MUICache = 0x5000,
+        SHKEY_Subkey_FileExts = 0x6000
     };
 
     static const WCHAR explorerW[] = {'S','o','f','t','w','a','r','e','\\',
         'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
-        'E','x','p','l','o','r','e','r',0};
-    HKEY hroot, hkey = NULL;
+        'E','x','p','l','o','r','e','r','\\'};
+    static const WCHAR shellW[] = {'S','o','f','t','w','a','r','e','\\',
+        'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
+        'S','h','e','l','l','\\'};
+    static const WCHAR shell_no_roamW[] = {'S','o','f','t','w','a','r','e','\\',
+        'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
+        'S','h','e','l','l','N','o','R','o','a','m','\\'};
+    static const WCHAR classesW[] = {'S','o','f','t','w','a','r','e','\\',
+        'C','l','a','s','s','e','s','\\'};
+
+    static const WCHAR localized_resource_nameW[] = {'L','o','c','a','l','i','z','e','d',
+        'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
+    static const WCHAR handlersW[] = {'H','a','n','d','l','e','r','s','\\'};
+    static const WCHAR associationsW[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
+    static const WCHAR volatileW[] = {'V','o','l','a','t','i','l','e','\\'};
+    static const WCHAR mui_cacheW[] = {'M','U','I','C','a','c','h','e','\\'};
+    static const WCHAR file_extsW[] = {'F','i','l','e','E','x','t','s','\\'};
+
+    WCHAR *path;
+    const WCHAR *key, *subkey;
+    int size_key, size_subkey, size_user;
+    HKEY hkey = NULL;
 
     TRACE("(0x%08x, %s, %d)\n", flags, debugstr_w(sub_key), create);
 
-    switch (flags)
-    {
-    case SHKEY_Explorer | SHKEY_Root_HKCU:
-        RegOpenKeyExW(HKEY_CURRENT_USER, explorerW, 0, MAXIMUM_ALLOWED, &hroot);
+    /* For compatibility with Vista+ */
+    if(flags == 0x1ffff)
+        flags = 0x21;
+
+    switch(flags&0xff0) {
+    case SHKEY_Key_Explorer:
+        key = explorerW;
+        size_key = sizeof(explorerW);
+        break;
+    case SHKEY_Key_Shell:
+        key = shellW;
+        size_key = sizeof(shellW);
+        break;
+    case SHKEY_Key_ShellNoRoam:
+        key = shell_no_roamW;
+        size_key = sizeof(shell_no_roamW);
+        break;
+    case SHKEY_Key_Classes:
+        key = classesW;
+        size_key = sizeof(classesW);
         break;
-    case 0:
+    default:
+        FIXME("unsupported flags (0x%08x)\n", flags);
         return NULL;
+    }
+
+    switch(flags&0xff000) {
+    case SHKEY_Subkey_Default:
+        subkey = NULL;
+        size_subkey = 0;
+        break;
+    case SHKEY_Subkey_ResourceName:
+        subkey = localized_resource_nameW;
+        size_subkey = sizeof(localized_resource_nameW);
+        break;
+    case SHKEY_Subkey_Handlers:
+        subkey = handlersW;
+        size_subkey = sizeof(handlersW);
+        break;
+    case SHKEY_Subkey_Associations:
+        subkey = associationsW;
+        size_subkey = sizeof(associationsW);
+        break;
+    case SHKEY_Subkey_Volatile:
+        subkey = volatileW;
+        size_subkey = sizeof(volatileW);
+        break;
+    case SHKEY_Subkey_MUICache:
+        subkey = mui_cacheW;
+        size_subkey = sizeof(mui_cacheW);
+        break;
+    case SHKEY_Subkey_FileExts:
+        subkey = file_extsW;
+        size_subkey = sizeof(file_extsW);
+        break;
     default:
         FIXME("unsupported flags (0x%08x)\n", flags);
-        return (HKEY)0xdeadbeef;
+        return NULL;
     }
 
-    if (create)
-        RegCreateKeyExW(hroot, sub_key, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL);
+    if(sub_key)
+        size_user = lstrlenW(sub_key)*sizeof(WCHAR);
+    else
+        size_user = 0;
+
+    path = HeapAlloc(GetProcessHeap(), 0, size_key+size_subkey+size_user);
+    if(!path) {
+        ERR("Out of memory\n");
+        return NULL;
+    }
+
+    memcpy(path, key, size_key);
+    if(subkey)
+        memcpy(path+size_key/sizeof(WCHAR), subkey, size_subkey);
+    if(sub_key)
+        memcpy(path+(size_key+size_subkey)/sizeof(WCHAR), sub_key, size_user);
+    path[(size_key+size_subkey+size_user)/sizeof(WCHAR)] = '\0';
+
+    if(create)
+        RegCreateKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
+                path, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL);
     else
-        RegOpenKeyExW(hroot, sub_key, 0, MAXIMUM_ALLOWED, &hkey);
+        RegOpenKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
+                path, 0, MAXIMUM_ALLOWED, &hkey);
 
-    RegCloseKey(hroot);
+    HeapFree(GetProcessHeap(), 0, path);
     return hkey;
 }
 
diff --git a/dlls/shlwapi/tests/ordinal.c b/dlls/shlwapi/tests/ordinal.c
index dfee9bf..1937cb0 100644
--- a/dlls/shlwapi/tests/ordinal.c
+++ b/dlls/shlwapi/tests/ordinal.c
@@ -61,7 +61,7 @@ static HWND    (WINAPI *pSHCreateWorkerWindowA)(LONG, HWND, DWORD, DWORD, HMENU,
 static HRESULT (WINAPI *pSHIShellFolder_EnumObjects)(LPSHELLFOLDER, HWND, SHCONTF, IEnumIDList**);
 static DWORD   (WINAPI *pSHGetIniStringW)(LPCWSTR, LPCWSTR, LPWSTR, DWORD, LPCWSTR);
 static BOOL    (WINAPI *pSHSetIniStringW)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
-static HKEY    (WINAPI *pSHGetShellKey)(DWORD, LPWSTR, BOOL);
+static HKEY    (WINAPI *pSHGetShellKey)(DWORD, LPCWSTR, BOOL);
 
 static HMODULE hmlang;
 static HRESULT (WINAPI *pLcidToRfc1766A)(LCID, LPSTR, INT);
@@ -2680,15 +2680,28 @@ static void test_SHSetIniString(void)
 }
 
 enum _shellkey_flags {
-    SHKEY_Explorer  = 0x00,
-    SHKEY_Root_HKCU = 0x01
+    SHKEY_Root_HKCU = 0x1,
+    SHKEY_Root_HKLM = 0x2,
+    SHKEY_Key_Explorer  = 0x00,
+    SHKEY_Key_Shell = 0x10,
+    SHKEY_Key_ShellNoRoam = 0x20,
+    SHKEY_Key_Classes = 0x30,
+    SHKEY_Subkey_Default = 0x0000,
+    SHKEY_Subkey_ResourceName = 0x1000,
+    SHKEY_Subkey_Handlers = 0x2000,
+    SHKEY_Subkey_Associations = 0x3000,
+    SHKEY_Subkey_Volatile = 0x4000,
+    SHKEY_Subkey_MUICache = 0x5000,
+    SHKEY_Subkey_FileExts = 0x6000
 };
 
 static void test_SHGetShellKey(void)
 {
+    static const WCHAR ShellFoldersW[] = { 'S','h','e','l','l',' ','F','o','l','d','e','r','s',0 };
+    static const WCHAR WineTestW[] = { 'W','i','n','e','T','e','s','t',0 };
+
     void *pPathBuildRootW = GetProcAddress(hShlwapi, "PathBuildRootW");
-    HKEY hkey, hkey2;
-    DWORD ret;
+    HKEY hkey;
 
     if (!pSHGetShellKey)
     {
@@ -2709,30 +2722,38 @@ static void test_SHGetShellKey(void)
         return;
     }
 
-    /* marking broken cause latest Vista+ versions fail here */
+    /* Vista+ limits SHKEY enumeration values */
     SetLastError(0xdeadbeef);
-    hkey = pSHGetShellKey(SHKEY_Explorer, NULL, FALSE);
-    ok(hkey == NULL || broken(hkey != NULL), "got %p\n", hkey);
+    hkey = pSHGetShellKey(SHKEY_Key_Explorer, ShellFoldersW, FALSE);
     if (hkey)
     {
-        hkey2 = 0;
-        ret = RegOpenKeyExA(hkey, "Shell Folders", 0, KEY_READ, &hkey2);
-        ok(ret == ERROR_SUCCESS, "got %d\n", ret);
-        ok(hkey2 != NULL, "got %p\n", hkey2);
-        RegCloseKey( hkey2 );
-        RegCloseKey( hkey );
+        /* Tests not working on Vista+ */
+        RegCloseKey(hkey);
+
+        hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Classes, NULL, FALSE);
+        ok(hkey != NULL, "hkey = NULL\n");
+        RegCloseKey(hkey);
     }
 
-    hkey = pSHGetShellKey(SHKEY_Explorer | SHKEY_Root_HKCU, NULL, FALSE);
-    ok(hkey != NULL, "got %p\n", hkey);
+    hkey = pSHGetShellKey(SHKEY_Root_HKCU|SHKEY_Key_Explorer, ShellFoldersW, FALSE);
+    ok(hkey != NULL, "hkey = NULL\n");
+    RegCloseKey(hkey);
+
+    hkey = pSHGetShellKey(SHKEY_Root_HKLM|SHKEY_Key_Explorer, ShellFoldersW, FALSE);
+    ok(hkey != NULL, "hkey = NULL\n");
+    RegCloseKey(hkey);
+
+    hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, FALSE);
+    ok(hkey == NULL, "hkey != NULL\n");
 
-    hkey2 = 0;
-    ret = RegOpenKeyExA(hkey, "Shell Folders", 0, KEY_READ, &hkey2);
-    ok(ret == ERROR_SUCCESS, "got %d\n", ret);
-    ok(hkey2 != NULL, "got %p\n", hkey2);
-    RegCloseKey( hkey2 );
+    hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, TRUE);
+    ok(hkey != NULL, "Can't create key\n");
+    RegCloseKey(hkey);
 
-    RegCloseKey( hkey );
+    hkey = pSHGetShellKey(SHKEY_Root_HKLM, NULL, FALSE);
+    ok(hkey != NULL, "Can't create key\n");
+    ok(SUCCEEDED(RegDeleteKeyW(hkey, WineTestW)), "Can't delte key\n");
+    RegCloseKey(hkey);
 }
 
 static void init_pointers(void)




More information about the wine-cvs mailing list