diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index 88f7fee9234..08f799df499 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 350840741d0..1e7639c5d0a 100644 --- a/dlls/advapi32/registry.c +++ b/dlls/advapi32/registry.c @@ -3104,6 +3104,101 @@ LSTATUS WINAPI RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey) return ret; } + +/****************************************************************************** + * RegCopyTreeW [ADVAPI32.@] + * + */ +LONG WINAPI RegCopyTreeW( HKEY hsrc, const WCHAR *subkey, HKEY hdst ) +{ + DWORD name_size, max_name; + DWORD value_size, max_value; + DWORD max_subkey, i, type; + WCHAR *name_buf = NULL; + BYTE *value_buf = NULL; + 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; + } + + ret = RegQueryInfoKeyW( hsrc, NULL, NULL, NULL, NULL, &max_subkey, + NULL, NULL, &max_name, &max_value, NULL, NULL ); + if (ret) + goto cleanup; + + max_name = max( max_subkey, max_name ) + 1; + if (!(name_buf = heap_alloc( max_name * sizeof(WCHAR) ))) + { + ret = ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + + if (!(value_buf = heap_alloc( max_value ))) + { + ret = ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + + /* Copy 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 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: + heap_free( name_buf ); + 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 d29e131e386..658b35620f2 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 d83fbdd2779..91b1a94784d 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 4105e59bf04..e1b46638004 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