shlwapi: Improved SHGetShellKey implementation.

This commit is contained in:
Piotr Caban 2010-10-12 16:35:35 +02:00 committed by Alexandre Julliard
parent b66e6d5cc4
commit c2f25a2206
2 changed files with 158 additions and 38 deletions

View File

@ -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;
}

View File

@ -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)