Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/shcore/main.c | 110 +++++++++++++++++++++++++++++++++++++ dlls/shcore/shcore.spec | 12 ++-- dlls/shcore/tests/shcore.c | 25 +++++++++ 3 files changed, 141 insertions(+), 6 deletions(-)
diff --git a/dlls/shcore/main.c b/dlls/shcore/main.c index 96ba7d791b..94e1ab1bbb 100644 --- a/dlls/shcore/main.c +++ b/dlls/shcore/main.c @@ -1763,3 +1763,113 @@ HKEY WINAPI SHRegDuplicateHKey(HKEY hKey) TRACE("new key is %p\n", newKey); return newKey; } + +/************************************************************************* + * SHDeleteEmptyKeyW [SHCORE.@] + */ +DWORD WINAPI SHDeleteEmptyKeyW(HKEY hkey, const WCHAR *subkey) +{ + DWORD ret, count = 0; + HKEY hsubkey = 0; + + TRACE("(%p, %s)\n", hkey, debugstr_w(subkey)); + + ret = RegOpenKeyExW(hkey, subkey, 0, KEY_READ, &hsubkey); + if (!ret) + { + ret = RegQueryInfoKeyW(hsubkey, NULL, NULL, NULL, &count, + NULL, NULL, NULL, NULL, NULL, NULL, NULL); + RegCloseKey(hsubkey); + if (!ret) + { + if (count) + ret = ERROR_KEY_HAS_CHILDREN; + else + ret = RegDeleteKeyW(hkey, subkey); + } + } + + return ret; +} + +/************************************************************************* + * SHDeleteEmptyKeyA [SHCORE.@] + */ +DWORD WINAPI SHDeleteEmptyKeyA(HKEY hkey, const char *subkey) +{ + WCHAR *subkeyW = NULL; + DWORD ret; + + TRACE("(%p, %s)\n", hkey, debugstr_a(subkey)); + + if (subkey && FAILED(SHStrDupA(subkey, &subkeyW))) + return ERROR_OUTOFMEMORY; + + ret = SHDeleteEmptyKeyW(hkey, subkeyW); + CoTaskMemFree(subkeyW); + return ret; +} + +/************************************************************************* + * SHDeleteKeyW [SHCORE.@] + */ +DWORD WINAPI SHDeleteKeyW(HKEY hkey, const WCHAR *subkey) +{ + TRACE("(%p, %s)\n", hkey, debugstr_w(subkey)); + + return RegDeleteTreeW(hkey, subkey); +} + +/************************************************************************* + * SHDeleteKeyA [SHCORE.@] + */ +DWORD WINAPI SHDeleteKeyA(HKEY hkey, const char *subkey) +{ + TRACE("(%p, %s)\n", hkey, debugstr_a(subkey)); + + return RegDeleteTreeA(hkey, subkey); +} + +/************************************************************************* + * SHDeleteValueW [SHCORE.@] + */ +DWORD WINAPI SHDeleteValueW(HKEY hkey, const WCHAR *subkey, const WCHAR *value) +{ + HKEY hsubkey; + DWORD ret; + + TRACE("(%p, %s, %s)\n", hkey, debugstr_w(subkey), debugstr_w(value)); + + ret = RegOpenKeyExW(hkey, subkey, 0, KEY_SET_VALUE, &hsubkey); + if (!ret) + { + ret = RegDeleteValueW(hsubkey, value); + RegCloseKey(hsubkey); + } + + return ret; +} + +/************************************************************************* + * SHDeleteValueA [SHCORE.@] + */ +DWORD WINAPI SHDeleteValueA(HKEY hkey, const char *subkey, const char *value) +{ + WCHAR *subkeyW = NULL, *valueW = NULL; + DWORD ret; + + TRACE("(%p, %s, %s)\n", hkey, debugstr_a(subkey), debugstr_a(value)); + + if (subkey && FAILED(SHStrDupA(subkey, &subkeyW))) + return ERROR_OUTOFMEMORY; + if (value && FAILED(SHStrDupA(value, &valueW))) + { + CoTaskMemFree(subkeyW); + return ERROR_OUTOFMEMORY; + } + + ret = SHDeleteValueW(hkey, subkeyW, valueW); + CoTaskMemFree(subkeyW); + CoTaskMemFree(valueW); + return ret; +} diff --git a/dlls/shcore/shcore.spec b/dlls/shcore/shcore.spec index c7a8744a2c..d6e48368ae 100644 --- a/dlls/shcore/shcore.spec +++ b/dlls/shcore/shcore.spec @@ -40,12 +40,12 @@ @ stdcall SHCreateThread(ptr ptr long ptr) @ stdcall SHCreateThreadRef(ptr ptr) @ stub SHCreateThreadWithHandle -@ stdcall SHDeleteEmptyKeyA(long ptr) shlwapi.SHDeleteEmptyKeyA -@ stdcall SHDeleteEmptyKeyW(long ptr) shlwapi.SHDeleteEmptyKeyW -@ stdcall SHDeleteKeyA(long str) shlwapi.SHDeleteKeyA -@ stdcall SHDeleteKeyW(long wstr) shlwapi.SHDeleteKeyW -@ stdcall SHDeleteValueA(long str str) shlwapi.SHDeleteValueA -@ stdcall SHDeleteValueW(long wstr wstr) shlwapi.SHDeleteValueW +@ stdcall SHDeleteEmptyKeyA(long ptr) +@ stdcall SHDeleteEmptyKeyW(long ptr) +@ stdcall SHDeleteKeyA(long str) +@ 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 diff --git a/dlls/shcore/tests/shcore.c b/dlls/shcore/tests/shcore.c index 0945e12174..e1af2a2edc 100644 --- a/dlls/shcore/tests/shcore.c +++ b/dlls/shcore/tests/shcore.c @@ -34,6 +34,7 @@ static int (WINAPI *pSHAnsiToUnicode)(const char *, WCHAR *, int); 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 void init(HMODULE hshcore) { @@ -45,6 +46,7 @@ static void init(HMODULE hshcore) X(SHAnsiToAnsi); X(SHUnicodeToUnicode); X(SHRegDuplicateHKey); + X(SHDeleteKeyA); #undef X }
@@ -319,6 +321,28 @@ static void test_SHRegDuplicateHKey(void) RegDeleteKeyA(HKEY_CURRENT_USER, "Software\Wine\Test"); }
+static void test_SHDeleteKey(void) +{ + HKEY hkey, hkey2; + DWORD ret; + + ret = RegCreateKeyA(HKEY_CURRENT_USER, "Software\Wine\Test", &hkey); + ok(!ret, "Failed to create test key, %d.\n", ret); + + ret = RegCreateKeyA(hkey, "delete_key", &hkey2); + ok(!ret, "Failed to create test key, %d.\n", ret); + RegCloseKey(hkey2); + + ret = RegDeleteKeyA(HKEY_CURRENT_USER, "Software\Wine\Test"); + ok(ret == ERROR_ACCESS_DENIED, "Unexpected return value %d.\n", ret); + + ret = pSHDeleteKeyA(HKEY_CURRENT_USER, "Software\Wine\Test"); + ok(!ret, "Failed to delete a key, %d.\n", ret); + + ret = RegCloseKey(hkey); + ok(!ret, "Failed to delete a key, %d.\n", ret); +} + START_TEST(shcore) { HMODULE hshcore = LoadLibraryA("shcore.dll"); @@ -337,4 +361,5 @@ START_TEST(shcore) test_SHAnsiToAnsi(); test_SHUnicodeToUnicode(); test_SHRegDuplicateHKey(); + test_SHDeleteKey(); }