Initial implementation for registry application hives, this is a step forward to get Visual Studio to run. :-)
From: Santino Mazza mazzasantino1206@gmail.com
Signed-off-by: Santino Mazza smazza@codeweavers.com --- dlls/advapi32/tests/registry.c | 89 ++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index df56b0968ee..7bafc1ed42e 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -1600,6 +1600,94 @@ static void test_reg_unload_key(void) DeleteFileA("saved_key.LOG"); }
+static void test_reg_load_app_key(void) +{ + DWORD ret; + HKEY key1; + HKEY key2; + HKEY childkey; + DWORD size1; + DWORD size2; + HANDLE hivefile; + + set_privileges(SE_BACKUP_NAME, FALSE); + set_privileges(SE_RESTORE_NAME, FALSE); + + /* Test with non existant file */ + ret = RegLoadAppKeyA("saved_app_key", &key1, KEY_READ, 0, 0); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(key1 != NULL, "got a null key\n"); + + ret = GetFileAttributesA("saved_app_key"); + todo_wine ok(ret != -1, "hive file didn't got created.\n"); + + RegCloseKey(key1); + DeleteFileA("saved_app_key"); + + if (!set_privileges(SE_BACKUP_NAME, TRUE) || + !set_privileges(SE_RESTORE_NAME, FALSE)) + { + win_skip("Failed to set SE_BACKUP_NAME privileges, skipping tests\n"); + return; + } + + ret = RegSaveKeyA(hkey_main, "saved_app_key", NULL); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + + /* Test without process app key ownership */ + ret = RegLoadAppKeyA("saved_app_key", &key1, KEY_READ, 0, 0); + ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(key1 != NULL, "got a null key\n"); + + ret = RegLoadAppKeyA("saved_app_key", &key2, KEY_READ, 0, 0); + ok(ret == ERROR_SUCCESS || broken(ret == ERROR_ALREADY_EXISTS) /* win7 */, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(key2 != NULL || broken(key2 == NULL) /* win7 */, "got a null key\n"); + + RegCloseKey(key1); + RegCloseKey(key2); + + /* Test with process app key ownership */ + ret = RegLoadAppKeyA("saved_app_key", &key1, KEY_READ, REG_PROCESS_APPKEY, 0); + ok(ret == ERROR_SUCCESS || broken(ret == ERROR_ALREADY_EXISTS) /* win7 */, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(key1 != NULL, "got a null key\n"); + + ret = RegLoadAppKeyA("saved_app_key", &key2, KEY_READ, 0, 0); + todo_wine ok(ret == ERROR_SHARING_VIOLATION || broken(ret == ERROR_ALREADY_EXISTS) /* win7 */, "expected ERROR_SHARING_VIOLATION, got %ld\n", ret); + todo_wine ok(key2 == NULL || broken(key2 != NULL), "expected null handle\n"); + + RegCloseKey(key1); + + ret = RegLoadAppKeyA("saved_app_key", &key2, KEY_READ, 0, 0); + ok(ret == ERROR_SUCCESS || broken(ret == ERROR_ALREADY_EXISTS) /* win7 */, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(key2 != NULL || broken(key2 == NULL) /* win7 */, "got a null key\n"); + RegCloseKey(key2); + + + /* Check if the changes are saved to the file */ + hivefile = CreateFileA("saved_app_key", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + size1 = GetFileSize(hivefile, NULL); + CloseHandle(hivefile); + + ret = RegLoadAppKeyA("saved_app_key", &key1, KEY_READ | KEY_WRITE, 0, 0); + ok(ret == ERROR_SUCCESS || broken(ret == ERROR_ALREADY_EXISTS) /* win7 */, "expected ERROR_SUCCESS, got %ld\n", ret); + ok(key1 != NULL, "got a null key\n"); + + ret = RegCreateKeyA(key1, "testkey", &childkey); + todo_wine ok(ret == ERROR_SUCCESS || broken(ret == ERROR_INVALID_HANDLE) /* win7 */, "error when creating testkey. %ld\n", ret); + RegCloseKey(key1); + + hivefile = CreateFileA("saved_app_key", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + size2 = GetFileSize(hivefile, NULL); + todo_wine ok(size2 > size1 || broken(size1 == size2) /* win7 */, "Expected file to increase size. %ld >= %ld\n", size1, size2); + CloseHandle(hivefile); + + DeleteFileA("saved_app_key"); + DeleteFileA("saved_app_key.LOG"); + +} + /* tests that show that RegConnectRegistry and OpenSCManager accept computer names without the \ prefix (what MSDN says). */ @@ -4485,6 +4573,7 @@ START_TEST(registry) test_classesroot_mask(); test_reg_save_key(); test_reg_load_key(); + test_reg_load_app_key(); test_reg_unload_key(); test_reg_copy_tree(); test_reg_delete_tree();
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=122002
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
advapi32: registry.c:1635: Test failed: expected ERROR_SUCCESS, got 183
From: Santino Mazza smazza@codeweavers.com
Signed-off-by: Santino Mazza smazza@codeweavers.com --- dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/unix/loader.c | 1 + dlls/ntdll/unix/registry.c | 10 ++++++++++ dlls/wow64/registry.c | 24 ++++++++++++++++++++++++ dlls/wow64/syscall.h | 1 + include/winternl.h | 1 + 6 files changed, 38 insertions(+)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index c294490d544..7469763e7dc 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -244,6 +244,7 @@ @ stdcall -syscall NtLoadDriver(ptr) @ stdcall -syscall NtLoadKey2(ptr ptr long) @ stdcall -syscall NtLoadKey(ptr ptr) +@ stdcall -syscall NtLoadKeyEx(ptr ptr long long long long ptr ptr) @ stdcall -syscall NtLockFile(long long ptr ptr ptr ptr ptr ptr long long) # @ stub NtLockProductActivationKeys # @ stub NtLockRegistryKey diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index f58a716d08c..b78efddee1f 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -203,6 +203,7 @@ static void * const syscalls[] = NtLoadDriver, NtLoadKey, NtLoadKey2, + NtLoadKeyEx, NtLockFile, NtLockVirtualMemory, NtMakeTemporaryObject, diff --git a/dlls/ntdll/unix/registry.c b/dlls/ntdll/unix/registry.c index 693a594e84b..fae969763e6 100644 --- a/dlls/ntdll/unix/registry.c +++ b/dlls/ntdll/unix/registry.c @@ -729,6 +729,16 @@ NTSTATUS WINAPI NtLoadKey2( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *fi return NtLoadKey( attr, file ); }
+/****************************************************************************** + * NtLoadKeyEx (NTDLL.@) + */ +NTSTATUS WINAPI NtLoadKeyEx( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file, ULONG flags, HANDLE trustkey, + HANDLE event, ACCESS_MASK access, HANDLE *roothandle, IO_STATUS_BLOCK *iostatus ) +{ + FIXME( "(%p,%p,0x%08x,%p,%p,0x%08x,%p,%p) stub\n", attr, file, flags, trustkey, event, + access, roothandle, iostatus); + return STATUS_NOT_IMPLEMENTED; +}
/****************************************************************************** * NtUnloadKey (NTDLL.@) diff --git a/dlls/wow64/registry.c b/dlls/wow64/registry.c index dfb75d72bc7..6ced946766c 100644 --- a/dlls/wow64/registry.c +++ b/dlls/wow64/registry.c @@ -181,6 +181,30 @@ NTSTATUS WINAPI wow64_NtLoadKey2( UINT *args ) return NtLoadKey2( objattr_32to64( &attr, attr32 ), objattr_32to64( &file, file32 ), flags ); }
+/********************************************************************** + * wow64_NtLoadKeyEx + */ +NTSTATUS WINAPI wow64_NtLoadKeyEx( UINT *args ) +{ + OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args ); + OBJECT_ATTRIBUTES32 *file32 = get_ptr( &args ); + ULONG flags = get_ulong( &args ); + HANDLE trustkey = get_handle( &args ); + HANDLE event = get_handle( &args ); + ACCESS_MASK desired_access = get_ulong( &args ); + HANDLE *rootkey = get_ptr( &args ); + IO_STATUS_BLOCK32 *io32 = get_ptr( &args ); + + struct object_attr64 attr, file; + IO_STATUS_BLOCK io; + NTSTATUS status; + + status = NtLoadKeyEx( objattr_32to64( &attr, attr32 ), objattr_32to64( &file, file32 ), flags, + trustkey, event, desired_access, rootkey, iosb_32to64(&io, io32) ); + put_iosb(io32, &io); + return status; +} +
/********************************************************************** * wow64_NtNotifyChangeKey diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h index 65fbca89f4f..b2b1ad6c2a8 100644 --- a/dlls/wow64/syscall.h +++ b/dlls/wow64/syscall.h @@ -104,6 +104,7 @@ SYSCALL_ENTRY( NtLoadDriver ) \ SYSCALL_ENTRY( NtLoadKey ) \ SYSCALL_ENTRY( NtLoadKey2 ) \ + SYSCALL_ENTRY( NtLoadKeyEx ) \ SYSCALL_ENTRY( NtLockFile ) \ SYSCALL_ENTRY( NtLockVirtualMemory ) \ SYSCALL_ENTRY( NtMakeTemporaryObject ) \ diff --git a/include/winternl.h b/include/winternl.h index 19354dd7ffb..24dd26af83c 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -4024,6 +4024,7 @@ NTSYSAPI NTSTATUS WINAPI NtListenPort(HANDLE,PLPC_MESSAGE); NTSYSAPI NTSTATUS WINAPI NtLoadDriver(const UNICODE_STRING *); NTSYSAPI NTSTATUS WINAPI NtLoadKey(const OBJECT_ATTRIBUTES *,OBJECT_ATTRIBUTES *); NTSYSAPI NTSTATUS WINAPI NtLoadKey2(const OBJECT_ATTRIBUTES *,OBJECT_ATTRIBUTES *,ULONG); +NTSYSAPI NTSTATUS WINAPI NtLoadKeyEx(const OBJECT_ATTRIBUTES *, OBJECT_ATTRIBUTES *, ULONG, HANDLE, HANDLE, ACCESS_MASK, HANDLE *, IO_STATUS_BLOCK *); NTSYSAPI NTSTATUS WINAPI NtLockFile(HANDLE,HANDLE,PIO_APC_ROUTINE,void*,PIO_STATUS_BLOCK,PLARGE_INTEGER,PLARGE_INTEGER,ULONG*,BOOLEAN,BOOLEAN); NTSYSAPI NTSTATUS WINAPI NtLockVirtualMemory(HANDLE,PVOID*,SIZE_T*,ULONG); NTSYSAPI NTSTATUS WINAPI NtMakeTemporaryObject(HANDLE);
From: Santino Mazza smazza@codeweavers.com
Signed-off-by: Santino Mazza smazza@codeweavers.com --- dlls/ntdll/tests/reg.c | 118 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index f3c4eb15da0..c2c6759ea43 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -150,6 +150,8 @@ static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG); static NTSTATUS (WINAPI * pRtlCreateRegistryKey)(ULONG, PWSTR); static NTSTATUS (WINAPI * pRtlpNtQueryValueKey)(HANDLE,ULONG*,PBYTE,DWORD*,void *); static NTSTATUS (WINAPI * pNtNotifyChangeKey)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN); +static NTSTATUS (WINAPI * pNtLoadKeyEx)(const OBJECT_ATTRIBUTES *, OBJECT_ATTRIBUTES *, ULONG, HANDLE, HANDLE, ACCESS_MASK, HANDLE*, IO_STATUS_BLOCK*); +static NTSTATUS (WINAPI * pNtUnloadKey)( OBJECT_ATTRIBUTES * ); static NTSTATUS (WINAPI * pNtNotifyChangeMultipleKeys)(HANDLE,ULONG,OBJECT_ATTRIBUTES*,HANDLE,PIO_APC_ROUTINE, void*,IO_STATUS_BLOCK*,ULONG,BOOLEAN,void*,ULONG,BOOLEAN); static NTSTATUS (WINAPI * pNtWaitForSingleObject)(HANDLE,BOOLEAN,const LARGE_INTEGER*); @@ -193,6 +195,8 @@ static BOOL InitFunctionPtrs(void) NTDLL_GET_PROC(NtSetValueKey) NTDLL_GET_PROC(NtOpenKey) NTDLL_GET_PROC(NtNotifyChangeKey) + NTDLL_GET_PROC(NtLoadKeyEx) + NTDLL_GET_PROC(NtUnloadKey) NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath) NTDLL_GET_PROC(RtlCompareUnicodeString) NTDLL_GET_PROC(RtlReAllocateHeap) @@ -457,6 +461,19 @@ static void test_NtOpenKey(void) ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtOpenKey failed: 0x%08lx\n", status ); pRtlFreeUnicodeString( &str );
+ /* test if application hive is accessible */ + pRtlCreateUnicodeStringFromAsciiz( &str, "\Registry\A" ); + status = pNtOpenKey(&key, KEY_READ, &attr); + todo_wine ok( status == STATUS_ACCESS_DENIED, "NtOpenKey failed: 0x%08lx\n", status ); + pNtClose( key ); + pRtlFreeUnicodeString( &str ); + + pRtlCreateUnicodeStringFromAsciiz( &str, "\Registry\A" ); + status = pNtOpenKey(&key, KEY_CREATE_SUB_KEY, &attr); + todo_wine ok( status == STATUS_ACCESS_DENIED, "NtOpenKey failed: 0x%08lx\n", status ); + pNtClose( key ); + pRtlFreeUnicodeString( &str ); + InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); status = pNtOpenKey(&key, KEY_WRITE|KEY_READ, &attr); ok(status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08lx\n", status); @@ -677,6 +694,12 @@ static void test_NtCreateKey(void) if (!status) pNtClose( subkey ); pRtlFreeUnicodeString( &str );
+ /* test if we can create a new application hive key */ + pRtlCreateUnicodeStringFromAsciiz( &str, "\Registry\A\FooTest" ); + status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); + todo_wine ok( status == STATUS_ACCESS_DENIED || broken(status == STATUS_OBJECT_PATH_NOT_FOUND) /* win7 */, "NtCreateKey failed: 0x%08lx\n", status ); + pRtlFreeUnicodeString( &str ); + pNtClose(key); }
@@ -2268,6 +2291,100 @@ static void test_NtRenameKey(void) pNtClose(key); }
+static BOOL set_privileges(LPCSTR privilege, BOOL set) +{ + TOKEN_PRIVILEGES tp; + HANDLE hToken; + LUID luid; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) + return FALSE; + + if(!LookupPrivilegeValueA(NULL, privilege, &luid)) + { + CloseHandle(hToken); + return FALSE; + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + + if (set) + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + else + tp.Privileges[0].Attributes = 0; + + AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); + if (GetLastError() != ERROR_SUCCESS) + { + CloseHandle(hToken); + return FALSE; + } + + CloseHandle(hToken); + return TRUE; +} + +static void test_NtLoadKeyEx(void) +{ + NTSTATUS status; + DWORD size, attr; + CHAR *directory; + OBJECT_ATTRIBUTES destkey, file; + UNICODE_STRING str, filename; + HANDLE rootkey; + HANDLE hivefile; + + /* Create empty hive file */ + hivefile = CreateFileA("savedkey", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hivefile == INVALID_HANDLE_VALUE) + { + win_skip("error when creating file %ld\n", GetLastError()); + return; + } + CloseHandle(hivefile); + + size = GetFullPathNameA("savedkey", 0, NULL, NULL); + directory = malloc(size + 4); + strcpy(directory, "\??\"); + GetFullPathNameA("savedkey", size, &directory[4], NULL); + pRtlCreateUnicodeStringFromAsciiz(&filename, directory); + file.Length = sizeof(file); + + InitializeObjectAttributes(&file, &filename, OBJ_CASE_INSENSITIVE, 0, 0); + InitializeObjectAttributes(&destkey, &str, 0, 0, 0); + + /* Test for application flag (0x10) */ + pRtlCreateUnicodeStringFromAsciiz(&str, "\REGISTRY\A\test1"); + status = pNtLoadKeyEx(&destkey, &file, 0x10, 0, 0, 0, &rootkey, 0); + todo_wine ok(status == STATUS_ACCESS_DENIED || broken(status == STATUS_ACCESS_VIOLATION) /* win7 */, "NtLoadKeyEx failed: %lx\n", status); + + status = pNtLoadKeyEx(&destkey, &file, 0x10, 0, 0, GENERIC_ALL, &rootkey, 0); + todo_wine ok(status == STATUS_SUCCESS || broken(status == STATUS_ACCESS_VIOLATION) /* win7 */, "NtLoadKeyEx failed: %lx\n", status); + pNtClose(rootkey); + + DeleteFileA("savedkey"); + /* Test normal key load */ + if (!set_privileges(SE_RESTORE_NAME, TRUE) || + !set_privileges(SE_BACKUP_NAME, FALSE)) + { + win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n"); + return; + } + + pRtlCreateUnicodeStringFromAsciiz(&str, "\REGISTRY\Machine\test2"); + status = pNtLoadKeyEx(&destkey, &file, 0, 0, 0, 0, NULL, 0); + todo_wine ok(status == STATUS_SUCCESS, "NtLoadKeyEx failed: %lx\n", status); + pNtUnloadKey(&destkey); + + attr = GetFileAttributesA("savedkey"); + todo_wine ok(attr != INVALID_FILE_ATTRIBUTES, "expected NtLoadKeyEx to create a file\n"); + + pRtlFreeUnicodeString(&str); + pRtlFreeUnicodeString(&filename); + DeleteFileA("savedkey"); +} + START_TEST(reg) { static const WCHAR winetest[] = {'\','W','i','n','e','T','e','s','t',0}; @@ -2298,6 +2415,7 @@ START_TEST(reg) test_symlinks(); test_redirection(); test_NtRenameKey(); + test_NtLoadKeyEx();
pRtlFreeUnicodeString(&winetestpath);
From: Santino Mazza smazza@codeweavers.com
Signed-off-by: Santino Mazza smazza@codeweavers.com --- dlls/ntdll/unix/registry.c | 41 ++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 22 deletions(-)
diff --git a/dlls/ntdll/unix/registry.c b/dlls/ntdll/unix/registry.c index fae969763e6..0a14664d721 100644 --- a/dlls/ntdll/unix/registry.c +++ b/dlls/ntdll/unix/registry.c @@ -680,6 +680,24 @@ NTSTATUS WINAPI NtFlushKey( HANDLE key ) * NtLoadKey (NTDLL.@) */ NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file ) +{ + return NtLoadKeyEx(attr, file, 0, 0, 0, 0, NULL, NULL); +} + +/****************************************************************************** + * NtLoadKey2 (NTDLL.@) + */ +NTSTATUS WINAPI NtLoadKey2( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file, ULONG flags ) +{ + FIXME( "(%p,%p,0x%08x) semi-stub: ignoring flags\n", attr, file, flags ); + return NtLoadKey( attr, file ); +} + +/****************************************************************************** + * NtLoadKeyEx (NTDLL.@) + */ +NTSTATUS WINAPI NtLoadKeyEx( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file, ULONG flags, HANDLE trustkey, + HANDLE event, ACCESS_MASK access, HANDLE *roothandle, IO_STATUS_BLOCK *iostatus ) { NTSTATUS ret; HANDLE key; @@ -689,7 +707,7 @@ NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *fil UNICODE_STRING nt_name; OBJECT_ATTRIBUTES new_attr = *file;
- TRACE("(%p,%p)\n", attr, file); + TRACE("(%p,%p,0x%x,%p,%p,0x%x,%p,%p)\n", attr, file, flags, trustkey, event, access, roothandle, iostatus);
get_redirect( &new_attr, &nt_name ); if (!(ret = nt_to_unix_file_name( &new_attr, &unix_name, FILE_OPEN ))) @@ -719,27 +737,6 @@ NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *fil return ret; }
- -/****************************************************************************** - * NtLoadKey2 (NTDLL.@) - */ -NTSTATUS WINAPI NtLoadKey2( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file, ULONG flags ) -{ - FIXME( "(%p,%p,0x%08x) semi-stub: ignoring flags\n", attr, file, flags ); - return NtLoadKey( attr, file ); -} - -/****************************************************************************** - * NtLoadKeyEx (NTDLL.@) - */ -NTSTATUS WINAPI NtLoadKeyEx( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file, ULONG flags, HANDLE trustkey, - HANDLE event, ACCESS_MASK access, HANDLE *roothandle, IO_STATUS_BLOCK *iostatus ) -{ - FIXME( "(%p,%p,0x%08x,%p,%p,0x%08x,%p,%p) stub\n", attr, file, flags, trustkey, event, - access, roothandle, iostatus); - return STATUS_NOT_IMPLEMENTED; -} - /****************************************************************************** * NtUnloadKey (NTDLL.@) */
From: Santino Mazza smazza@codeweavers.com
Signed-off-by: Santino Mazza smazza@codeweavers.com --- dlls/ntdll/unix/registry.c | 8 ++++++ include/wine/server_protocol.h | 6 ++++- server/protocol.def | 4 +++ server/registry.c | 45 ++++++++++++++++++++++++++++++++-- server/request.h | 6 ++++- server/trace.c | 9 ++++++- 6 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/unix/registry.c b/dlls/ntdll/unix/registry.c index 0a14664d721..c5766ab1f1e 100644 --- a/dlls/ntdll/unix/registry.c +++ b/dlls/ntdll/unix/registry.c @@ -709,6 +709,8 @@ NTSTATUS WINAPI NtLoadKeyEx( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *f
TRACE("(%p,%p,0x%x,%p,%p,0x%x,%p,%p)\n", attr, file, flags, trustkey, event, access, roothandle, iostatus);
+ if (roothandle) *roothandle = NULL; + get_redirect( &new_attr, &nt_name ); if (!(ret = nt_to_unix_file_name( &new_attr, &unix_name, FILE_OPEN ))) { @@ -726,8 +728,14 @@ NTSTATUS WINAPI NtLoadKeyEx( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *f SERVER_START_REQ( load_registry ) { req->file = wine_server_obj_handle( key ); + req->flags = flags; + req->access = access; wine_server_add_data( req, objattr, len ); ret = wine_server_call( req ); + if (roothandle) + *roothandle = wine_server_ptr_handle( reply->hkey ); + else + NtClose( (HANDLE) reply->hkey ); if (ret == STATUS_OBJECT_NAME_EXISTS) ret = STATUS_SUCCESS; } SERVER_END_REQ; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index fb3168c4a6a..220a1ace665 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2361,11 +2361,15 @@ struct load_registry_request { struct request_header __header; obj_handle_t file; + unsigned int flags; + unsigned int access; /* VARARG(objattr,object_attributes); */ }; struct load_registry_reply { struct reply_header __header; + obj_handle_t hkey; + char __pad_12[4]; };
@@ -6324,7 +6328,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 755 +#define SERVER_PROTOCOL_VERSION 756
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index d828d41d1f7..defe071a722 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1826,7 +1826,11 @@ struct process_info /* Load a registry branch from a file */ @REQ(load_registry) obj_handle_t file; /* file to load from */ + unsigned int flags; /* flags */ + unsigned int access; /* wanted access rights */ VARARG(objattr,object_attributes); /* object attributes */ +@REPLY + obj_handle_t hkey; /* handle to root key */ @END
diff --git a/server/registry.c b/server/registry.c index 96ba18a0a5a..7ce7a27eacf 100644 --- a/server/registry.c +++ b/server/registry.c @@ -102,6 +102,10 @@ struct key
#define OBJ_KEY_WOW64 0x100000 /* magic flag added to attributes for WoW64 redirection */
+/* load key flags */ +#define LOAD_NONE 0x0 +#define LOAD_APP_KEY 0x10 + /* a key value */ struct key_value { @@ -1767,6 +1771,25 @@ static void load_registry( struct key *key, obj_handle_t handle ) } }
+static void load_app_registry( struct key *key, obj_handle_t handle ) +{ + WCHAR applicationhive_fullpath[12] = {'\', 'R', 'E', 'G', 'I', 'S', 'T', 'R', 'Y', '\', 'A'}; + WCHAR *key_fullpath; + data_size_t key_fullpath_size; + + /* check if we are loading in \REGISTRY\A */ + key_fullpath = key_get_full_name( (struct object*)key, &key_fullpath_size ); + if (key_fullpath_size < (sizeof(applicationhive_fullpath) - 1 ) || + memcmp( key_fullpath, applicationhive_fullpath, sizeof(applicationhive_fullpath) - 2 )) + { + set_error( STATUS_PRIVILEGE_NOT_HELD ); + } + free( key_fullpath ); + + if (!get_error()) + load_registry( key, handle ); +} + /* load one of the initial registry files */ static int load_init_registry_from_file( const char *filename, struct key *key ) { @@ -1853,10 +1876,12 @@ void init_registry(void) 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\', 'P','e','r','f','l','i','b','\', '0','0','9'}; + static const WCHAR application[] = {'A'}; static const struct unicode_str root_name = { REGISTRY, sizeof(REGISTRY) }; static const struct unicode_str HKLM_name = { HKLM, sizeof(HKLM) }; static const struct unicode_str HKU_name = { HKU_default, sizeof(HKU_default) }; static const struct unicode_str perflib_name = { perflib, sizeof(perflib) }; + static const struct unicode_str application_name = { application, sizeof(application) };
WCHAR *current_user_path; struct unicode_str current_user_str; @@ -1934,6 +1959,11 @@ void init_registry(void) release_object( key ); }
+ /* create application hive */ + if (!(key = create_key_recursive( root_key, &application_name, current_time ))) + fatal_error( "could not create \REGISTRY\A registry key\n" ); + release_object(key); + release_object( hklm ); release_object( hkcu );
@@ -2285,7 +2315,7 @@ DECL_HANDLER(load_registry)
if (!objattr) return;
- if (!thread_single_check_privilege( current, SeRestorePrivilege )) + if (!(req->flags & LOAD_APP_KEY) && !thread_single_check_privilege( current, SeRestorePrivilege )) { set_error( STATUS_PRIVILEGE_NOT_HELD ); return; @@ -2297,7 +2327,18 @@ DECL_HANDLER(load_registry)
if ((key = create_key( parent, &name, 0, KEY_WOW64_64KEY, 0, sd ))) { - load_registry( key, req->file ); + if (req->flags & LOAD_APP_KEY) + load_app_registry( key, req->file ); + else + load_registry( key, req->file ); + + if (!get_error()) + reply->hkey = alloc_handle( current->process, key, req->access, objattr->attributes ); + else + { + reply->hkey = 0; + delete_key( key, 1 ); + } release_object( key ); } if (parent) release_object( parent ); diff --git a/server/request.h b/server/request.h index 9e943cceb3c..c10d98691ba 100644 --- a/server/request.h +++ b/server/request.h @@ -1231,7 +1231,11 @@ C_ASSERT( sizeof(struct enum_key_value_reply) == 24 ); C_ASSERT( FIELD_OFFSET(struct delete_key_value_request, hkey) == 12 ); C_ASSERT( sizeof(struct delete_key_value_request) == 16 ); C_ASSERT( FIELD_OFFSET(struct load_registry_request, file) == 12 ); -C_ASSERT( sizeof(struct load_registry_request) == 16 ); +C_ASSERT( FIELD_OFFSET(struct load_registry_request, flags) == 16 ); +C_ASSERT( FIELD_OFFSET(struct load_registry_request, access) == 20 ); +C_ASSERT( sizeof(struct load_registry_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct load_registry_reply, hkey) == 8 ); +C_ASSERT( sizeof(struct load_registry_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct unload_registry_request, parent) == 12 ); C_ASSERT( FIELD_OFFSET(struct unload_registry_request, attributes) == 16 ); C_ASSERT( sizeof(struct unload_registry_request) == 24 ); diff --git a/server/trace.c b/server/trace.c index c6a324bb905..b7a4c47849f 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2407,9 +2407,16 @@ static void dump_delete_key_value_request( const struct delete_key_value_request static void dump_load_registry_request( const struct load_registry_request *req ) { fprintf( stderr, " file=%04x", req->file ); + fprintf( stderr, ", flags=%08x", req->flags ); + fprintf( stderr, ", access=%08x", req->access ); dump_varargs_object_attributes( ", objattr=", cur_size ); }
+static void dump_load_registry_reply( const struct load_registry_reply *req ) +{ + fprintf( stderr, " hkey=%04x", req->hkey ); +} + static void dump_unload_registry_request( const struct unload_registry_request *req ) { fprintf( stderr, " parent=%04x", req->parent ); @@ -4869,7 +4876,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_get_key_value_reply, (dump_func)dump_enum_key_value_reply, NULL, - NULL, + (dump_func)dump_load_registry_reply, NULL, NULL, NULL,
From: Santino Mazza smazza@codeweavers.com
Signed-off-by: Santino Mazza smazza@codweavers.com --- dlls/advapi32/tests/registry.c | 6 +-- dlls/kernelbase/registry.c | 70 ++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 15 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 7bafc1ed42e..6d4053f5992 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -1615,8 +1615,8 @@ static void test_reg_load_app_key(void)
/* Test with non existant file */ ret = RegLoadAppKeyA("saved_app_key", &key1, KEY_READ, 0, 0); - ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); - ok(key1 != NULL, "got a null key\n"); + todo_wine ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %ld\n", ret); + todo_wine ok(key1 != NULL, "got a null key\n");
ret = GetFileAttributesA("saved_app_key"); todo_wine ok(ret != -1, "hive file didn't got created.\n"); @@ -1674,7 +1674,7 @@ static void test_reg_load_app_key(void) ok(key1 != NULL, "got a null key\n");
ret = RegCreateKeyA(key1, "testkey", &childkey); - todo_wine ok(ret == ERROR_SUCCESS || broken(ret == ERROR_INVALID_HANDLE) /* win7 */, "error when creating testkey. %ld\n", ret); + ok(ret == ERROR_SUCCESS || broken(ret == ERROR_INVALID_HANDLE) /* win7 */, "error when creating testkey. %ld\n", ret); RegCloseKey(key1);
hivefile = CreateFileA("saved_app_key", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, diff --git a/dlls/kernelbase/registry.c b/dlls/kernelbase/registry.c index 91462d80e06..4768e922816 100644 --- a/dlls/kernelbase/registry.c +++ b/dlls/kernelbase/registry.c @@ -3080,35 +3080,81 @@ cleanup: return ret; }
+static void generate_string_uuid(WCHAR *out, DWORD out_size) +{ + UUID uuid; + LARGE_INTEGER ft; + ULONG seed; + + NtQuerySystemTime(&ft); + seed = ft.LowPart; + for (int i = 0; i < sizeof(uuid); ++i) + ((UCHAR*)&uuid)[i] = (UCHAR)RtlRandom(&seed); + + + uuid.Data3 &= 0x0fff; + uuid.Data3 |= (4 << 12); + uuid.Data4[0] &= 0x3f; + uuid.Data4[0] |= 0x80; + + swprintf(out, out_size, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", uuid.Data1, + uuid.Data2, uuid.Data3, uuid.Data4[0], uuid.Data4[1], uuid.Data4[2], uuid.Data4[3], + uuid.Data4[4], uuid.Data4[5], uuid.Data4[6], uuid.Data4[7]); +}
/****************************************************************************** * RegLoadAppKeyA (kernelbase.@) * */ -LSTATUS WINAPI RegLoadAppKeyA(const char *file, HKEY *result, REGSAM sam, DWORD options, DWORD reserved) +LSTATUS WINAPI RegLoadAppKeyA(const char *filename, HKEY *result, REGSAM sam, DWORD options, DWORD reserved) { - FIXME("%s %p %lu %lu %lu: stub\n", wine_dbgstr_a(file), result, sam, options, reserved); + UNICODE_STRING filenameW; + LSTATUS status; + FIXME("%s %p %lu %lu %lu: stub\n", wine_dbgstr_a(filename), result, sam, options, reserved);
- if (!file || reserved) - return ERROR_INVALID_PARAMETER; - - *result = (HKEY)0xdeadbeef; - return ERROR_SUCCESS; + RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); + status = RegLoadAppKeyW(filenameW.Buffer, result, sam, options, reserved); + RtlFreeUnicodeString(&filenameW); + return status; }
/****************************************************************************** * RegLoadAppKeyW (kernelbase.@) * */ -LSTATUS WINAPI RegLoadAppKeyW(const WCHAR *file, HKEY *result, REGSAM sam, DWORD options, DWORD reserved) +LSTATUS WINAPI RegLoadAppKeyW(const WCHAR *filename, HKEY *result, REGSAM sam, DWORD options, DWORD reserved) { - FIXME("%s %p %lu %lu %lu: stub\n", wine_dbgstr_w(file), result, sam, options, reserved); + NTSTATUS status; + WCHAR application_root[13] = L"\REGISTRY\A\"; + WCHAR rootguid_str[39]; + WCHAR *destkey_path_tmp; + UNICODE_STRING destkey_path, filenameW; + OBJECT_ATTRIBUTES destkey, file; + + FIXME("%s %p %lu %lu %lu: stub\n", wine_dbgstr_w(filename), result, sam, options, reserved);
- if (!file || reserved) + if (!filename || reserved) return ERROR_INVALID_PARAMETER;
- *result = (HKEY)0xdeadbeef; - return ERROR_SUCCESS; + InitializeObjectAttributes(&destkey, &destkey_path, 0, 0, 0); + RtlDosPathNameToNtPathName_U(filename, &filenameW, NULL, NULL); + InitializeObjectAttributes(&file, &filenameW, 0, 0, 0); + + generate_string_uuid(rootguid_str, sizeof(rootguid_str)); + + destkey_path_tmp = heap_alloc_zero(sizeof(application_root) + sizeof(rootguid_str)); + wcscat(destkey_path_tmp, application_root); + wcscat(destkey_path_tmp, rootguid_str); + + RtlCreateUnicodeString(&destkey_path, destkey_path_tmp); + heap_free(destkey_path_tmp); + + status = NtLoadKeyEx(&destkey, &file, 0x10 /* LOAD_APP_KEY flag */, 0, 0, sam, (HANDLE *)result, 0); + + RtlFreeUnicodeString(&destkey_path); + RtlFreeUnicodeString(&filenameW); + + return RtlNtStatusToDosError(status); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=122007
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
advapi32: registry.c:1635: Test failed: expected ERROR_SUCCESS, got 183
=== w7u_el (32 bit report) ===
advapi32: registry.c:1635: Test failed: expected ERROR_SUCCESS, got 183
From: Santino Mazza mazzasantino1206@gmail.com
This change simplifies the code for future changes in load_registry and load_app_registry.
Signed-off-by: Santino Mazza smazza@codeweavers.com --- dlls/ntdll/unix/registry.c | 12 +++--------- include/wine/server_protocol.h | 5 +++-- server/protocol.def | 2 +- server/registry.c | 32 ++++++++++++++------------------ server/request.h | 5 ++--- server/trace.c | 4 ++-- 6 files changed, 25 insertions(+), 35 deletions(-)
diff --git a/dlls/ntdll/unix/registry.c b/dlls/ntdll/unix/registry.c index c5766ab1f1e..8e30a55bc19 100644 --- a/dlls/ntdll/unix/registry.c +++ b/dlls/ntdll/unix/registry.c @@ -700,7 +700,6 @@ NTSTATUS WINAPI NtLoadKeyEx( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *f HANDLE event, ACCESS_MASK access, HANDLE *roothandle, IO_STATUS_BLOCK *iostatus ) { NTSTATUS ret; - HANDLE key; data_size_t len; struct object_attributes *objattr; char *unix_name; @@ -712,12 +711,7 @@ NTSTATUS WINAPI NtLoadKeyEx( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *f if (roothandle) *roothandle = NULL;
get_redirect( &new_attr, &nt_name ); - if (!(ret = nt_to_unix_file_name( &new_attr, &unix_name, FILE_OPEN ))) - { - ret = open_unix_file( &key, unix_name, GENERIC_READ | SYNCHRONIZE, - &new_attr, 0, 0, FILE_OPEN, 0, NULL, 0 ); - free( unix_name ); - } + ret = nt_to_unix_file_name( &new_attr, &unix_name, FILE_OPEN ); free( nt_name.Buffer );
if (ret) return ret; @@ -727,10 +721,10 @@ NTSTATUS WINAPI NtLoadKeyEx( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *f
SERVER_START_REQ( load_registry ) { - req->file = wine_server_obj_handle( key ); req->flags = flags; req->access = access; wine_server_add_data( req, objattr, len ); + wine_server_add_data( req, unix_name, strlen(unix_name) + 1 ); ret = wine_server_call( req ); if (roothandle) *roothandle = wine_server_ptr_handle( reply->hkey ); @@ -740,7 +734,7 @@ NTSTATUS WINAPI NtLoadKeyEx( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *f } SERVER_END_REQ;
- NtClose( key ); + free( unix_name ); free( objattr ); return ret; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 220a1ace665..3343c0de396 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2360,10 +2360,11 @@ struct delete_key_value_reply struct load_registry_request { struct request_header __header; - obj_handle_t file; unsigned int flags; unsigned int access; /* VARARG(objattr,object_attributes); */ + /* VARARG(filename,string); */ + char __pad_20[4]; }; struct load_registry_reply { @@ -6328,7 +6329,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 756 +#define SERVER_PROTOCOL_VERSION 757
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index defe071a722..4e0c4b905db 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1825,10 +1825,10 @@ struct process_info
/* Load a registry branch from a file */ @REQ(load_registry) - obj_handle_t file; /* file to load from */ unsigned int flags; /* flags */ unsigned int access; /* wanted access rights */ VARARG(objattr,object_attributes); /* object attributes */ + VARARG(filename,string); /* file to load name */ @REPLY obj_handle_t hkey; /* handle to root key */ @END diff --git a/server/registry.c b/server/registry.c index 7ce7a27eacf..d88797d7591 100644 --- a/server/registry.c +++ b/server/registry.c @@ -1751,27 +1751,20 @@ static void load_keys( struct key *key, const char *filename, FILE *f, int prefi }
/* load a part of the registry from a file */ -static void load_registry( struct key *key, obj_handle_t handle ) +static void load_registry( struct key *key, const char *filename ) { - struct file *file; - int fd; + FILE *f;
- if (!(file = get_file_obj( current->process, handle, FILE_READ_DATA ))) return; - fd = dup( get_file_unix_fd( file ) ); - release_object( file ); - if (fd != -1) + f = fopen( filename, "r" ); + if (f) { - FILE *f = fdopen( fd, "r" ); - if (f) - { - load_keys( key, NULL, f, -1 ); - fclose( f ); - } - else file_set_error(); + load_keys( key, NULL, f, -1 ); + fclose( f ); } + else file_set_error(); }
-static void load_app_registry( struct key *key, obj_handle_t handle ) +static void load_app_registry( struct key *key, const char *filename ) { WCHAR applicationhive_fullpath[12] = {'\', 'R', 'E', 'G', 'I', 'S', 'T', 'R', 'Y', '\', 'A'}; WCHAR *key_fullpath; @@ -1787,7 +1780,7 @@ static void load_app_registry( struct key *key, obj_handle_t handle ) free( key_fullpath );
if (!get_error()) - load_registry( key, handle ); + load_registry( key, filename ); }
/* load one of the initial registry files */ @@ -2310,8 +2303,11 @@ DECL_HANDLER(load_registry) { struct key *key, *parent = NULL; struct unicode_str name; + const char *filename; + data_size_t filename_len; const struct security_descriptor *sd; const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, NULL ); + filename = get_req_data_after_objattr(objattr, &filename_len);
if (!objattr) return;
@@ -2328,9 +2324,9 @@ DECL_HANDLER(load_registry) if ((key = create_key( parent, &name, 0, KEY_WOW64_64KEY, 0, sd ))) { if (req->flags & LOAD_APP_KEY) - load_app_registry( key, req->file ); + load_app_registry( key, filename ); else - load_registry( key, req->file ); + load_registry( key, filename );
if (!get_error()) reply->hkey = alloc_handle( current->process, key, req->access, objattr->attributes ); diff --git a/server/request.h b/server/request.h index c10d98691ba..faf66287b60 100644 --- a/server/request.h +++ b/server/request.h @@ -1230,9 +1230,8 @@ C_ASSERT( FIELD_OFFSET(struct enum_key_value_reply, namelen) == 16 ); C_ASSERT( sizeof(struct enum_key_value_reply) == 24 ); C_ASSERT( FIELD_OFFSET(struct delete_key_value_request, hkey) == 12 ); C_ASSERT( sizeof(struct delete_key_value_request) == 16 ); -C_ASSERT( FIELD_OFFSET(struct load_registry_request, file) == 12 ); -C_ASSERT( FIELD_OFFSET(struct load_registry_request, flags) == 16 ); -C_ASSERT( FIELD_OFFSET(struct load_registry_request, access) == 20 ); +C_ASSERT( FIELD_OFFSET(struct load_registry_request, flags) == 12 ); +C_ASSERT( FIELD_OFFSET(struct load_registry_request, access) == 16 ); C_ASSERT( sizeof(struct load_registry_request) == 24 ); C_ASSERT( FIELD_OFFSET(struct load_registry_reply, hkey) == 8 ); C_ASSERT( sizeof(struct load_registry_reply) == 16 ); diff --git a/server/trace.c b/server/trace.c index b7a4c47849f..97435dc7493 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2406,10 +2406,10 @@ static void dump_delete_key_value_request( const struct delete_key_value_request
static void dump_load_registry_request( const struct load_registry_request *req ) { - fprintf( stderr, " file=%04x", req->file ); - fprintf( stderr, ", flags=%08x", req->flags ); + fprintf( stderr, " flags=%08x", req->flags ); fprintf( stderr, ", access=%08x", req->access ); dump_varargs_object_attributes( ", objattr=", cur_size ); + dump_varargs_string( ", filename=", cur_size ); }
static void dump_load_registry_reply( const struct load_registry_reply *req )
From: Santino Mazza mazzasantino1206@gmail.com
Signed-off-by: Santino Mazza smazza@codeweavers.com --- dlls/advapi32/tests/registry.c | 2 +- server/registry.c | 36 +++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/dlls/advapi32/tests/registry.c b/dlls/advapi32/tests/registry.c index 6d4053f5992..f7a2c1b3682 100644 --- a/dlls/advapi32/tests/registry.c +++ b/dlls/advapi32/tests/registry.c @@ -1680,7 +1680,7 @@ static void test_reg_load_app_key(void) hivefile = CreateFileA("saved_app_key", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); size2 = GetFileSize(hivefile, NULL); - todo_wine ok(size2 > size1 || broken(size1 == size2) /* win7 */, "Expected file to increase size. %ld >= %ld\n", size1, size2); + ok(size2 > size1 || broken(size1 == size2) /* win7 */, "Expected file to increase size. %ld >= %ld\n", size1, size2); CloseHandle(hivefile);
DeleteFileA("saved_app_key"); diff --git a/server/registry.c b/server/registry.c index d88797d7591..eacac63ecd6 100644 --- a/server/registry.c +++ b/server/registry.c @@ -90,6 +90,7 @@ struct key unsigned int flags; /* flags */ timeout_t modif; /* last modification time */ struct list notify_list; /* list of notifications */ + FILE *file; /* loaded file */ };
/* key flags */ @@ -641,15 +642,6 @@ static void key_unlink_name( struct object *obj, struct object_name *name ) } }
-/* close the notification associated with a handle */ -static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) -{ - struct key * key = (struct key *) obj; - struct notify *notify = find_notify( key, process, handle ); - if (notify) do_notification( key, notify, 1 ); - return 1; /* ok to close */ -} - static void key_destroy( struct object *obj ) { int i; @@ -703,6 +695,7 @@ static struct key *create_key_object( struct object *parent, const struct unicod key->last_value = -1; key->values = NULL; key->modif = modif; + key->file = NULL; list_init( &key->notify_list );
if (options & REG_OPTION_CREATE_LINK) key->flags |= KEY_SYMLINK; @@ -1781,6 +1774,14 @@ static void load_app_registry( struct key *key, const char *filename )
if (!get_error()) load_registry( key, filename ); + + key->file = fopen(filename, "r+"); + if (!key->file) + { + file_set_error(); + return; + } + flockfile(key->file); }
/* load one of the initial registry files */ @@ -2142,6 +2143,23 @@ void flush_registry(void) if (fchdir( server_dir_fd ) == -1) fatal_error( "chdir to server dir: %s\n", strerror( errno )); }
+/* close the notification associated with a handle */ +static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) +{ + struct key * key = (struct key *) obj; + struct notify *notify = find_notify( key, process, handle ); + if (notify) do_notification( key, notify, 1 ); + if (key->file) + { + save_all_subkeys(key, key->file); + funlockfile(key->file); + if (fclose(key->file)) file_set_error(); + delete_key(key, 1); + } + return 1; /* ok to close */ +} + + /* determine if the thread is wow64 (32-bit client running on 64-bit prefix) */ static int is_wow64_thread( struct thread *thread ) {
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=122009
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
advapi32: registry.c:1635: Test failed: expected ERROR_SUCCESS, got 183