shcore: Add registry access helpers.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1fd60d5656
commit
6ae247bb50
|
@ -1873,3 +1873,445 @@ DWORD WINAPI SHDeleteValueA(HKEY hkey, const char *subkey, const char *value)
|
|||
CoTaskMemFree(valueW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHCopyKeyA [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHCopyKeyA(HKEY hkey_src, const char *subkey, HKEY hkey_dst, DWORD reserved)
|
||||
{
|
||||
WCHAR *subkeyW = NULL;
|
||||
DWORD ret;
|
||||
|
||||
TRACE("(%p, %s, %p, %d)\n", hkey_src, debugstr_a(subkey), hkey_dst, reserved);
|
||||
|
||||
if (subkey && FAILED(SHStrDupA(subkey, &subkeyW)))
|
||||
return 0;
|
||||
|
||||
ret = SHCopyKeyW(hkey_src, subkeyW, hkey_dst, reserved);
|
||||
CoTaskMemFree(subkeyW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHCopyKeyW [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHCopyKeyW(HKEY hkey_src, const WCHAR *subkey, HKEY hkey_dst, DWORD reserved)
|
||||
{
|
||||
DWORD key_count = 0, value_count = 0, max_key_len = 0;
|
||||
WCHAR name[MAX_PATH], *ptr_name = name;
|
||||
BYTE buff[1024], *ptr = buff;
|
||||
DWORD max_data_len = 0, i;
|
||||
DWORD ret = 0;
|
||||
|
||||
TRACE("(%p, %s, %p, %d)\n", hkey_src, debugstr_w(subkey), hkey_dst, reserved);
|
||||
|
||||
if (!hkey_dst || !hkey_src)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (subkey)
|
||||
ret = RegOpenKeyExW(hkey_src, subkey, 0, KEY_ALL_ACCESS, &hkey_src);
|
||||
|
||||
if (ret)
|
||||
hkey_src = NULL; /* Don't close this key since we didn't open it */
|
||||
else
|
||||
{
|
||||
DWORD max_value_len;
|
||||
|
||||
ret = RegQueryInfoKeyW(hkey_src, NULL, NULL, NULL, &key_count, &max_key_len,
|
||||
NULL, &value_count, &max_value_len, &max_data_len, NULL, NULL);
|
||||
if (!ret)
|
||||
{
|
||||
/* Get max size for key/value names */
|
||||
max_key_len = max(max_key_len, max_value_len);
|
||||
|
||||
if (max_key_len++ > MAX_PATH - 1)
|
||||
ptr_name = heap_alloc(max_key_len * sizeof(WCHAR));
|
||||
|
||||
if (max_data_len > sizeof(buff))
|
||||
ptr = heap_alloc(max_data_len);
|
||||
|
||||
if (!ptr_name || !ptr)
|
||||
ret = ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < key_count && !ret; i++)
|
||||
{
|
||||
HKEY hsubkey_src, hsubkey_dst;
|
||||
DWORD length = max_key_len;
|
||||
|
||||
ret = RegEnumKeyExW(hkey_src, i, ptr_name, &length, NULL, NULL, NULL, NULL);
|
||||
if (!ret)
|
||||
{
|
||||
ret = RegOpenKeyExW(hkey_src, ptr_name, 0, KEY_READ, &hsubkey_src);
|
||||
if (!ret)
|
||||
{
|
||||
/* Create destination sub key */
|
||||
ret = RegCreateKeyW(hkey_dst, ptr_name, &hsubkey_dst);
|
||||
if (!ret)
|
||||
{
|
||||
/* Recursively copy keys and values from the sub key */
|
||||
ret = SHCopyKeyW(hsubkey_src, NULL, hsubkey_dst, 0);
|
||||
RegCloseKey(hsubkey_dst);
|
||||
}
|
||||
}
|
||||
RegCloseKey(hsubkey_src);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy all the values in this key */
|
||||
for (i = 0; i < value_count && !ret; i++)
|
||||
{
|
||||
DWORD length = max_key_len, type, data_len = max_data_len;
|
||||
|
||||
ret = RegEnumValueW(hkey_src, i, ptr_name, &length, NULL, &type, ptr, &data_len);
|
||||
if (!ret) {
|
||||
ret = SHSetValueW(hkey_dst, NULL, ptr_name, type, ptr, data_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free buffers if allocated */
|
||||
if (ptr_name != name)
|
||||
heap_free(ptr_name);
|
||||
if (ptr != buff)
|
||||
heap_free(ptr);
|
||||
|
||||
if (subkey && hkey_src)
|
||||
RegCloseKey(hkey_src);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* SHEnumKeyExA [SHCORE.@]
|
||||
*/
|
||||
LONG WINAPI SHEnumKeyExA(HKEY hkey, DWORD index, char *subkey, DWORD *length)
|
||||
{
|
||||
TRACE("(%p, %d, %s, %p)\n", hkey, index, debugstr_a(subkey), length);
|
||||
|
||||
return RegEnumKeyExA(hkey, index, subkey, length, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHEnumKeyExW [SHCORE.@]
|
||||
*/
|
||||
LONG WINAPI SHEnumKeyExW(HKEY hkey, DWORD index, WCHAR *subkey, DWORD *length)
|
||||
{
|
||||
TRACE("(%p, %d, %s, %p)\n", hkey, index, debugstr_w(subkey), length);
|
||||
|
||||
return RegEnumKeyExW(hkey, index, subkey, length, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHEnumValueA [SHCORE.@]
|
||||
*/
|
||||
LONG WINAPI SHEnumValueA(HKEY hkey, DWORD index, char *value, DWORD *length, DWORD *type,
|
||||
void *data, DWORD *data_len)
|
||||
{
|
||||
TRACE("(%p, %d, %s, %p, %p, %p, %p)\n", hkey, index, debugstr_a(value), length, type, data, data_len);
|
||||
|
||||
return RegEnumValueA(hkey, index, value, length, NULL, type, data, data_len);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHEnumValueW [SHCORE.@]
|
||||
*/
|
||||
LONG WINAPI SHEnumValueW(HKEY hkey, DWORD index, WCHAR *value, DWORD *length, DWORD *type,
|
||||
void *data, DWORD *data_len)
|
||||
{
|
||||
TRACE("(%p, %d, %s, %p, %p, %p, %p)\n", hkey, index, debugstr_w(value), length, type, data, data_len);
|
||||
|
||||
return RegEnumValueW(hkey, index, value, length, NULL, type, data, data_len);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHQueryValueExW [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHQueryValueExW(HKEY hkey, const WCHAR *name, DWORD *reserved, DWORD *type,
|
||||
void *buff, DWORD *buff_len)
|
||||
{
|
||||
DWORD ret, value_type, data_len = 0;
|
||||
|
||||
TRACE("(%p, %s, %p, %p, %p, %p)\n", hkey, debugstr_w(name), reserved, type, buff, buff_len);
|
||||
|
||||
if (buff_len)
|
||||
data_len = *buff_len;
|
||||
|
||||
ret = RegQueryValueExW(hkey, name, reserved, &value_type, buff, &data_len);
|
||||
if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)
|
||||
return ret;
|
||||
|
||||
if (buff_len && value_type == REG_EXPAND_SZ)
|
||||
{
|
||||
DWORD length;
|
||||
WCHAR *value;
|
||||
|
||||
if (!buff || ret == ERROR_MORE_DATA)
|
||||
{
|
||||
length = data_len;
|
||||
value = heap_alloc(length);
|
||||
RegQueryValueExW(hkey, name, reserved, NULL, (BYTE *)value, &length);
|
||||
length = ExpandEnvironmentStringsW(value, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = (strlenW(buff) + 1) * sizeof(WCHAR);
|
||||
value = heap_alloc(length);
|
||||
memcpy(value, buff, length);
|
||||
length = ExpandEnvironmentStringsW(value, buff, *buff_len / sizeof(WCHAR));
|
||||
if (length > *buff_len) ret = ERROR_MORE_DATA;
|
||||
}
|
||||
data_len = max(data_len, length);
|
||||
heap_free(value);
|
||||
}
|
||||
|
||||
if (type)
|
||||
*type = value_type == REG_EXPAND_SZ ? REG_SZ : value_type;
|
||||
if (buff_len)
|
||||
*buff_len = data_len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHQueryValueExA [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHQueryValueExA(HKEY hkey, const char *name, DWORD *reserved, DWORD *type,
|
||||
void *buff, DWORD *buff_len)
|
||||
{
|
||||
DWORD ret, value_type, data_len = 0;
|
||||
|
||||
TRACE("(%p, %s, %p, %p, %p, %p)\n", hkey, debugstr_a(name), reserved, type, buff, buff_len);
|
||||
|
||||
if (buff_len)
|
||||
data_len = *buff_len;
|
||||
|
||||
ret = RegQueryValueExA(hkey, name, reserved, &value_type, buff, &data_len);
|
||||
if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)
|
||||
return ret;
|
||||
|
||||
if (buff_len && value_type == REG_EXPAND_SZ)
|
||||
{
|
||||
DWORD length;
|
||||
char *value;
|
||||
|
||||
if (!buff || ret == ERROR_MORE_DATA)
|
||||
{
|
||||
length = data_len;
|
||||
value = heap_alloc(length);
|
||||
RegQueryValueExA(hkey, name, reserved, NULL, (BYTE *)value, &length);
|
||||
length = ExpandEnvironmentStringsA(value, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
length = strlen(buff) + 1;
|
||||
value = heap_alloc(length);
|
||||
memcpy(value, buff, length);
|
||||
length = ExpandEnvironmentStringsA(value, buff, *buff_len);
|
||||
if (length > *buff_len) ret = ERROR_MORE_DATA;
|
||||
}
|
||||
data_len = max(data_len, length);
|
||||
heap_free(value);
|
||||
}
|
||||
|
||||
if (type)
|
||||
*type = value_type == REG_EXPAND_SZ ? REG_SZ : value_type;
|
||||
if (buff_len)
|
||||
*buff_len = data_len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHGetValueA [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHGetValueA(HKEY hkey, const char *subkey, const char *value,
|
||||
DWORD *type, void *data, DWORD *data_len)
|
||||
{
|
||||
HKEY hsubkey = 0;
|
||||
DWORD ret = 0;
|
||||
|
||||
TRACE("(%p, %s, %s, %p, %p, %p)\n", hkey, debugstr_a(subkey), debugstr_a(value),
|
||||
type, data, data_len);
|
||||
|
||||
if (subkey)
|
||||
ret = RegOpenKeyExA(hkey, subkey, 0, KEY_QUERY_VALUE, &hsubkey);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
ret = SHQueryValueExA(hsubkey ? hsubkey : hkey, value, 0, type, data, data_len);
|
||||
if (subkey)
|
||||
RegCloseKey(hsubkey);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHGetValueW [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHGetValueW(HKEY hkey, const WCHAR *subkey, const WCHAR *value,
|
||||
DWORD *type, void *data, DWORD *data_len)
|
||||
{
|
||||
HKEY hsubkey = 0;
|
||||
DWORD ret = 0;
|
||||
|
||||
TRACE("(%p, %s, %s, %p, %p, %p)\n", hkey, debugstr_w(subkey), debugstr_w(value),
|
||||
type, data, data_len);
|
||||
|
||||
if (subkey)
|
||||
ret = RegOpenKeyExW(hkey, subkey, 0, KEY_QUERY_VALUE, &hsubkey);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
ret = SHQueryValueExW(hsubkey ? hsubkey : hkey, value, 0, type, data, data_len);
|
||||
if (subkey)
|
||||
RegCloseKey(hsubkey);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHRegGetIntW [SHCORE.280]
|
||||
*/
|
||||
int WINAPI SHRegGetIntW(HKEY hkey, const WCHAR *value, int default_value)
|
||||
{
|
||||
WCHAR buff[32];
|
||||
DWORD buff_len;
|
||||
|
||||
TRACE("(%p, %s, %d)\n", hkey, debugstr_w(value), default_value);
|
||||
|
||||
buff[0] = 0;
|
||||
buff_len = sizeof(buff);
|
||||
if (SHQueryValueExW(hkey, value, 0, 0, buff, &buff_len))
|
||||
return default_value;
|
||||
|
||||
if (*buff >= '0' && *buff <= '9')
|
||||
return atoiW(buff);
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHRegGetPathA [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHRegGetPathA(HKEY hkey, const char *subkey, const char *value, char *path, DWORD flags)
|
||||
{
|
||||
DWORD length = MAX_PATH;
|
||||
|
||||
TRACE("(%p, %s, %s, %p, %#x)\n", hkey, debugstr_a(subkey), debugstr_a(value), path, flags);
|
||||
|
||||
return SHGetValueA(hkey, subkey, value, 0, path, &length);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHRegGetPathW [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHRegGetPathW(HKEY hkey, const WCHAR *subkey, const WCHAR *value, WCHAR *path, DWORD flags)
|
||||
{
|
||||
DWORD length = MAX_PATH;
|
||||
|
||||
TRACE("(%p, %s, %s, %p, %d)\n", hkey, debugstr_w(subkey), debugstr_w(value), path, flags);
|
||||
|
||||
return SHGetValueW(hkey, subkey, value, 0, path, &length);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHSetValueW [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHSetValueW(HKEY hkey, const WCHAR *subkey, const WCHAR *value, DWORD type,
|
||||
const void *data, DWORD data_len)
|
||||
{
|
||||
DWORD ret = ERROR_SUCCESS, dummy;
|
||||
HKEY hsubkey;
|
||||
|
||||
TRACE("(%p, %s, %s, %d, %p, %d)\n", hkey, debugstr_w(subkey), debugstr_w(value),
|
||||
type, data, data_len);
|
||||
|
||||
if (subkey && *subkey)
|
||||
ret = RegCreateKeyExW(hkey, subkey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hsubkey, &dummy);
|
||||
else
|
||||
hsubkey = hkey;
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
ret = RegSetValueExW(hsubkey, value, 0, type, data, data_len);
|
||||
if (hsubkey != hkey)
|
||||
RegCloseKey(hsubkey);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHSetValueA [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHSetValueA(HKEY hkey, const char *subkey, const char *value,
|
||||
DWORD type, const void *data, DWORD data_len)
|
||||
{
|
||||
DWORD ret = ERROR_SUCCESS, dummy;
|
||||
HKEY hsubkey;
|
||||
|
||||
TRACE("(%p, %s, %s, %d, %p, %d)\n", hkey, debugstr_a(subkey), debugstr_a(value),
|
||||
type, data, data_len);
|
||||
|
||||
if (subkey && *subkey)
|
||||
ret = RegCreateKeyExA(hkey, subkey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hsubkey, &dummy);
|
||||
else
|
||||
hsubkey = hkey;
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
ret = RegSetValueExA(hsubkey, value, 0, type, data, data_len);
|
||||
if (hsubkey != hkey)
|
||||
RegCloseKey(hsubkey);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHRegSetPathA [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHRegSetPathA(HKEY hkey, const char *subkey, const char *value, const char *path, DWORD flags)
|
||||
{
|
||||
FIXME("(%p, %s, %s, %p, %#x) - semi-stub\n", hkey, debugstr_a(subkey),
|
||||
debugstr_a(value), debugstr_a(path), flags);
|
||||
|
||||
/* FIXME: PathUnExpandEnvStringsA() */
|
||||
|
||||
return SHSetValueA(hkey, subkey, value, REG_SZ, path, lstrlenA(path));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHRegSetPathW [SHCORE.@]
|
||||
*/
|
||||
DWORD WINAPI SHRegSetPathW(HKEY hkey, const WCHAR *subkey, const WCHAR *value, const WCHAR *path, DWORD flags)
|
||||
{
|
||||
FIXME("(%p, %s, %s, %s, %#x) - semi-stub\n", hkey, debugstr_w(subkey),
|
||||
debugstr_w(value), debugstr_w(path), flags);
|
||||
|
||||
/* FIXME: PathUnExpandEnvStringsW(); */
|
||||
|
||||
return SHSetValueW(hkey, subkey, value, REG_SZ, path, lstrlenW(path));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHQueryInfoKeyA [SHCORE.@]
|
||||
*/
|
||||
LONG WINAPI SHQueryInfoKeyA(HKEY hkey, DWORD *subkeys, DWORD *subkey_max, DWORD *values, DWORD *value_max)
|
||||
{
|
||||
TRACE("(%p, %p, %p, %p, %p)\n", hkey, subkeys, subkey_max, values, value_max);
|
||||
|
||||
return RegQueryInfoKeyA(hkey, NULL, NULL, NULL, subkeys, subkey_max, NULL, values, value_max, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHQueryInfoKeyW [SHCORE.@]
|
||||
*/
|
||||
LONG WINAPI SHQueryInfoKeyW(HKEY hkey, DWORD *subkeys, DWORD *subkey_max, DWORD *values, DWORD *value_max)
|
||||
{
|
||||
TRACE("(%p, %p, %p, %p, %p)\n", hkey, subkeys, subkey_max, values, value_max);
|
||||
|
||||
return RegQueryInfoKeyW(hkey, NULL, NULL, NULL, subkeys, subkey_max, NULL, values, value_max, NULL, NULL, NULL);
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
@ stub RevokeScaleChangeNotifications
|
||||
@ stdcall SHAnsiToAnsi(str ptr long)
|
||||
@ stdcall SHAnsiToUnicode(str ptr long)
|
||||
@ stdcall SHCopyKeyA(long str long long) shlwapi.SHCopyKeyA
|
||||
@ stdcall SHCopyKeyW(long wstr long long) shlwapi.SHCopyKeyW
|
||||
@ stdcall SHCopyKeyA(long str long long)
|
||||
@ stdcall SHCopyKeyW(long wstr long long)
|
||||
@ stdcall SHCreateMemStream(ptr long)
|
||||
@ stdcall SHCreateStreamOnFileA(str long ptr)
|
||||
@ stdcall SHCreateStreamOnFileEx(wstr long long long ptr ptr)
|
||||
|
@ -46,33 +46,33 @@
|
|||
@ stdcall SHDeleteKeyW(long wstr)
|
||||
@ stdcall SHDeleteValueA(long str str)
|
||||
@ stdcall SHDeleteValueW(long wstr wstr)
|
||||
@ stdcall SHEnumKeyExA(long long str ptr) shlwapi.SHEnumKeyExA
|
||||
@ stdcall SHEnumKeyExW(long long wstr ptr) shlwapi.SHEnumKeyExW
|
||||
@ stdcall SHEnumValueA(long long str ptr ptr ptr ptr) shlwapi.SHEnumValueA
|
||||
@ stdcall SHEnumValueW(long long wstr ptr ptr ptr ptr) shlwapi.SHEnumValueW
|
||||
@ stdcall SHEnumKeyExA(long long str ptr)
|
||||
@ stdcall SHEnumKeyExW(long long wstr ptr)
|
||||
@ stdcall SHEnumValueA(long long str ptr ptr ptr ptr)
|
||||
@ stdcall SHEnumValueW(long long wstr ptr ptr ptr ptr)
|
||||
@ stdcall SHGetThreadRef(ptr)
|
||||
@ stdcall SHGetValueA( long str str ptr ptr ptr ) shlwapi.SHGetValueA
|
||||
@ stdcall SHGetValueW( long wstr wstr ptr ptr ptr ) shlwapi.SHGetValueW
|
||||
@ stdcall SHGetValueA(long str str ptr ptr ptr)
|
||||
@ stdcall SHGetValueW(long wstr wstr ptr ptr ptr)
|
||||
@ stdcall SHOpenRegStream2A(long str str long)
|
||||
@ stdcall SHOpenRegStream2W(long wstr wstr long)
|
||||
@ stdcall SHOpenRegStreamA(long str str long)
|
||||
@ stdcall SHOpenRegStreamW(long wstr wstr long)
|
||||
@ stdcall SHQueryInfoKeyA(long ptr ptr ptr ptr) shlwapi.SHQueryInfoKeyA
|
||||
@ stdcall SHQueryInfoKeyW(long ptr ptr ptr ptr) shlwapi.SHQueryInfoKeyW
|
||||
@ stdcall SHQueryValueExA(long str ptr ptr ptr ptr) shlwapi.SHQueryValueExA
|
||||
@ stdcall SHQueryValueExW(long wstr ptr ptr ptr ptr) shlwapi.SHQueryValueExW
|
||||
@ stdcall SHQueryInfoKeyA(long ptr ptr ptr ptr)
|
||||
@ stdcall SHQueryInfoKeyW(long ptr ptr ptr ptr)
|
||||
@ stdcall SHQueryValueExA(long str ptr ptr ptr ptr)
|
||||
@ stdcall SHQueryValueExW(long wstr ptr ptr ptr ptr)
|
||||
@ stdcall SHRegDuplicateHKey(long)
|
||||
@ stdcall SHRegGetIntW(ptr wstr long) shlwapi.SHRegGetIntW
|
||||
@ stdcall SHRegGetPathA(long str str ptr long) shlwapi.SHRegGetPathA
|
||||
@ stdcall SHRegGetPathW(long wstr wstr ptr long) shlwapi.SHRegGetPathW
|
||||
@ stdcall SHRegGetValueA( long str str long ptr ptr ptr ) shlwapi.SHRegGetValueA
|
||||
@ stdcall SHRegGetValueW( long wstr wstr long ptr ptr ptr ) shlwapi.SHRegGetValueW
|
||||
@ stdcall SHRegSetPathA(long str str str long) shlwapi.SHRegSetPathA
|
||||
@ stdcall SHRegSetPathW(long wstr wstr wstr long) shlwapi.SHRegSetPathW
|
||||
@ stdcall SHRegGetIntW(ptr wstr long)
|
||||
@ stdcall SHRegGetPathA(long str str ptr long)
|
||||
@ stdcall SHRegGetPathW(long wstr wstr ptr long)
|
||||
@ stdcall SHRegGetValueA(long str str long ptr ptr ptr) advapi32.RegGetValueA
|
||||
@ stdcall SHRegGetValueW(long wstr wstr long ptr ptr ptr) advapi32.RegGetValueW
|
||||
@ stdcall SHRegSetPathA(long str str str long)
|
||||
@ stdcall SHRegSetPathW(long wstr wstr wstr long)
|
||||
@ stdcall SHReleaseThreadRef()
|
||||
@ stdcall SHSetThreadRef(ptr)
|
||||
@ stdcall SHSetValueA(long str str long ptr long) shlwapi.SHSetValueA
|
||||
@ stdcall SHSetValueW(long wstr wstr long ptr long) shlwapi.SHSetValueW
|
||||
@ stdcall SHSetValueA(long str str long ptr long)
|
||||
@ stdcall SHSetValueW(long wstr wstr long ptr long)
|
||||
@ stdcall SHStrDupA(str ptr)
|
||||
@ stdcall SHStrDupW(wstr ptr)
|
||||
@ stdcall SHUnicodeToAnsi(wstr ptr ptr)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <windows.h>
|
||||
#include "initguid.h"
|
||||
#include "objidl.h"
|
||||
#include "shlwapi.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
|
@ -35,6 +36,26 @@ static int (WINAPI *pSHAnsiToAnsi)(const char *, char *, int);
|
|||
static int (WINAPI *pSHUnicodeToUnicode)(const WCHAR *, WCHAR *, int);
|
||||
static HKEY (WINAPI *pSHRegDuplicateHKey)(HKEY);
|
||||
static DWORD (WINAPI *pSHDeleteKeyA)(HKEY, const char *);
|
||||
static DWORD (WINAPI *pSHGetValueA)(HKEY, const char *, const char *, DWORD *, void *, DWORD *);
|
||||
static LSTATUS (WINAPI *pSHRegGetValueA)(HKEY, const char *, const char *, SRRF, DWORD *, void *, DWORD *);
|
||||
static DWORD (WINAPI *pSHQueryValueExA)(HKEY, const char *, DWORD *, DWORD *, void *buff, DWORD *buff_len);
|
||||
static DWORD (WINAPI *pSHRegGetPathA)(HKEY, const char *, const char *, char *, DWORD);
|
||||
static DWORD (WINAPI *pSHCopyKeyA)(HKEY, const char *, HKEY, DWORD);
|
||||
|
||||
/* Keys used for testing */
|
||||
#define REG_TEST_KEY "Software\\Wine\\Test"
|
||||
#define REG_CURRENT_VERSION "Software\\Microsoft\\Windows\\CurrentVersion\\explorer"
|
||||
|
||||
static const char test_path1[] = "%LONGSYSTEMVAR%\\subdir1";
|
||||
static const char test_path2[] = "%FOO%\\subdir1";
|
||||
|
||||
static const char * test_envvar1 = "bar";
|
||||
static const char * test_envvar2 = "ImARatherLongButIndeedNeededString";
|
||||
static char test_exp_path1[MAX_PATH];
|
||||
static char test_exp_path2[MAX_PATH];
|
||||
static DWORD exp_len1;
|
||||
static DWORD exp_len2;
|
||||
static const char * initial_buffer ="0123456789";
|
||||
|
||||
static void init(HMODULE hshcore)
|
||||
{
|
||||
|
@ -47,6 +68,11 @@ static void init(HMODULE hshcore)
|
|||
X(SHUnicodeToUnicode);
|
||||
X(SHRegDuplicateHKey);
|
||||
X(SHDeleteKeyA);
|
||||
X(SHGetValueA);
|
||||
X(SHRegGetValueA);
|
||||
X(SHQueryValueExA);
|
||||
X(SHRegGetPathA);
|
||||
X(SHCopyKeyA);
|
||||
#undef X
|
||||
}
|
||||
|
||||
|
@ -343,6 +369,308 @@ static void test_SHDeleteKey(void)
|
|||
ok(!ret, "Failed to delete a key, %d.\n", ret);
|
||||
}
|
||||
|
||||
static HKEY create_test_entries(void)
|
||||
{
|
||||
HKEY hKey;
|
||||
DWORD ret;
|
||||
DWORD nExpectedLen1, nExpectedLen2;
|
||||
|
||||
SetEnvironmentVariableA("LONGSYSTEMVAR", test_envvar1);
|
||||
SetEnvironmentVariableA("FOO", test_envvar2);
|
||||
|
||||
ret = RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEY, &hKey);
|
||||
ok(!ret, "RegCreateKeyA failed, ret=%u\n", ret);
|
||||
|
||||
if (hKey)
|
||||
{
|
||||
ok(!RegSetValueExA(hKey, "Test1", 0, REG_EXPAND_SZ, (BYTE *)test_path1, strlen(test_path1)+1), "RegSetValueExA failed\n");
|
||||
ok(!RegSetValueExA(hKey, "Test2", 0, REG_SZ, (BYTE *)test_path1, strlen(test_path1)+1), "RegSetValueExA failed\n");
|
||||
ok(!RegSetValueExA(hKey, "Test3", 0, REG_EXPAND_SZ, (BYTE *)test_path2, strlen(test_path2)+1), "RegSetValueExA failed\n");
|
||||
}
|
||||
|
||||
exp_len1 = ExpandEnvironmentStringsA(test_path1, test_exp_path1, sizeof(test_exp_path1));
|
||||
exp_len2 = ExpandEnvironmentStringsA(test_path2, test_exp_path2, sizeof(test_exp_path2));
|
||||
|
||||
nExpectedLen1 = strlen(test_path1) - strlen("%LONGSYSTEMVAR%") + strlen(test_envvar1) + 1;
|
||||
nExpectedLen2 = strlen(test_path2) - strlen("%FOO%") + strlen(test_envvar2) + 1;
|
||||
|
||||
/* Make sure we carry on with correct values */
|
||||
exp_len1 = nExpectedLen1;
|
||||
exp_len2 = nExpectedLen2;
|
||||
|
||||
return hKey;
|
||||
}
|
||||
|
||||
/* delete key and all its subkeys */
|
||||
static DWORD delete_key( HKEY hkey, LPCSTR parent, LPCSTR keyname )
|
||||
{
|
||||
HKEY parentKey;
|
||||
DWORD ret;
|
||||
|
||||
RegCloseKey(hkey);
|
||||
|
||||
/* open the parent of the key to close */
|
||||
ret = RegOpenKeyExA( HKEY_CURRENT_USER, parent, 0, KEY_ALL_ACCESS, &parentKey);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
return ret;
|
||||
|
||||
ret = pSHDeleteKeyA( parentKey, keyname );
|
||||
RegCloseKey(parentKey);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void test_SHGetValue(void)
|
||||
{
|
||||
DWORD size;
|
||||
DWORD type;
|
||||
DWORD ret;
|
||||
char buf[MAX_PATH];
|
||||
|
||||
HKEY hkey = create_test_entries();
|
||||
|
||||
strcpy(buf, initial_buffer);
|
||||
size = MAX_PATH;
|
||||
type = -1;
|
||||
ret = pSHGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", &type, buf, &size);
|
||||
ok(!ret, "Failed to get value, ret %u.\n", ret);
|
||||
|
||||
ok(!strcmp(test_exp_path1, buf), "Unexpected value %s.\n", buf);
|
||||
ok(type == REG_SZ, "Unexpected value type %d.\n", type);
|
||||
|
||||
strcpy(buf, initial_buffer);
|
||||
size = MAX_PATH;
|
||||
type = -1;
|
||||
ret = pSHGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", &type, buf, &size);
|
||||
ok(!ret, "Failed to get value, ret %u.\n", ret);
|
||||
ok(!strcmp(test_path1, buf), "Unexpected value %s.\n", buf);
|
||||
ok(type == REG_SZ, "Unexpected value type %d.\n", type);
|
||||
|
||||
delete_key(hkey, "Software\\Wine", "Test");
|
||||
}
|
||||
|
||||
static void test_SHRegGetValue(void)
|
||||
{
|
||||
LSTATUS ret;
|
||||
DWORD size, type;
|
||||
char data[MAX_PATH];
|
||||
|
||||
HKEY hkey = create_test_entries();
|
||||
|
||||
size = MAX_PATH;
|
||||
ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", SRRF_RT_REG_EXPAND_SZ, &type, data, &size);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SHRegGetValue failed, ret=%u\n", ret);
|
||||
|
||||
size = MAX_PATH;
|
||||
ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", SRRF_RT_REG_SZ, &type, data, &size);
|
||||
ok(ret == ERROR_SUCCESS, "SHRegGetValue failed, ret=%u\n", ret);
|
||||
ok(!strcmp(data, test_exp_path1), "data = %s, expected %s\n", data, test_exp_path1);
|
||||
ok(type == REG_SZ, "type = %d, expected REG_SZ\n", type);
|
||||
|
||||
size = MAX_PATH;
|
||||
ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", SRRF_RT_REG_DWORD, &type, data, &size);
|
||||
ok(ret == ERROR_UNSUPPORTED_TYPE, "SHRegGetValue failed, ret=%u\n", ret);
|
||||
|
||||
size = MAX_PATH;
|
||||
ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", SRRF_RT_REG_EXPAND_SZ, &type, data, &size);
|
||||
ok(ret == ERROR_INVALID_PARAMETER, "SHRegGetValue failed, ret=%u\n", ret);
|
||||
|
||||
size = MAX_PATH;
|
||||
ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", SRRF_RT_REG_SZ, &type, data, &size);
|
||||
ok(ret == ERROR_SUCCESS, "SHRegGetValue failed, ret=%u\n", ret);
|
||||
ok(!strcmp(data, test_path1), "data = %s, expected %s\n", data, test_path1);
|
||||
ok(type == REG_SZ, "type = %d, expected REG_SZ\n", type);
|
||||
|
||||
size = MAX_PATH;
|
||||
ret = pSHRegGetValueA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test2", SRRF_RT_REG_QWORD, &type, data, &size);
|
||||
ok(ret == ERROR_UNSUPPORTED_TYPE, "SHRegGetValue failed, ret=%u\n", ret);
|
||||
|
||||
delete_key(hkey, "Software\\Wine", "Test");
|
||||
}
|
||||
|
||||
static void test_SHQueryValueEx(void)
|
||||
{
|
||||
DWORD buffer_len1,buffer_len2;
|
||||
DWORD ret, type, size;
|
||||
char buf[MAX_PATH];
|
||||
HKEY hKey, testkey;
|
||||
|
||||
testkey = create_test_entries();
|
||||
|
||||
ret = RegOpenKeyExA(HKEY_CURRENT_USER, REG_TEST_KEY, 0, KEY_QUERY_VALUE, &hKey);
|
||||
ok(!ret, "Failed to open a key, ret %u.\n", ret);
|
||||
|
||||
/****** SHQueryValueExA ******/
|
||||
|
||||
buffer_len1 = max(strlen(test_exp_path1)+1, strlen(test_path1)+1);
|
||||
buffer_len2 = max(strlen(test_exp_path2)+1, strlen(test_path2)+1);
|
||||
|
||||
/*
|
||||
* Case 1.1 All arguments are NULL
|
||||
*/
|
||||
ret = pSHQueryValueExA( hKey, "Test1", NULL, NULL, NULL, NULL);
|
||||
ok(!ret, "Failed to query value, ret %u.\n", ret);
|
||||
|
||||
/*
|
||||
* Case 1.2 dwType is set
|
||||
*/
|
||||
type = -1;
|
||||
ret = pSHQueryValueExA( hKey, "Test1", NULL, &type, NULL, NULL);
|
||||
ok(!ret, "Failed to query value, ret %u.\n", ret);
|
||||
ok(type == REG_SZ, "Expected REG_SZ, got (%u)\n", type);
|
||||
|
||||
size = 6;
|
||||
ret = pSHQueryValueExA( hKey, "Test1", NULL, NULL, NULL, &size);
|
||||
ok(!ret, "Failed to query value, ret %u.\n", ret);
|
||||
ok(size == buffer_len1, "Buffer sizes (%u) and (%u) are not equal\n", size, buffer_len1);
|
||||
|
||||
/*
|
||||
* Expanded > unexpanded
|
||||
*/
|
||||
size = 6;
|
||||
ret = pSHQueryValueExA( hKey, "Test3", NULL, NULL, NULL, &size);
|
||||
ok(!ret, "Failed to query value, ret %u.\n", ret);
|
||||
ok(size >= buffer_len2, "Buffer size (%u) should be >= (%u)\n", size, buffer_len2);
|
||||
|
||||
/*
|
||||
* Case 1 string shrinks during expanding
|
||||
*/
|
||||
strcpy(buf, initial_buffer);
|
||||
size = 6;
|
||||
type = -1;
|
||||
ret = pSHQueryValueExA( hKey, "Test1", NULL, &type, buf, &size);
|
||||
ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got (%u)\n", ret);
|
||||
ok(!strcmp(initial_buffer, buf), "Comparing (%s) with (%s) failed\n", buf, initial_buffer);
|
||||
ok(size == buffer_len1, "Buffer sizes (%u) and (%u) are not equal\n", size, buffer_len1);
|
||||
ok(type == REG_SZ, "Expected REG_SZ, got (%u)\n", type);
|
||||
|
||||
/*
|
||||
* string grows during expanding
|
||||
* dwSize is smaller than the size of the unexpanded string
|
||||
*/
|
||||
strcpy(buf, initial_buffer);
|
||||
size = 6;
|
||||
type = -1;
|
||||
ret = pSHQueryValueExA( hKey, "Test3", NULL, &type, buf, &size);
|
||||
ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got (%u)\n", ret);
|
||||
ok(!strcmp(initial_buffer, buf), "Comparing (%s) with (%s) failed\n", buf, initial_buffer);
|
||||
ok(size >= buffer_len2, "Buffer size (%u) should be >= (%u)\n", size, buffer_len2);
|
||||
ok(type == REG_SZ, "Expected REG_SZ, got (%u)\n", type);
|
||||
|
||||
/*
|
||||
* string grows during expanding
|
||||
* dwSize is larger than the size of the unexpanded string, but
|
||||
* smaller than the part before the backslash. If the unexpanded
|
||||
* string fits into the buffer, it can get cut when expanded.
|
||||
*/
|
||||
strcpy(buf, initial_buffer);
|
||||
size = strlen(test_envvar2) - 2;
|
||||
type = -1;
|
||||
ret = pSHQueryValueExA(hKey, "Test3", NULL, &type, buf, &size);
|
||||
ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got (%u)\n", ret);
|
||||
|
||||
todo_wine
|
||||
{
|
||||
ok(!strcmp("", buf), "Unexpanded string %s.\n", buf);
|
||||
}
|
||||
|
||||
ok(size >= buffer_len2, "Buffer size (%u) should be >= (%u)\n", size, buffer_len2);
|
||||
ok(type == REG_SZ, "Expected REG_SZ, got (%u)\n", type);
|
||||
|
||||
/*
|
||||
* string grows during expanding
|
||||
* dwSize is larger than the size of the part before the backslash,
|
||||
* but smaller than the expanded string. If the unexpanded string fits
|
||||
* into the buffer, it can get cut when expanded.
|
||||
*/
|
||||
strcpy(buf, initial_buffer);
|
||||
size = exp_len2 - 4;
|
||||
type = -1;
|
||||
ret = pSHQueryValueExA( hKey, "Test3", NULL, &type, buf, &size);
|
||||
ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got (%u)\n", ret);
|
||||
|
||||
todo_wine
|
||||
{
|
||||
ok( (0 == strcmp("", buf)) || (0 == strcmp(test_envvar2, buf)),
|
||||
"Expected empty or first part of the string \"%s\", got \"%s\"\n", test_envvar2, buf);
|
||||
}
|
||||
|
||||
ok(size >= buffer_len2, "Buffer size (%u) should be >= (%u)\n", size, buffer_len2);
|
||||
ok(type == REG_SZ, "Expected REG_SZ, got (%u)\n", type);
|
||||
|
||||
/*
|
||||
* The buffer is NULL but the size is set
|
||||
*/
|
||||
strcpy(buf, initial_buffer);
|
||||
size = 6;
|
||||
type = -1;
|
||||
ret = pSHQueryValueExA( hKey, "Test3", NULL, &type, NULL, &size);
|
||||
ok(!ret, "Failed to query value, ret %u.\n", ret);
|
||||
ok(size >= buffer_len2, "Buffer size (%u) should be >= (%u)\n", size, buffer_len2);
|
||||
ok(type == REG_SZ, "Expected REG_SZ, got (%u)\n", type);
|
||||
|
||||
RegCloseKey(hKey);
|
||||
|
||||
delete_key(testkey, "Software\\Wine", "Test");
|
||||
}
|
||||
|
||||
static void test_SHRegGetPath(void)
|
||||
{
|
||||
char buf[MAX_PATH];
|
||||
DWORD ret;
|
||||
HKEY hkey;
|
||||
|
||||
hkey = create_test_entries();
|
||||
|
||||
strcpy(buf, initial_buffer);
|
||||
ret = pSHRegGetPathA(HKEY_CURRENT_USER, REG_TEST_KEY, "Test1", buf, 0);
|
||||
ok(!ret, "Failed to get path, ret %u.\n", ret);
|
||||
ok(!strcmp(test_exp_path1, buf), "Unexpected path %s.\n", buf);
|
||||
|
||||
delete_key(hkey, "Software\\Wine", "Test");
|
||||
}
|
||||
|
||||
static void test_SHCopyKey(void)
|
||||
{
|
||||
HKEY hKeySrc, hKeyDst;
|
||||
DWORD ret;
|
||||
|
||||
HKEY hkey = create_test_entries();
|
||||
|
||||
/* Delete existing destination sub keys */
|
||||
hKeyDst = NULL;
|
||||
if (!RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination", &hKeyDst) && hKeyDst)
|
||||
{
|
||||
pSHDeleteKeyA(hKeyDst, NULL);
|
||||
RegCloseKey(hKeyDst);
|
||||
}
|
||||
|
||||
hKeyDst = NULL;
|
||||
ret = RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination", &hKeyDst);
|
||||
ok(!ret, "Failed to create a test key, ret %d.\n", ret);
|
||||
|
||||
hKeySrc = NULL;
|
||||
ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, REG_CURRENT_VERSION, &hKeySrc);
|
||||
ok(!ret, "Failed to open a test key, ret %d.\n", ret);
|
||||
|
||||
ret = pSHCopyKeyA(hKeySrc, NULL, hKeyDst, 0);
|
||||
ok(!ret, "Copy failed, ret=(%u)\n", ret);
|
||||
|
||||
RegCloseKey(hKeySrc);
|
||||
RegCloseKey(hKeyDst);
|
||||
|
||||
/* Check we copied the sub keys, i.e. something that's on every windows system (including Wine) */
|
||||
hKeyDst = NULL;
|
||||
ret = RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_KEY "\\CopyDestination\\Shell Folders", &hKeyDst);
|
||||
ok(!ret, "Failed to open a test key, ret %d.\n", ret);
|
||||
|
||||
/* And the we copied the values too */
|
||||
ok(!pSHQueryValueExA(hKeyDst, "Common AppData", NULL, NULL, NULL, NULL), "SHQueryValueExA failed\n");
|
||||
|
||||
RegCloseKey(hKeyDst);
|
||||
delete_key( hkey, "Software\\Wine", "Test" );
|
||||
}
|
||||
|
||||
START_TEST(shcore)
|
||||
{
|
||||
HMODULE hshcore = LoadLibraryA("shcore.dll");
|
||||
|
@ -362,4 +690,9 @@ START_TEST(shcore)
|
|||
test_SHUnicodeToUnicode();
|
||||
test_SHRegDuplicateHKey();
|
||||
test_SHDeleteKey();
|
||||
test_SHGetValue();
|
||||
test_SHRegGetValue();
|
||||
test_SHQueryValueEx();
|
||||
test_SHRegGetPath();
|
||||
test_SHCopyKey();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue