mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Added patch to implement advapi32.RegCopyTree{A,W}.
This commit is contained in:
parent
d6cc738728
commit
d88399a1de
@ -0,0 +1,55 @@
|
||||
From 33d8e5aac7dfedd9230ef340eeef57398282147c Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Mon, 15 Feb 2016 03:38:48 +0100
|
||||
Subject: advapi32/tests: Improve RegDeleteTree tests.
|
||||
|
||||
---
|
||||
dlls/advapi32/tests/registry.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c
|
||||
index ef5d989..183e538 100644
|
||||
--- a/dlls/advapi32/tests/registry.c
|
||||
+++ b/dlls/advapi32/tests/registry.c
|
||||
@@ -41,7 +41,7 @@ static const char * sTestpath2 = "%FOO%\\subdir1";
|
||||
static const DWORD ptr_size = 8 * sizeof(void*);
|
||||
|
||||
static DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD);
|
||||
-static DWORD (WINAPI *pRegDeleteTreeA)(HKEY,LPCSTR);
|
||||
+static LONG (WINAPI *pRegDeleteTreeA)(HKEY,const char *);
|
||||
static DWORD (WINAPI *pRegDeleteKeyExA)(HKEY,LPCSTR,REGSAM,DWORD);
|
||||
static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
|
||||
static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE);
|
||||
@@ -2083,6 +2083,7 @@ static void test_reg_delete_tree(void)
|
||||
{
|
||||
CHAR buffer[MAX_PATH];
|
||||
HKEY subkey, subkey2;
|
||||
+ DWORD dwsize, type;
|
||||
LONG size, ret;
|
||||
|
||||
if(!pRegDeleteTreeA) {
|
||||
@@ -2128,7 +2129,9 @@ static void test_reg_delete_tree(void)
|
||||
ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
ret = RegCloseKey(subkey2);
|
||||
ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
- ret = RegSetValueA(subkey, "value", REG_SZ, "data2", 5);
|
||||
+ ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data2", 5);
|
||||
ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
ret = pRegDeleteTreeA(subkey, NULL);
|
||||
ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
@@ -2143,8 +2146,8 @@ static void test_reg_delete_tree(void)
|
||||
ok(ret == ERROR_SUCCESS,
|
||||
"Default value of subkey is not present\n");
|
||||
ok(!buffer[0], "Expected length 0 got length %u(%s)\n", lstrlenA(buffer), buffer);
|
||||
- size = MAX_PATH;
|
||||
- ok(RegQueryValueA(subkey, "value", buffer, &size),
|
||||
+ dwsize = MAX_PATH;
|
||||
+ ok(RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize),
|
||||
"Value is still present\n");
|
||||
|
||||
ret = pRegDeleteTreeA(hkey_main, "not-here");
|
||||
--
|
||||
2.7.1
|
||||
|
@ -0,0 +1,142 @@
|
||||
From b41aaf3ea73161ee1680dd3dad34544484eaf05c Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Mon, 15 Feb 2016 03:40:36 +0100
|
||||
Subject: advapi32/tests: Add tests for RegCopyTree.
|
||||
|
||||
---
|
||||
dlls/advapi32/tests/registry.c | 98 ++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 98 insertions(+)
|
||||
|
||||
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c
|
||||
index 183e538..d29e131 100644
|
||||
--- a/dlls/advapi32/tests/registry.c
|
||||
+++ b/dlls/advapi32/tests/registry.c
|
||||
@@ -41,6 +41,7 @@ static const char * sTestpath2 = "%FOO%\\subdir1";
|
||||
static const DWORD ptr_size = 8 * sizeof(void*);
|
||||
|
||||
static DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD);
|
||||
+static LONG (WINAPI *pRegCopyTreeA)(HKEY,const char *,HKEY);
|
||||
static LONG (WINAPI *pRegDeleteTreeA)(HKEY,const char *);
|
||||
static DWORD (WINAPI *pRegDeleteKeyExA)(HKEY,LPCSTR,REGSAM,DWORD);
|
||||
static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
|
||||
@@ -135,6 +136,7 @@ static void InitFunctionPtrs(void)
|
||||
|
||||
/* This function was introduced with Windows 2003 SP1 */
|
||||
ADVAPI32_GET_PROC(RegGetValueA);
|
||||
+ ADVAPI32_GET_PROC(RegCopyTreeA);
|
||||
ADVAPI32_GET_PROC(RegDeleteTreeA);
|
||||
ADVAPI32_GET_PROC(RegDeleteKeyExA);
|
||||
ADVAPI32_GET_PROC(RegDeleteKeyValueA);
|
||||
@@ -2079,6 +2081,101 @@ static void test_string_termination(void)
|
||||
RegCloseKey(subkey);
|
||||
}
|
||||
|
||||
+static void test_reg_copy_tree(void)
|
||||
+{
|
||||
+ HKEY src, dst, subkey;
|
||||
+ CHAR buffer[MAX_PATH];
|
||||
+ DWORD dwsize, type;
|
||||
+ LONG size, ret;
|
||||
+
|
||||
+ if (!pRegCopyTreeA)
|
||||
+ {
|
||||
+ skip("Skipping RegCopyTreeA tests, function not present\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ret = RegCreateKeyA(hkey_main, "src", &src);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ret = RegCreateKeyA(hkey_main, "dst", &dst);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+
|
||||
+ /* Copy nonexistent subkey */
|
||||
+ ret = pRegCopyTreeA(src, "nonexistent_subkey", dst);
|
||||
+ ok(ret == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", ret);
|
||||
+
|
||||
+ /* Create test keys and values */
|
||||
+ ret = RegSetValueA(src, NULL, REG_SZ, "data", 4);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ret = RegSetValueExA(src, "value", 0, REG_SZ, (const BYTE *)"data2", 5);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+
|
||||
+ ret = RegCreateKeyA(src, "subkey2", &subkey);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ret = RegSetValueA(subkey, NULL, REG_SZ, "data3", 5);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data4", 5);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ret = RegCloseKey(subkey);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+
|
||||
+ ret = RegCreateKeyA(src, "subkey3", &subkey);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ret = RegCloseKey(subkey);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+
|
||||
+ /* Copy subkey */
|
||||
+ ret = pRegCopyTreeA(src, "subkey2", dst);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+
|
||||
+ size = MAX_PATH;
|
||||
+ ret = RegQueryValueA(dst, NULL, buffer, &size);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer);
|
||||
+
|
||||
+ dwsize = MAX_PATH;
|
||||
+ ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type);
|
||||
+ ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer);
|
||||
+
|
||||
+ /* Copy full tree */
|
||||
+ ret = pRegCopyTreeA(src, NULL, dst);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+
|
||||
+ size = MAX_PATH;
|
||||
+ ret = RegQueryValueA(dst, NULL, buffer, &size);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ok(!strcmp(buffer, "data"), "Expected 'data', got '%s'\n", buffer);
|
||||
+
|
||||
+ dwsize = MAX_PATH;
|
||||
+ ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type);
|
||||
+ ok(!strcmp(buffer, "data2"), "Expected 'data2', got '%s'\n", buffer);
|
||||
+
|
||||
+ ret = RegOpenKeyA(dst, "subkey2", &subkey);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ size = MAX_PATH;
|
||||
+ ret = RegQueryValueA(subkey, NULL, buffer, &size);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer);
|
||||
+ dwsize = MAX_PATH;
|
||||
+ ret = RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type);
|
||||
+ ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer);
|
||||
+ ret = RegCloseKey(subkey);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+
|
||||
+ ret = RegOpenKeyA(dst, "subkey3", &subkey);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+ ret = RegCloseKey(subkey);
|
||||
+ ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret);
|
||||
+
|
||||
+ delete_key(src);
|
||||
+ delete_key(dst);
|
||||
+}
|
||||
+
|
||||
static void test_reg_delete_tree(void)
|
||||
{
|
||||
CHAR buffer[MAX_PATH];
|
||||
@@ -3320,6 +3417,7 @@ START_TEST(registry)
|
||||
test_reg_save_key();
|
||||
test_reg_load_key();
|
||||
test_reg_unload_key();
|
||||
+ test_reg_copy_tree();
|
||||
test_reg_delete_tree();
|
||||
test_rw_order();
|
||||
test_deleted_key();
|
||||
--
|
||||
2.7.1
|
||||
|
@ -0,0 +1,193 @@
|
||||
From 8303376b344d5525f7124016fef073da747c6acd Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
|
||||
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
|
||||
|
@ -0,0 +1,217 @@
|
||||
From f9c5910f851677d6a8e7051043d254fb1538c0c3 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Mon, 15 Feb 2016 06:40:17 +0100
|
||||
Subject: advapi32: Clean up RegDeleteTree implementation.
|
||||
|
||||
---
|
||||
dlls/advapi32/registry.c | 156 ++++++++++++++++++++++-------------------------
|
||||
1 file changed, 74 insertions(+), 82 deletions(-)
|
||||
|
||||
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
|
||||
index faca66c..eb23eb1 100644
|
||||
--- a/dlls/advapi32/registry.c
|
||||
+++ b/dlls/advapi32/registry.c
|
||||
@@ -3016,126 +3016,118 @@ LSTATUS WINAPI RegDisablePredefinedCache(void)
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
+
|
||||
+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 (value_buf && max_value > *value_size)
|
||||
+ {
|
||||
+ if (!(*value_buf = heap_alloc( max_value )))
|
||||
+ return ERROR_NOT_ENOUGH_MEMORY;
|
||||
+ *value_size = max_value;
|
||||
+ }
|
||||
+
|
||||
+ return ERROR_SUCCESS;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/******************************************************************************
|
||||
* RegDeleteTreeW [ADVAPI32.@]
|
||||
*
|
||||
*/
|
||||
-LSTATUS WINAPI RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey)
|
||||
+LSTATUS WINAPI RegDeleteTreeW( HKEY hkey, const WCHAR *subkey )
|
||||
{
|
||||
+ static const WCHAR emptyW[] = {0};
|
||||
+ WCHAR buf1[MAX_PATH], *name_buf = buf1;
|
||||
+ DWORD name_size, max_name = sizeof(buf1) / sizeof(WCHAR);
|
||||
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));
|
||||
+ TRACE( "(%p, %s)\n", hkey, debugstr_w(subkey) );
|
||||
|
||||
- if(lpszSubKey)
|
||||
+ if (subkey)
|
||||
{
|
||||
- ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
|
||||
+ ret = RegOpenKeyExW( hkey, subkey, 0, KEY_READ, &hkey );
|
||||
if (ret) return ret;
|
||||
}
|
||||
|
||||
- /* Get highest length for keys, values */
|
||||
- ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
|
||||
- &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
|
||||
+ /* Allocate required buffers */
|
||||
+ ret = reg_get_buffers( hkey, &name_buf, &max_name, NULL, NULL );
|
||||
if (ret) goto cleanup;
|
||||
|
||||
- dwMaxSubkeyLen++;
|
||||
- dwMaxValueLen++;
|
||||
- dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
|
||||
- if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
|
||||
+ /* Recursively delete all the subkeys */
|
||||
+ for (;;)
|
||||
{
|
||||
- /* Name too big: alloc a buffer for it */
|
||||
- if (!(lpszName = heap_alloc( dwMaxLen*sizeof(WCHAR))))
|
||||
- {
|
||||
- ret = ERROR_NOT_ENOUGH_MEMORY;
|
||||
- goto cleanup;
|
||||
- }
|
||||
+ name_size = max_name;
|
||||
+ ret = RegEnumKeyExW( hkey, 0, name_buf, &name_size, NULL, NULL, NULL, NULL );
|
||||
+ if (ret == ERROR_NO_MORE_ITEMS) break;
|
||||
+ if (ret) goto cleanup;
|
||||
+ ret = RegDeleteTreeW( hkey, name_buf );
|
||||
+ if (ret) goto cleanup;
|
||||
}
|
||||
|
||||
-
|
||||
- /* Recursively delete all the subkeys */
|
||||
- while (TRUE)
|
||||
+ /* Delete the key itself */
|
||||
+ if (subkey)
|
||||
{
|
||||
- dwSize = dwMaxLen;
|
||||
- if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
|
||||
- NULL, NULL, NULL)) break;
|
||||
+ ret = RegDeleteKeyW( hkey, emptyW );
|
||||
+ goto cleanup;
|
||||
+ }
|
||||
|
||||
- ret = RegDeleteTreeW(hSubKey, lpszName);
|
||||
+ /* Delete the values */
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ name_size = max_name;
|
||||
+ ret = RegEnumValueW( hkey, 0, name_buf, &name_size, NULL, NULL, NULL, NULL );
|
||||
+ if (ret == ERROR_NO_MORE_ITEMS) break;
|
||||
+ if (ret) goto cleanup;
|
||||
+ ret = RegDeleteValueW( hkey, name_buf );
|
||||
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;
|
||||
- }
|
||||
+ ret = ERROR_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
- /* Free buffer if allocated */
|
||||
- if (lpszName != szNameBuf)
|
||||
- heap_free( lpszName);
|
||||
- if(lpszSubKey)
|
||||
- RegCloseKey(hSubKey);
|
||||
+ if (name_buf != buf1)
|
||||
+ heap_free( name_buf );
|
||||
+ if (subkey)
|
||||
+ RegCloseKey( hkey );
|
||||
return ret;
|
||||
}
|
||||
|
||||
+
|
||||
/******************************************************************************
|
||||
* RegDeleteTreeA [ADVAPI32.@]
|
||||
*
|
||||
*/
|
||||
-LSTATUS WINAPI RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
|
||||
+LSTATUS WINAPI RegDeleteTreeA( HKEY hkey, const char *subkey )
|
||||
{
|
||||
+ UNICODE_STRING subkeyW;
|
||||
LONG ret;
|
||||
- UNICODE_STRING lpszSubKeyW;
|
||||
|
||||
- if (lpszSubKey) RtlCreateUnicodeStringFromAsciiz( &lpszSubKeyW, lpszSubKey);
|
||||
- else lpszSubKeyW.Buffer = NULL;
|
||||
- ret = RegDeleteTreeW( hKey, lpszSubKeyW.Buffer);
|
||||
- RtlFreeUnicodeString( &lpszSubKeyW );
|
||||
+ if (subkey) RtlCreateUnicodeStringFromAsciiz( &subkeyW, subkey );
|
||||
+ else subkeyW.Buffer = NULL;
|
||||
+ ret = RegDeleteTreeW( hkey, subkeyW.Buffer );
|
||||
+ RtlFreeUnicodeString( &subkeyW );
|
||||
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.@]
|
||||
*
|
||||
--
|
||||
2.7.1
|
||||
|
1
patches/advapi32-RegCopyTree/definition
Normal file
1
patches/advapi32-RegCopyTree/definition
Normal file
@ -0,0 +1 @@
|
||||
Fixes: [39690] Implement advapi32.RegCopyTree{A,W}
|
@ -87,6 +87,7 @@ patch_enable_all ()
|
||||
enable_Pipelight="$1"
|
||||
enable_Staging="$1"
|
||||
enable_advapi32_LsaLookupSids="$1"
|
||||
enable_advapi32_RegCopyTree="$1"
|
||||
enable_advapi32_SetSecurityInfo="$1"
|
||||
enable_amstream_GetMultiMediaStream="$1"
|
||||
enable_api_ms_win_Stub_DLLs="$1"
|
||||
@ -405,6 +406,9 @@ patch_enable ()
|
||||
advapi32-LsaLookupSids)
|
||||
enable_advapi32_LsaLookupSids="$2"
|
||||
;;
|
||||
advapi32-RegCopyTree)
|
||||
enable_advapi32_RegCopyTree="$2"
|
||||
;;
|
||||
advapi32-SetSecurityInfo)
|
||||
enable_advapi32_SetSecurityInfo="$2"
|
||||
;;
|
||||
@ -2468,6 +2472,29 @@ if test "$enable_advapi32_LsaLookupSids" -eq 1; then
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset advapi32-RegCopyTree
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#39690] Implement advapi32.RegCopyTree{A,W}
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/advapi32/advapi32.spec, dlls/advapi32/registry.c, dlls/advapi32/tests/registry.c, dlls/api-ms-win-core-
|
||||
# | registry-l1-1-0/api-ms-win-core-registry-l1-1-0.spec, dlls/api-ms-win-downlevel-advapi32-l1-1-0/api-ms-win-downlevel-
|
||||
# | advapi32-l1-1-0.spec
|
||||
# |
|
||||
if test "$enable_advapi32_RegCopyTree" -eq 1; then
|
||||
patch_apply advapi32-RegCopyTree/0001-advapi32-tests-Improve-RegDeleteTree-tests.patch
|
||||
patch_apply advapi32-RegCopyTree/0002-advapi32-tests-Add-tests-for-RegCopyTree.patch
|
||||
patch_apply advapi32-RegCopyTree/0003-advapi32-Implement-RegCopyTreeA-W.patch
|
||||
patch_apply advapi32-RegCopyTree/0004-advapi32-Clean-up-RegDeleteTree-implementation.patch
|
||||
(
|
||||
echo '+ { "Sebastian Lackner", "advapi32/tests: Improve RegDeleteTree tests.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "advapi32/tests: Add tests for RegCopyTree.", 1 },';
|
||||
echo '+ { "Michael Müller", "advapi32: Implement RegCopyTreeA/W.", 1 },';
|
||||
echo '+ { "Sebastian Lackner", "advapi32: Clean up RegDeleteTree implementation.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
# Patchset advapi32-SetSecurityInfo
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
x
Reference in New Issue
Block a user