diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index 0d27297e97f..20f333d53e7 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -473,6 +473,8 @@ @ stdcall RegCreateKeyW(long wstr ptr) @ stdcall RegDeleteKeyA(long str) @ stdcall RegDeleteKeyW(long wstr) +@ stdcall RegDeleteTreeA(long str) +@ stdcall RegDeleteTreeW(long wstr) @ stdcall RegDeleteValueA(long str) @ stdcall RegDeleteValueW(long wstr) @ stdcall RegDisablePredefinedCache() diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c index 44060048425..cb905ed592f 100644 --- a/dlls/advapi32/registry.c +++ b/dlls/advapi32/registry.c @@ -2615,3 +2615,91 @@ LONG WINAPI RegDisablePredefinedCache(void) return ERROR_SUCCESS; } + +/****************************************************************************** + * RegDeleteTreeW [ADVAPI32.@] + * + */ +LONG WINAPI RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey) +{ + LONG ret; + DWORD dwMaxSubkeyLen, dwMaxValueLen; + DWORD dwMaxLen, dwSize; + WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf; + HKEY hSubKey = hKey; + + TRACE("(hkey=%p,%p %s)\n", hKey, lpszSubKey, debugstr_w(lpszSubKey)); + + if(lpszSubKey) + { + ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey); + if (ret) return ret; + } + + /* Get highest length for keys, values */ + ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL, + &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL); + if (ret) goto cleanup; + + dwMaxSubkeyLen++; + dwMaxValueLen++; + dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen); + if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR)) + { + /* Name too big: alloc a buffer for it */ + if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR)))) + { + ret = ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + } + + + /* Recursively delete all the subkeys */ + while (TRUE) + { + dwSize = dwMaxLen; + if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, + NULL, NULL, NULL)) break; + + ret = RegDeleteTreeW(hSubKey, lpszName); + if (ret) goto cleanup; + } + + if (lpszSubKey) + ret = RegDeleteKeyW(hKey, lpszSubKey); + else + while (TRUE) + { + dwSize = dwMaxLen; + if (RegEnumValueW(hKey, 0, lpszName, &dwSize, + NULL, NULL, NULL, NULL)) break; + + ret = RegDeleteValueW(hKey, lpszName); + if (ret) goto cleanup; + } + +cleanup: + /* Free buffer if allocated */ + if (lpszName != szNameBuf) + HeapFree( GetProcessHeap(), 0, lpszName); + if(lpszSubKey) + RegCloseKey(hSubKey); + return ret; +} + +/****************************************************************************** + * RegDeleteTreeA [ADVAPI32.@] + * + */ +LONG WINAPI RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey) +{ + LONG ret; + UNICODE_STRING lpszSubKeyW; + + if (lpszSubKey) RtlCreateUnicodeStringFromAsciiz( &lpszSubKeyW, lpszSubKey); + else lpszSubKeyW.Buffer = NULL; + ret = RegDeleteTreeW( hKey, lpszSubKeyW.Buffer); + RtlFreeUnicodeString( &lpszSubKeyW ); + return ret; +} diff --git a/include/winreg.h b/include/winreg.h index c6940521072..4e04956ba72 100644 --- a/include/winreg.h +++ b/include/winreg.h @@ -154,6 +154,9 @@ LONG WINAPI RegCreateKeyW(HKEY,LPCWSTR,PHKEY); LONG WINAPI RegDeleteKeyA(HKEY,LPCSTR); LONG WINAPI RegDeleteKeyW(HKEY,LPCWSTR); #define RegDeleteKey WINELIB_NAME_AW(RegDeleteKey) +LONG WINAPI RegDeleteTreeA(HKEY,LPCSTR); +LONG WINAPI RegDeleteTreeW(HKEY,LPCWSTR); +#define RegDeleteTree WINELIB_NAME_AW(RegDeleteTree) LONG WINAPI RegDeleteValueA(HKEY,LPCSTR); LONG WINAPI RegDeleteValueW(HKEY,LPCWSTR); #define RegDeleteValue WINELIB_NAME_AW(RegDeleteValue)