From c2f25a2206d4786888fbd2191952cf3d80da6689 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Tue, 12 Oct 2010 16:35:35 +0200 Subject: [PATCH] shlwapi: Improved SHGetShellKey implementation. --- dlls/shlwapi/ordinal.c | 131 ++++++++++++++++++++++++++++++----- dlls/shlwapi/tests/ordinal.c | 65 +++++++++++------ 2 files changed, 158 insertions(+), 38 deletions(-) diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c index 3edb11609a2..63fffb2ea8f 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: - return NULL; 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); - else - RegOpenKeyExW(hroot, sub_key, 0, MAXIMUM_ALLOWED, &hkey); + 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 NULL; + } - RegCloseKey(hroot); + 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((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, + path, 0, MAXIMUM_ALLOWED, &hkey); + + HeapFree(GetProcessHeap(), 0, path); return hkey; } diff --git a/dlls/shlwapi/tests/ordinal.c b/dlls/shlwapi/tests/ordinal.c index dfee9bf5e69..1937cb0ce53 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); - 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|SHKEY_Key_Explorer, ShellFoldersW, FALSE); + ok(hkey != NULL, "hkey = NULL\n"); + RegCloseKey(hkey); - RegCloseKey( hkey ); + hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, FALSE); + ok(hkey == NULL, "hkey != NULL\n"); + + hkey = pSHGetShellKey(SHKEY_Root_HKLM, WineTestW, TRUE); + ok(hkey != NULL, "Can't create key\n"); + 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)