diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c index c3cb3cfd379..5ee66d722b2 100644 --- a/dlls/advapi32/registry.c +++ b/dlls/advapi32/registry.c @@ -1588,42 +1588,28 @@ DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name ) */ LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename ) { - HANDLE file; - DWORD ret, len, err = GetLastError(); - HKEY shkey; + OBJECT_ATTRIBUTES destkey, file; + UNICODE_STRING subkeyW, filenameW; - TRACE( "(%p,%s,%s)\n", hkey, debugstr_w(subkey), debugstr_w(filename) ); + if (!(hkey = get_special_root_hkey(hkey))) return ERROR_INVALID_HANDLE; - if (!filename || !*filename) return ERROR_INVALID_PARAMETER; - if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER; - if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; + destkey.Length = sizeof(destkey); + destkey.RootDirectory = hkey; /* root key: HKLM or HKU */ + destkey.ObjectName = &subkeyW; /* name of the key */ + destkey.Attributes = 0; + destkey.SecurityDescriptor = NULL; + destkey.SecurityQualityOfService = NULL; + RtlInitUnicodeString(&subkeyW, subkey); - len = strlenW( subkey ) * sizeof(WCHAR); - if (len > MAX_PATH*sizeof(WCHAR)) return ERROR_INVALID_PARAMETER; + file.Length = sizeof(file); + file.RootDirectory = NULL; + file.ObjectName = &filenameW; /* file containing the hive */ + file.Attributes = OBJ_CASE_INSENSITIVE; + file.SecurityDescriptor = NULL; + file.SecurityQualityOfService = NULL; + RtlDosPathNameToNtPathName_U(filename, &filenameW, NULL, NULL); - if ((file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE) - { - ret = GetLastError(); - goto done; - } - - RegCreateKeyW(hkey,subkey,&shkey); - - SERVER_START_REQ( load_registry ) - { - req->hkey = shkey; - req->file = file; - wine_server_add_data( req, subkey, len ); - ret = RtlNtStatusToDosError( wine_server_call(req) ); - } - SERVER_END_REQ; - CloseHandle( file ); - RegCloseKey(shkey); - - done: - SetLastError( err ); /* restore the last error code */ - return ret; + return RtlNtStatusToDosError( NtLoadKey(&destkey, &file) ); } @@ -1634,43 +1620,20 @@ LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename ) */ LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename ) { - WCHAR buffer[MAX_PATH]; - HANDLE file; - DWORD ret, len, err = GetLastError(); - HKEY shkey; + UNICODE_STRING subkeyW, filenameW; + STRING subkeyA, filenameA; + NTSTATUS status; - TRACE( "(%p,%s,%s)\n", hkey, debugstr_a(subkey), debugstr_a(filename) ); + RtlInitAnsiString(&subkeyA, subkey); + RtlInitAnsiString(&filenameA, filename); - if (!filename || !*filename) return ERROR_INVALID_PARAMETER; - if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER; - if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; + if ((status = RtlAnsiStringToUnicodeString(&subkeyW, &subkeyA, TRUE))) + return RtlNtStatusToDosError(status); - if (!(len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), buffer, MAX_PATH ))) - return ERROR_INVALID_PARAMETER; + if ((status = RtlAnsiStringToUnicodeString(&filenameW, &filenameA, TRUE))) + return RtlNtStatusToDosError(status); - if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE) - { - ret = GetLastError(); - goto done; - } - - RegCreateKeyA(hkey,subkey,&shkey); - - SERVER_START_REQ( load_registry ) - { - req->hkey = shkey; - req->file = file; - wine_server_add_data( req, buffer, len * sizeof(WCHAR) ); - ret = RtlNtStatusToDosError( wine_server_call(req) ); - } - SERVER_END_REQ; - CloseHandle( file ); - RegCloseKey(shkey); - - done: - SetLastError( err ); /* restore the last error code */ - return ret; + return RegLoadKeyW(hkey, subkeyW.Buffer, filenameW.Buffer); } diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c index 42287ee7949..283044b5f6b 100644 --- a/dlls/ntdll/reg.c +++ b/dlls/ntdll/reg.c @@ -558,12 +558,30 @@ NTSTATUS WINAPI NtFlushKey(HKEY key) * NtLoadKey [NTDLL.@] * ZwLoadKey [NTDLL.@] */ -NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file ) +NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file ) { - FIXME("stub!\n"); - dump_ObjectAttributes(attr); - dump_ObjectAttributes(file); - return STATUS_SUCCESS; + NTSTATUS ret; + HANDLE hive; + IO_STATUS_BLOCK io; + + TRACE("(%p,%p)\n", attr, file); + + ret = NtCreateFile(&hive, GENERIC_READ, file, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0, + OPEN_EXISTING, 0, NULL, 0); + if (ret) return ret; + + SERVER_START_REQ( load_registry ) + { + req->hkey = attr->RootDirectory; + req->file = hive; + wine_server_add_data(req, attr->ObjectName->Buffer, attr->ObjectName->Length); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + + NtClose(hive); + + return ret; } /****************************************************************************** diff --git a/include/winternl.h b/include/winternl.h index 320b1ab32ec..9deca751e45 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1449,7 +1449,7 @@ NTSTATUS WINAPI NtImpersonateAnonymousToken(HANDLE); NTSTATUS WINAPI NtImpersonateClientOfPort(HANDLE,PPORT_MESSAGE); NTSTATUS WINAPI NtImpersonateThread(HANDLE,HANDLE,PSECURITY_QUALITY_OF_SERVICE); NTSTATUS WINAPI NtLoadDriver(const UNICODE_STRING *); -NTSTATUS WINAPI NtLoadKey(const OBJECT_ATTRIBUTES *,const OBJECT_ATTRIBUTES *); +NTSTATUS WINAPI NtLoadKey(const OBJECT_ATTRIBUTES *,OBJECT_ATTRIBUTES *); NTSTATUS WINAPI NtLockFile(HANDLE,HANDLE,PIO_APC_ROUTINE,void*,PIO_STATUS_BLOCK,PLARGE_INTEGER,PLARGE_INTEGER,ULONG*,BOOLEAN,BOOLEAN); NTSTATUS WINAPI NtLockVirtualMemory(HANDLE,PVOID*,ULONG*,ULONG); NTSTATUS WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,ULONG,const LARGE_INTEGER*,ULONG*,SECTION_INHERIT,ULONG,ULONG); diff --git a/server/registry.c b/server/registry.c index 5b7474eafc6..370a6f02624 100644 --- a/server/registry.c +++ b/server/registry.c @@ -1834,13 +1834,18 @@ DECL_HANDLER(delete_key_value) /* load a registry branch from a file */ DECL_HANDLER(load_registry) { - struct key *key; + struct key *key, *parent; - if ((key = get_hkey_obj( req->hkey, KEY_SET_VALUE | KEY_CREATE_SUB_KEY ))) + if ((parent = get_hkey_obj( req->hkey, KEY_SET_VALUE | KEY_CREATE_SUB_KEY ))) { - /* FIXME: use subkey name */ - load_registry( key, req->file ); - release_object( key ); + int dummy; + WCHAR *name = copy_path( get_req_data(), get_req_data_size(), !req->hkey ); + if (name && (key = create_key( parent, name, NULL, KEY_DIRTY, time(NULL), &dummy ))) + { + load_registry( key, req->file ); + release_object( key ); + } + release_object( parent ); } }