From 8303376b344d5525f7124016fef073da747c6acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Mon, 15 Feb 2016 06:27:10 +0100 Subject: advapi32: Implement RegCopyTreeA/W. --- dlls/advapi32/advapi32.spec | 4 +- dlls/advapi32/registry.c | 114 +++++++++++++++++++++ dlls/advapi32/tests/registry.c | 2 +- .../api-ms-win-core-registry-l1-1-0.spec | 2 +- .../api-ms-win-downlevel-advapi32-l1-1-0.spec | 2 +- 5 files changed, 119 insertions(+), 5 deletions(-) diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index 36f176b..e3c7c4b 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -575,8 +575,8 @@ @ stdcall RegConnectRegistryW(wstr long ptr) # @ stub RegConnectRegistryExA # @ stub RegConnectRegistryExW -# @ stub RegCopyTreeA -# @ stub RegCopyTreeW +@ stdcall RegCopyTreeA(long str long) +@ stdcall RegCopyTreeW(long wstr long) @ stdcall RegCreateKeyA(long str ptr) @ stdcall RegCreateKeyExA(long str long ptr long long ptr ptr ptr) @ stdcall RegCreateKeyExW(long wstr long ptr long long ptr ptr ptr) diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c index 3508407..faca66c 100644 --- a/dlls/advapi32/registry.c +++ b/dlls/advapi32/registry.c @@ -3104,6 +3104,120 @@ LSTATUS WINAPI RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey) return ret; } + +static LONG reg_get_buffers( HKEY hkey, WCHAR **name_buf, DWORD *name_size, + BYTE **value_buf, DWORD *value_size ) +{ + DWORD ret, max_subkey, max_name, max_value; + + ret = RegQueryInfoKeyW( hkey, NULL, NULL, NULL, NULL, &max_subkey, + NULL, NULL, &max_name, &max_value, NULL, NULL ); + if (ret) + return ret; + + /* allocate buffer for subkeys / names */ + max_name = max( max_subkey, max_name ) + 1; + if (max_name > *name_size) + { + if (!(*name_buf = heap_alloc( max_name * sizeof(WCHAR) ))) + return ERROR_NOT_ENOUGH_MEMORY; + *name_size = max_name; + } + + /* allocate buffer for values */ + if (max_value > *value_size) + { + if (!(*value_buf = heap_alloc( max_value ))) + return ERROR_NOT_ENOUGH_MEMORY; + *value_size = max_value; + } + + return ERROR_SUCCESS; +} + + +/****************************************************************************** + * RegCopyTreeW [ADVAPI32.@] + * + */ +LONG WINAPI RegCopyTreeW( HKEY hsrc, const WCHAR *subkey, HKEY hdst ) +{ + WCHAR buf1[MAX_PATH], *name_buf = buf1; + BYTE buf2[MAX_PATH], *value_buf = buf2; + DWORD name_size, max_name = sizeof(buf1) / sizeof(WCHAR); + DWORD value_size, max_value = sizeof(buf2); + DWORD i, type; + HKEY hkey; + LONG ret; + + TRACE( "(%p, %s, %p)\n", hsrc, debugstr_w(subkey), hdst ); + + if (subkey) + { + ret = RegOpenKeyExW( hsrc, subkey, 0, KEY_READ, &hsrc ); + if (ret) return ret; + } + + /* Allocate required buffers */ + ret = reg_get_buffers( hsrc, &name_buf, &max_name, &value_buf, &max_value ); + if (ret) goto cleanup; + + /* Copy all the values */ + for (i = 0;; i++) + { + name_size = max_name; + value_size = max_value; + ret = RegEnumValueW( hsrc, i, name_buf, &name_size, NULL, &type, value_buf, &value_size ); + if (ret == ERROR_NO_MORE_ITEMS) break; + if (ret) goto cleanup; + ret = RegSetValueExW( hdst, name_buf, 0, type, value_buf, value_size ); + if (ret) goto cleanup; + } + + /* Recursively copy all the subkeys */ + for (i = 0;; i++) + { + name_size = max_name; + ret = RegEnumKeyExW( hsrc, i, name_buf, &name_size, NULL, NULL, NULL, NULL ); + if (ret == ERROR_NO_MORE_ITEMS) break; + if (ret) goto cleanup; + ret = RegCreateKeyExW( hdst, name_buf, 0, NULL, 0, KEY_WRITE, NULL, &hkey, NULL ); + if (ret) goto cleanup; + ret = RegCopyTreeW( hsrc, name_buf, hkey ); + RegCloseKey( hkey ); + if (ret) goto cleanup; + } + + ret = ERROR_SUCCESS; + +cleanup: + if (name_buf != buf1) + heap_free( name_buf ); + if (value_buf != buf2) + heap_free( value_buf ); + if (subkey) + RegCloseKey( hsrc ); + return ret; +} + + +/****************************************************************************** + * RegCopyTreeA [ADVAPI32.@] + * + */ +LONG WINAPI RegCopyTreeA( HKEY hsrc, const char *subkey, HKEY hdst ) +{ + UNICODE_STRING subkeyW; + LONG ret; + + if (subkey) RtlCreateUnicodeStringFromAsciiz( &subkeyW, subkey ); + else subkeyW.Buffer = NULL; + ret = RegCopyTreeW( hsrc, subkeyW.Buffer, hdst ); + RtlFreeUnicodeString( &subkeyW ); + return ret; +} + + /****************************************************************************** * RegDisableReflectionKey [ADVAPI32.@] * diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index d29e131..658b356 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -2090,7 +2090,7 @@ static void test_reg_copy_tree(void) if (!pRegCopyTreeA) { - skip("Skipping RegCopyTreeA tests, function not present\n"); + win_skip("Skipping RegCopyTreeA tests, function not present\n"); return; } diff --git a/dlls/api-ms-win-core-registry-l1-1-0/api-ms-win-core-registry-l1-1-0.spec b/dlls/api-ms-win-core-registry-l1-1-0/api-ms-win-core-registry-l1-1-0.spec index d83fbdd..91b1a94 100644 --- a/dlls/api-ms-win-core-registry-l1-1-0/api-ms-win-core-registry-l1-1-0.spec +++ b/dlls/api-ms-win-core-registry-l1-1-0/api-ms-win-core-registry-l1-1-0.spec @@ -1,5 +1,5 @@ @ stdcall RegCloseKey(long) advapi32.RegCloseKey -@ stub RegCopyTreeW +@ stdcall RegCopyTreeW(long wstr long) advapi32.RegCopyTreeW @ stdcall RegCreateKeyExA(long str long ptr long long ptr ptr ptr) advapi32.RegCreateKeyExA @ stdcall RegCreateKeyExW(long wstr long ptr long long ptr ptr ptr) advapi32.RegCreateKeyExW @ stdcall RegDeleteKeyExA(long str long long) advapi32.RegDeleteKeyExA diff --git a/dlls/api-ms-win-downlevel-advapi32-l1-1-0/api-ms-win-downlevel-advapi32-l1-1-0.spec b/dlls/api-ms-win-downlevel-advapi32-l1-1-0/api-ms-win-downlevel-advapi32-l1-1-0.spec index 4105e59..e1b4663 100644 --- a/dlls/api-ms-win-downlevel-advapi32-l1-1-0/api-ms-win-downlevel-advapi32-l1-1-0.spec +++ b/dlls/api-ms-win-downlevel-advapi32-l1-1-0/api-ms-win-downlevel-advapi32-l1-1-0.spec @@ -84,7 +84,7 @@ @ stdcall PrivilegedServiceAuditAlarmW(wstr wstr long ptr long) advapi32.PrivilegedServiceAuditAlarmW @ stub QuerySecurityAccessMask @ stdcall RegCloseKey(long) advapi32.RegCloseKey -@ stub RegCopyTreeW +@ stdcall RegCopyTreeW(long wstr long) advapi32.RegCopyTreeW @ stdcall RegCreateKeyExA(long str long ptr long long ptr ptr ptr) advapi32.RegCreateKeyExA @ stdcall RegCreateKeyExW(long wstr long ptr long long ptr ptr ptr) advapi32.RegCreateKeyExW @ stdcall RegDeleteKeyExA(long str long long) advapi32.RegDeleteKeyExA -- 2.7.1