Initial implementation for registry application hives, this is a step forward to get Visual Studio to run. :-)
-- v4: server: save app hive into it's file when closing handle. server/registry: pass file name instead of file handle to server. kernelbase: Implement RegLoadAppKey.
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..e2707504c4f 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 || broken(ret == ERROR_ALREADY_EXISTS), "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();
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 | 42 ++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/dlls/ntdll/unix/registry.c b/dlls/ntdll/unix/registry.c index fae969763e6..9167197c9ec 100644 --- a/dlls/ntdll/unix/registry.c +++ b/dlls/ntdll/unix/registry.c @@ -680,6 +680,25 @@ NTSTATUS WINAPI NtFlushKey( HANDLE key ) * NtLoadKey (NTDLL.@) */ NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file ) +{ + TRACE("(%p,%p)", attr, 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 +708,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 +738,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 9167197c9ec..60956b1ace5 100644 --- a/dlls/ntdll/unix/registry.c +++ b/dlls/ntdll/unix/registry.c @@ -710,6 +710,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 ))) { @@ -727,8 +729,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( wine_server_ptr_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 e2707504c4f..555cc72451e 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..a0fa81118b9 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; + + TRACE("%s %p %lu %lu %lu\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); }
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 60956b1ace5..09a9dae3534 100644 --- a/dlls/ntdll/unix/registry.c +++ b/dlls/ntdll/unix/registry.c @@ -701,7 +701,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; @@ -713,12 +712,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; @@ -728,10 +722,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 ); @@ -741,7 +735,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 555cc72451e..81f3fb788ef 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 ) {
On Fri Aug 26 11:12:10 2022 +0000, Santino Mazza wrote:
I could pass the flags, but I'm not entirely sure if they are the same flags, obviously some flags should not be supported by NtLoadKey2, like the LOAD_APP_KEY flag as it needs an extra parameter for returning the loaded key.
according to some unofficial documentation, the only valid flags are REG_NO_LAZY_FLUSH and no flags, adding support for REG_NO_LAZY_FLUSH, should be all that is needed Since it's an undocumented function, it isn't used by many applications, so maybe we can ignore flags and get away with it for now
On Fri Aug 26 18:17:06 2022 +0000, Etaash Mathamsetty wrote:
according to some unofficial documentation (from two different sources), the only valid flags are REG_NO_LAZY_FLUSH and no flags, so adding support for REG_NO_LAZY_FLUSH should be all that is needed
That could be done in a different merge request, for this we only need NtLoadKeyEx and the load app flag
On Fri Aug 26 19:33:03 2022 +0000, Santino Mazza wrote:
That could be done in a different merge request, for this we only need NtLoadKeyEx and the load app flag
I think to reduce the spam made by that function you could say unhandled flag REG_NO_LAZY_FLUSH or something, since that's the only other flag it takes (other than no flags)