shlwapi: Improved SHGetShellKey implementation.
This commit is contained in:
parent
b66e6d5cc4
commit
c2f25a2206
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue