diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index 874903a9ea1..dc2f19f9bd4 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -52,6 +52,7 @@ C_SRCS = \ unix/file.c \ unix/loader.c \ unix/process.c \ + unix/registry.c \ unix/serial.c \ unix/server.c \ unix/signal_arm.c \ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 4c8a1f6165a..a5c8b38219a 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -166,8 +166,8 @@ @ stdcall -syscall NtCreateIoCompletion(ptr long ptr long) @ stdcall -syscall NtCreateJobObject(ptr long ptr) # @ stub NtCreateJobSet -@ stdcall NtCreateKey(ptr long ptr long ptr long ptr) -@ stdcall NtCreateKeyTransacted(ptr long ptr long ptr long long ptr) +@ stdcall -syscall NtCreateKey(ptr long ptr long ptr long ptr) +@ stdcall -syscall NtCreateKeyTransacted(ptr long ptr long ptr long long ptr) @ stdcall -syscall NtCreateKeyedEvent(ptr long ptr long) @ stdcall NtCreateLowBoxToken(ptr long long ptr ptr long ptr long ptr) @ stdcall -syscall NtCreateMailslotFile(ptr long ptr ptr long long long ptr) @@ -195,24 +195,24 @@ @ stdcall NtDeleteAtom(long) # @ stub NtDeleteBootEntry @ stdcall -syscall NtDeleteFile(ptr) -@ stdcall NtDeleteKey(long) +@ stdcall -syscall NtDeleteKey(long) # @ stub NtDeleteObjectAuditAlarm -@ stdcall NtDeleteValueKey(long ptr) +@ stdcall -syscall NtDeleteValueKey(long ptr) @ stdcall -syscall NtDeviceIoControlFile(long long ptr ptr ptr long ptr long ptr long) @ stdcall NtDisplayString(ptr) @ stdcall -syscall NtDuplicateObject(long long long ptr long long long) @ stdcall NtDuplicateToken(long long ptr long long ptr) # @ stub NtEnumerateBootEntries @ stub NtEnumerateBus -@ stdcall NtEnumerateKey(long long long ptr long ptr) +@ stdcall -syscall NtEnumerateKey(long long long ptr long ptr) # @ stub NtEnumerateSystemEnvironmentValuesEx -@ stdcall NtEnumerateValueKey(long long long ptr long ptr) +@ stdcall -syscall NtEnumerateValueKey(long long long ptr long ptr) @ stub NtExtendSection # @ stub NtFilterToken @ stdcall NtFindAtom(ptr long ptr) @ stdcall -syscall NtFlushBuffersFile(long ptr) @ stdcall -syscall NtFlushInstructionCache(long ptr long) -@ stdcall NtFlushKey(long) +@ stdcall -syscall NtFlushKey(long) @ stdcall -syscall NtFlushProcessWriteBuffers() @ stdcall -syscall NtFlushVirtualMemory(long ptr ptr long) @ stub NtFlushWriteBuffer @@ -235,8 +235,8 @@ # @ stub NtIsSystemResumeAutomatic @ stdcall NtListenPort(ptr ptr) @ stdcall NtLoadDriver(ptr) -@ stdcall NtLoadKey2(ptr ptr long) -@ stdcall NtLoadKey(ptr ptr) +@ stdcall -syscall NtLoadKey2(ptr ptr long) +@ stdcall -syscall NtLoadKey(ptr ptr) @ stdcall NtLockFile(long long ptr ptr ptr ptr ptr ptr long long) # @ stub NtLockProductActivationKeys # @ stub NtLockRegistryKey @@ -248,18 +248,18 @@ @ stdcall -syscall NtMapViewOfSection(long long ptr long long ptr ptr long long long) # @ stub NtModifyBootEntry @ stdcall -syscall NtNotifyChangeDirectoryFile(long long ptr ptr ptr ptr long long long) -@ stdcall NtNotifyChangeKey(long long ptr ptr ptr long long ptr long long) -@ stdcall NtNotifyChangeMultipleKeys(long long ptr long ptr ptr ptr long long ptr long long) +@ stdcall -syscall NtNotifyChangeKey(long long ptr ptr ptr long long ptr long long) +@ stdcall -syscall NtNotifyChangeMultipleKeys(long long ptr long ptr ptr ptr long long ptr long long) @ stdcall NtOpenDirectoryObject(ptr long ptr) @ stdcall -syscall NtOpenEvent(ptr long ptr) @ stub NtOpenEventPair @ stdcall -syscall NtOpenFile(ptr long ptr ptr long long) @ stdcall -syscall NtOpenIoCompletion(ptr long ptr) @ stdcall -syscall NtOpenJobObject(ptr long ptr) -@ stdcall NtOpenKey(ptr long ptr) -@ stdcall NtOpenKeyEx(ptr long ptr long) -@ stdcall NtOpenKeyTransacted(ptr long ptr long) -@ stdcall NtOpenKeyTransactedEx(ptr long ptr long long) +@ stdcall -syscall NtOpenKey(ptr long ptr) +@ stdcall -syscall NtOpenKeyEx(ptr long ptr long) +@ stdcall -syscall NtOpenKeyTransacted(ptr long ptr long) +@ stdcall -syscall NtOpenKeyTransactedEx(ptr long ptr long long) @ stdcall -syscall NtOpenKeyedEvent(ptr long ptr) @ stdcall -syscall NtOpenMutant(ptr long ptr) @ stub NtOpenObjectAuditAlarm @@ -301,9 +301,9 @@ @ stdcall NtQueryInstallUILanguage(ptr) @ stub NtQueryIntervalProfile @ stdcall -syscall NtQueryIoCompletion(long long ptr long ptr) -@ stdcall NtQueryKey (long long ptr long ptr) -@ stdcall NtQueryLicenseValue(ptr ptr ptr long ptr) -@ stdcall NtQueryMultipleValueKey(long ptr long ptr long ptr) +@ stdcall -syscall NtQueryKey(long long ptr long ptr) +@ stdcall -syscall NtQueryLicenseValue(ptr ptr ptr long ptr) +@ stdcall -syscall NtQueryMultipleValueKey(long ptr long ptr long ptr) @ stdcall -syscall NtQueryMutant(long long ptr long ptr) @ stdcall -syscall NtQueryObject(long long ptr long ptr) @ stub NtQueryOpenSubKeys @@ -321,7 +321,7 @@ @ stdcall -syscall NtQuerySystemTime(ptr) @ stdcall -syscall NtQueryTimer(ptr long ptr long ptr) @ stdcall NtQueryTimerResolution(ptr ptr ptr) -@ stdcall NtQueryValueKey(long ptr long ptr long ptr) +@ stdcall -syscall NtQueryValueKey(long ptr long ptr long ptr) @ stdcall -syscall NtQueryVirtualMemory(long ptr long ptr long ptr) @ stdcall -syscall NtQueryVolumeInformationFile(long ptr ptr long long) @ stdcall -syscall NtQueueApcThread(long ptr long long long) @@ -340,8 +340,8 @@ @ stdcall -syscall NtRemoveIoCompletion(ptr ptr ptr ptr ptr) @ stdcall -syscall NtRemoveIoCompletionEx(ptr ptr long ptr ptr long) # @ stub NtRemoveProcessDebug -@ stdcall NtRenameKey(long ptr) -@ stdcall NtReplaceKey(ptr long ptr) +@ stdcall -syscall NtRenameKey(long ptr) +@ stdcall -syscall NtReplaceKey(ptr long ptr) @ stub NtReplyPort @ stdcall NtReplyWaitReceivePort(ptr ptr ptr ptr) @ stub NtReplyWaitReceivePortEx @@ -352,10 +352,10 @@ # @ stub NtRequestWakeupLatency @ stdcall -syscall NtResetEvent(long ptr) @ stdcall -syscall NtResetWriteWatch(long ptr long) -@ stdcall NtRestoreKey(long long long) +@ stdcall -syscall NtRestoreKey(long long long) @ stdcall -syscall NtResumeProcess(long) @ stdcall -syscall NtResumeThread(long ptr) -@ stdcall NtSaveKey(long long) +@ stdcall -syscall NtSaveKey(long long) # @ stub NtSaveKeyEx # @ stub NtSaveMergedKeys @ stdcall NtSecureConnectPort(ptr ptr ptr ptr ptr ptr ptr ptr ptr) @@ -375,7 +375,7 @@ # @ stub NtSetInformationDebugObject @ stdcall -syscall NtSetInformationFile(long ptr ptr long long) @ stdcall -syscall NtSetInformationJobObject(long long ptr long) -@ stdcall NtSetInformationKey(long long ptr long) +@ stdcall -syscall NtSetInformationKey(long long ptr long) @ stdcall -syscall NtSetInformationObject(long long ptr long) @ stdcall -syscall NtSetInformationProcess(long long ptr long) @ stdcall -syscall NtSetInformationThread(long long ptr long) @@ -398,7 +398,7 @@ @ stdcall -syscall NtSetTimer(long ptr ptr ptr long long ptr) @ stdcall NtSetTimerResolution(long long ptr) # @ stub NtSetUuidSeed -@ stdcall NtSetValueKey(long ptr long long ptr long) +@ stdcall -syscall NtSetValueKey(long ptr long long ptr long) @ stdcall -syscall NtSetVolumeInformationFile(long ptr ptr long long) @ stdcall NtShutdownSystem(long) @ stdcall -syscall NtSignalAndWaitForSingleObject(long long long ptr) @@ -414,7 +414,7 @@ # @ stub NtTraceEvent # @ stub NtTranslateFilePath @ stdcall NtUnloadDriver(ptr) -@ stdcall NtUnloadKey(ptr) +@ stdcall -syscall NtUnloadKey(ptr) @ stub NtUnloadKeyEx @ stdcall NtUnlockFile(long ptr ptr ptr ptr) @ stdcall -syscall NtUnlockVirtualMemory(long ptr ptr long) @@ -1155,8 +1155,8 @@ @ stdcall -private -syscall ZwCreateIoCompletion(ptr long ptr long) NtCreateIoCompletion @ stdcall -private -syscall ZwCreateJobObject(ptr long ptr) NtCreateJobObject # @ stub ZwCreateJobSet -@ stdcall -private ZwCreateKey(ptr long ptr long ptr long ptr) NtCreateKey -@ stdcall -private ZwCreateKeyTransacted(ptr long ptr long ptr long long ptr) NtCreateKeyTransacted +@ stdcall -private -syscall ZwCreateKey(ptr long ptr long ptr long ptr) NtCreateKey +@ stdcall -private -syscall ZwCreateKeyTransacted(ptr long ptr long ptr long long ptr) NtCreateKeyTransacted @ stdcall -private -syscall ZwCreateKeyedEvent(ptr long ptr long) NtCreateKeyedEvent @ stdcall -private -syscall ZwCreateMailslotFile(ptr long ptr ptr long long long ptr) NtCreateMailslotFile @ stdcall -private -syscall ZwCreateMutant(ptr long ptr long) NtCreateMutant @@ -1182,24 +1182,24 @@ @ stdcall -private ZwDeleteAtom(long) NtDeleteAtom # @ stub ZwDeleteBootEntry @ stdcall -private -syscall ZwDeleteFile(ptr) NtDeleteFile -@ stdcall -private ZwDeleteKey(long) NtDeleteKey +@ stdcall -private -syscall ZwDeleteKey(long) NtDeleteKey # @ stub ZwDeleteObjectAuditAlarm -@ stdcall -private ZwDeleteValueKey(long ptr) NtDeleteValueKey +@ stdcall -private -syscall ZwDeleteValueKey(long ptr) NtDeleteValueKey @ stdcall -private -syscall ZwDeviceIoControlFile(long long ptr ptr ptr long ptr long ptr long) NtDeviceIoControlFile @ stdcall -private ZwDisplayString(ptr) NtDisplayString @ stdcall -private -syscall ZwDuplicateObject(long long long ptr long long long) NtDuplicateObject @ stdcall -private ZwDuplicateToken(long long ptr long long ptr) NtDuplicateToken # @ stub ZwEnumerateBootEntries @ stub ZwEnumerateBus -@ stdcall -private ZwEnumerateKey(long long long ptr long ptr) NtEnumerateKey +@ stdcall -private -syscall ZwEnumerateKey(long long long ptr long ptr) NtEnumerateKey # @ stub ZwEnumerateSystemEnvironmentValuesEx -@ stdcall -private ZwEnumerateValueKey(long long long ptr long ptr) NtEnumerateValueKey +@ stdcall -private -syscall ZwEnumerateValueKey(long long long ptr long ptr) NtEnumerateValueKey @ stub ZwExtendSection # @ stub ZwFilterToken @ stdcall -private ZwFindAtom(ptr long ptr) NtFindAtom @ stdcall -private -syscall ZwFlushBuffersFile(long ptr) NtFlushBuffersFile @ stdcall -private -syscall ZwFlushInstructionCache(long ptr long) NtFlushInstructionCache -@ stdcall -private ZwFlushKey(long) NtFlushKey +@ stdcall -private -syscall ZwFlushKey(long) NtFlushKey @ stdcall -private -syscall ZwFlushProcessWriteBuffers() NtFlushProcessWriteBuffers @ stdcall -private -syscall ZwFlushVirtualMemory(long ptr ptr long) NtFlushVirtualMemory @ stub ZwFlushWriteBuffer @@ -1222,8 +1222,8 @@ # @ stub ZwIsSystemResumeAutomatic @ stdcall -private ZwListenPort(ptr ptr) NtListenPort @ stdcall -private ZwLoadDriver(ptr) NtLoadDriver -@ stdcall -private ZwLoadKey2(ptr ptr long) NtLoadKey2 -@ stdcall -private ZwLoadKey(ptr ptr) NtLoadKey +@ stdcall -private -syscall ZwLoadKey2(ptr ptr long) NtLoadKey2 +@ stdcall -private -syscall ZwLoadKey(ptr ptr) NtLoadKey @ stdcall -private ZwLockFile(long long ptr ptr ptr ptr ptr ptr long long) NtLockFile # @ stub ZwLockProductActivationKeys # @ stub ZwLockRegistryKey @@ -1235,18 +1235,18 @@ @ stdcall -private -syscall ZwMapViewOfSection(long long ptr long long ptr ptr long long long) NtMapViewOfSection # @ stub ZwModifyBootEntry @ stdcall -private -syscall ZwNotifyChangeDirectoryFile(long long ptr ptr ptr ptr long long long) NtNotifyChangeDirectoryFile -@ stdcall -private ZwNotifyChangeKey(long long ptr ptr ptr long long ptr long long) NtNotifyChangeKey -@ stdcall -private ZwNotifyChangeMultipleKeys(long long ptr long ptr ptr ptr long long ptr long long) NtNotifyChangeMultipleKeys +@ stdcall -private -syscall ZwNotifyChangeKey(long long ptr ptr ptr long long ptr long long) NtNotifyChangeKey +@ stdcall -private -syscall ZwNotifyChangeMultipleKeys(long long ptr long ptr ptr ptr long long ptr long long) NtNotifyChangeMultipleKeys @ stdcall -private ZwOpenDirectoryObject(ptr long ptr) NtOpenDirectoryObject @ stdcall -private -syscall ZwOpenEvent(ptr long ptr) NtOpenEvent @ stub ZwOpenEventPair @ stdcall -private -syscall ZwOpenFile(ptr long ptr ptr long long) NtOpenFile @ stdcall -private -syscall ZwOpenIoCompletion(ptr long ptr) NtOpenIoCompletion @ stdcall -private -syscall ZwOpenJobObject(ptr long ptr) NtOpenJobObject -@ stdcall -private ZwOpenKey(ptr long ptr) NtOpenKey -@ stdcall -private ZwOpenKeyEx(ptr long ptr long) NtOpenKeyEx -@ stdcall -private ZwOpenKeyTransacted(ptr long ptr long) NtOpenKeyTransacted -@ stdcall -private ZwOpenKeyTransactedEx(ptr long ptr long long) NtOpenKeyTransactedEx +@ stdcall -private -syscall ZwOpenKey(ptr long ptr) NtOpenKey +@ stdcall -private -syscall ZwOpenKeyEx(ptr long ptr long) NtOpenKeyEx +@ stdcall -private -syscall ZwOpenKeyTransacted(ptr long ptr long) NtOpenKeyTransacted +@ stdcall -private -syscall ZwOpenKeyTransactedEx(ptr long ptr long long) NtOpenKeyTransactedEx @ stdcall -private -syscall ZwOpenKeyedEvent(ptr long ptr) NtOpenKeyedEvent @ stdcall -private -syscall ZwOpenMutant(ptr long ptr) NtOpenMutant @ stub ZwOpenObjectAuditAlarm @@ -1288,9 +1288,9 @@ @ stdcall -private ZwQueryInstallUILanguage(ptr) NtQueryInstallUILanguage @ stub ZwQueryIntervalProfile @ stdcall -private -syscall ZwQueryIoCompletion(long long ptr long ptr) NtQueryIoCompletion -@ stdcall -private ZwQueryKey(long long ptr long ptr) NtQueryKey -@ stdcall -private ZwQueryLicenseValue(ptr ptr ptr long ptr) NtQueryLicenseValue -@ stdcall -private ZwQueryMultipleValueKey(long ptr long ptr long ptr) NtQueryMultipleValueKey +@ stdcall -private -syscall ZwQueryKey(long long ptr long ptr) NtQueryKey +@ stdcall -private -syscall ZwQueryLicenseValue(ptr ptr ptr long ptr) NtQueryLicenseValue +@ stdcall -private -syscall ZwQueryMultipleValueKey(long ptr long ptr long ptr) NtQueryMultipleValueKey @ stdcall -private -syscall ZwQueryMutant(long long ptr long ptr) NtQueryMutant @ stdcall -private -syscall ZwQueryObject(long long ptr long ptr) NtQueryObject @ stub ZwQueryOpenSubKeys @@ -1308,7 +1308,7 @@ @ stdcall -private -syscall ZwQuerySystemTime(ptr) NtQuerySystemTime @ stdcall -private -syscall ZwQueryTimer(ptr long ptr long ptr) NtQueryTimer @ stdcall -private ZwQueryTimerResolution(ptr ptr ptr) NtQueryTimerResolution -@ stdcall -private ZwQueryValueKey(long ptr long ptr long ptr) NtQueryValueKey +@ stdcall -private -syscall ZwQueryValueKey(long ptr long ptr long ptr) NtQueryValueKey @ stdcall -private -syscall ZwQueryVirtualMemory(long ptr long ptr long ptr) NtQueryVirtualMemory @ stdcall -private -syscall ZwQueryVolumeInformationFile(long ptr ptr long long) NtQueryVolumeInformationFile @ stdcall -private -syscall ZwQueueApcThread(long ptr long long long) NtQueueApcThread @@ -1327,8 +1327,8 @@ @ stdcall -private -syscall ZwRemoveIoCompletion(ptr ptr ptr ptr ptr) NtRemoveIoCompletion @ stdcall -private -syscall ZwRemoveIoCompletionEx(ptr ptr long ptr ptr long) NtRemoveIoCompletionEx # @ stub ZwRemoveProcessDebug -@ stdcall -private ZwRenameKey(long ptr) NtRenameKey -@ stdcall -private ZwReplaceKey(ptr long ptr) NtReplaceKey +@ stdcall -private -syscall ZwRenameKey(long ptr) NtRenameKey +@ stdcall -private -syscall ZwReplaceKey(ptr long ptr) NtReplaceKey @ stub ZwReplyPort @ stdcall -private ZwReplyWaitReceivePort(ptr ptr ptr ptr) NtReplyWaitReceivePort @ stub ZwReplyWaitReceivePortEx @@ -1339,10 +1339,10 @@ # @ stub ZwRequestWakeupLatency @ stdcall -private -syscall ZwResetEvent(long ptr) NtResetEvent @ stdcall -private -syscall ZwResetWriteWatch(long ptr long) NtResetWriteWatch -@ stdcall -private ZwRestoreKey(long long long) NtRestoreKey +@ stdcall -private -syscall ZwRestoreKey(long long long) NtRestoreKey @ stdcall -private -syscall ZwResumeProcess(long) NtResumeProcess @ stdcall -private -syscall ZwResumeThread(long ptr) NtResumeThread -@ stdcall -private ZwSaveKey(long long) NtSaveKey +@ stdcall -private -syscall ZwSaveKey(long long) NtSaveKey # @ stub ZwSaveKeyEx # @ stub ZwSaveMergedKeys @ stdcall -private ZwSecureConnectPort(ptr ptr ptr ptr ptr ptr ptr ptr ptr) NtSecureConnectPort @@ -1362,7 +1362,7 @@ # @ stub ZwSetInformationDebugObject @ stdcall -private -syscall ZwSetInformationFile(long ptr ptr long long) NtSetInformationFile @ stdcall -private -syscall ZwSetInformationJobObject(long long ptr long) NtSetInformationJobObject -@ stdcall -private ZwSetInformationKey(long long ptr long) NtSetInformationKey +@ stdcall -private -syscall ZwSetInformationKey(long long ptr long) NtSetInformationKey @ stdcall -private -syscall ZwSetInformationObject(long long ptr long) NtSetInformationObject @ stdcall -private -syscall ZwSetInformationProcess(long long ptr long) NtSetInformationProcess @ stdcall -private -syscall ZwSetInformationThread(long long ptr long) NtSetInformationThread @@ -1385,7 +1385,7 @@ @ stdcall -private -syscall ZwSetTimer(long ptr ptr ptr long long ptr) NtSetTimer @ stdcall -private ZwSetTimerResolution(long long ptr) NtSetTimerResolution # @ stub ZwSetUuidSeed -@ stdcall -private ZwSetValueKey(long ptr long long ptr long) NtSetValueKey +@ stdcall -private -syscall ZwSetValueKey(long ptr long long ptr long) NtSetValueKey @ stdcall -private -syscall ZwSetVolumeInformationFile(long ptr ptr long long) NtSetVolumeInformationFile @ stdcall -private ZwShutdownSystem(long) NtShutdownSystem @ stdcall -private -syscall ZwSignalAndWaitForSingleObject(long long long ptr) NtSignalAndWaitForSingleObject @@ -1401,7 +1401,7 @@ # @ stub ZwTraceEvent # @ stub ZwTranslateFilePath @ stdcall -private ZwUnloadDriver(ptr) NtUnloadDriver -@ stdcall -private ZwUnloadKey(ptr) NtUnloadKey +@ stdcall -private -syscall ZwUnloadKey(ptr) NtUnloadKey @ stub ZwUnloadKeyEx @ stdcall -private ZwUnlockFile(long ptr ptr ptr ptr) NtUnlockFile @ stdcall -private -syscall ZwUnlockVirtualMemory(long ptr ptr long) NtUnlockVirtualMemory diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c index fb5b3051025..5a54d7fee26 100644 --- a/dlls/ntdll/reg.c +++ b/dlls/ntdll/reg.c @@ -37,60 +37,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(reg); -/* maximum length of a value name in bytes (without terminating null) */ -#define MAX_VALUE_LENGTH (16383 * sizeof(WCHAR)) - -/****************************************************************************** - * NtCreateKey [NTDLL.@] - * ZwCreateKey [NTDLL.@] - */ -NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, - ULONG TitleIndex, const UNICODE_STRING *class, ULONG options, - PULONG dispos ) -{ - NTSTATUS ret; - data_size_t len; - struct object_attributes *objattr; - - if (!retkey || !attr) return STATUS_ACCESS_VIOLATION; - if (attr->Length > sizeof(OBJECT_ATTRIBUTES)) return STATUS_INVALID_PARAMETER; - - TRACE( "(%p,%s,%s,%x,%x,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName), - debugstr_us(class), options, access, retkey ); - - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - - SERVER_START_REQ( create_key ) - { - req->access = access; - req->options = options; - wine_server_add_data( req, objattr, len ); - if (class) wine_server_add_data( req, class->Buffer, class->Length ); - ret = wine_server_call( req ); - *retkey = wine_server_ptr_handle( reply->hkey ); - if (dispos && !ret) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; - } - SERVER_END_REQ; - - TRACE("<- %p\n", *retkey); - RtlFreeHeap( GetProcessHeap(), 0, objattr ); - return ret; -} - -NTSTATUS WINAPI NtCreateKeyTransacted( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, - ULONG TitleIndex, const UNICODE_STRING *class, ULONG options, - HANDLE transacted, ULONG *dispos ) -{ - FIXME( "(%p,%s,%s,%x,%x,%p,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName), - debugstr_us(class), options, access, transacted, retkey ); - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS WINAPI NtRenameKey( HANDLE handle, UNICODE_STRING *name ) -{ - FIXME( "(%p %s)\n", handle, debugstr_us(name) ); - return STATUS_NOT_IMPLEMENTED; -} /****************************************************************************** * RtlpNtCreateKey [NTDLL.@] @@ -113,67 +59,6 @@ NTSTATUS WINAPI RtlpNtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJEC return NtCreateKey(retkey, access, attr, 0, NULL, 0, dispos); } -static NTSTATUS open_key( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, ULONG options ) -{ - NTSTATUS ret; - - if (!retkey || !attr || !attr->ObjectName) return STATUS_ACCESS_VIOLATION; - if ((ret = validate_open_object_attributes( attr ))) return ret; - - TRACE( "(%p,%s,%x,%p)\n", attr->RootDirectory, - debugstr_us(attr->ObjectName), access, retkey ); - if (options & ~REG_OPTION_OPEN_LINK) - FIXME("options %x not implemented\n", options); - - SERVER_START_REQ( open_key ) - { - req->parent = wine_server_obj_handle( attr->RootDirectory ); - req->access = access; - req->attributes = attr->Attributes; - wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length ); - ret = wine_server_call( req ); - *retkey = wine_server_ptr_handle( reply->hkey ); - } - SERVER_END_REQ; - TRACE("<- %p\n", *retkey); - return ret; -} - -/****************************************************************************** - * NtOpenKeyEx [NTDLL.@] - * ZwOpenKeyEx [NTDLL.@] - */ -NTSTATUS WINAPI NtOpenKeyEx( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, ULONG options ) -{ - return open_key( retkey, access, attr, options ); -} - -/****************************************************************************** - * NtOpenKey [NTDLL.@] - * ZwOpenKey [NTDLL.@] - * - * OUT HANDLE retkey (returns 0 when failure) - * IN ACCESS_MASK access - * IN POBJECT_ATTRIBUTES attr - */ -NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr ) -{ - return open_key( retkey, access, attr, 0 ); -} - -NTSTATUS WINAPI NtOpenKeyTransactedEx( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, - ULONG options, HANDLE transaction ) -{ - FIXME( "(%p %x %p %x %p)\n", retkey, access, attr, options, transaction ); - return STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS WINAPI NtOpenKeyTransacted( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, - HANDLE transaction ) -{ - return NtOpenKeyTransactedEx( retkey, access, attr, 0, transaction ); -} - /****************************************************************************** * RtlpNtOpenKey [NTDLL.@] * @@ -186,25 +71,6 @@ NTSTATUS WINAPI RtlpNtOpenKey( PHANDLE retkey, ACCESS_MASK access, OBJECT_ATTRIB return NtOpenKey(retkey, access, attr); } -/****************************************************************************** - * NtDeleteKey [NTDLL.@] - * ZwDeleteKey [NTDLL.@] - */ -NTSTATUS WINAPI NtDeleteKey( HANDLE hkey ) -{ - NTSTATUS ret; - - TRACE( "(%p)\n", hkey ); - - SERVER_START_REQ( delete_key ) - { - req->hkey = wine_server_obj_handle( hkey ); - ret = wine_server_call( req ); - } - SERVER_END_REQ; - return ret; -} - /****************************************************************************** * RtlpNtMakeTemporaryKey [NTDLL.@] * @@ -215,163 +81,6 @@ NTSTATUS WINAPI RtlpNtMakeTemporaryKey( HANDLE hkey ) return NtDeleteKey(hkey); } -/****************************************************************************** - * NtDeleteValueKey [NTDLL.@] - * ZwDeleteValueKey [NTDLL.@] - */ -NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name ) -{ - NTSTATUS ret; - - TRACE( "(%p,%s)\n", hkey, debugstr_us(name) ); - if (name->Length > MAX_VALUE_LENGTH) return STATUS_OBJECT_NAME_NOT_FOUND; - - SERVER_START_REQ( delete_key_value ) - { - req->hkey = wine_server_obj_handle( hkey ); - wine_server_add_data( req, name->Buffer, name->Length ); - ret = wine_server_call( req ); - } - SERVER_END_REQ; - return ret; -} - - -/****************************************************************************** - * enumerate_key - * - * Implementation of NtQueryKey and NtEnumerateKey - */ -static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS info_class, - void *info, DWORD length, DWORD *result_len ) - -{ - NTSTATUS ret; - void *data_ptr; - size_t fixed_size; - - switch(info_class) - { - case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break; - case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break; - case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break; - case KeyNameInformation: data_ptr = ((KEY_NAME_INFORMATION *)info)->Name; break; - case KeyCachedInformation: data_ptr = ((KEY_CACHED_INFORMATION *)info)+1; break; - default: - FIXME( "Information class %d not implemented\n", info_class ); - return STATUS_INVALID_PARAMETER; - } - fixed_size = (char *)data_ptr - (char *)info; - - SERVER_START_REQ( enum_key ) - { - req->hkey = wine_server_obj_handle( handle ); - req->index = index; - req->info_class = info_class; - if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size ); - if (!(ret = wine_server_call( req ))) - { - switch(info_class) - { - case KeyBasicInformation: - { - KEY_BASIC_INFORMATION keyinfo; - fixed_size = (char *)keyinfo.Name - (char *)&keyinfo; - keyinfo.LastWriteTime.QuadPart = reply->modif; - keyinfo.TitleIndex = 0; - keyinfo.NameLength = reply->namelen; - memcpy( info, &keyinfo, min( length, fixed_size ) ); - } - break; - case KeyFullInformation: - { - KEY_FULL_INFORMATION keyinfo; - fixed_size = (char *)keyinfo.Class - (char *)&keyinfo; - keyinfo.LastWriteTime.QuadPart = reply->modif; - keyinfo.TitleIndex = 0; - keyinfo.ClassLength = wine_server_reply_size(reply); - keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1; - keyinfo.SubKeys = reply->subkeys; - keyinfo.MaxNameLen = reply->max_subkey; - keyinfo.MaxClassLen = reply->max_class; - keyinfo.Values = reply->values; - keyinfo.MaxValueNameLen = reply->max_value; - keyinfo.MaxValueDataLen = reply->max_data; - memcpy( info, &keyinfo, min( length, fixed_size ) ); - } - break; - case KeyNodeInformation: - { - KEY_NODE_INFORMATION keyinfo; - fixed_size = (char *)keyinfo.Name - (char *)&keyinfo; - keyinfo.LastWriteTime.QuadPart = reply->modif; - keyinfo.TitleIndex = 0; - if (reply->namelen < wine_server_reply_size(reply)) - { - keyinfo.ClassLength = wine_server_reply_size(reply) - reply->namelen; - keyinfo.ClassOffset = fixed_size + reply->namelen; - } - else - { - keyinfo.ClassLength = 0; - keyinfo.ClassOffset = -1; - } - keyinfo.NameLength = reply->namelen; - memcpy( info, &keyinfo, min( length, fixed_size ) ); - } - break; - case KeyNameInformation: - { - KEY_NAME_INFORMATION keyinfo; - fixed_size = (char *)keyinfo.Name - (char *)&keyinfo; - keyinfo.NameLength = reply->namelen; - memcpy( info, &keyinfo, min( length, fixed_size ) ); - } - break; - case KeyCachedInformation: - { - KEY_CACHED_INFORMATION keyinfo; - fixed_size = sizeof(keyinfo); - keyinfo.LastWriteTime.QuadPart = reply->modif; - keyinfo.TitleIndex = 0; - keyinfo.SubKeys = reply->subkeys; - keyinfo.MaxNameLen = reply->max_subkey; - keyinfo.Values = reply->values; - keyinfo.MaxValueNameLen = reply->max_value; - keyinfo.MaxValueDataLen = reply->max_data; - keyinfo.NameLength = reply->namelen; - memcpy( info, &keyinfo, min( length, fixed_size ) ); - } - break; - default: - break; - } - *result_len = fixed_size + reply->total; - if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW; - } - } - SERVER_END_REQ; - return ret; -} - - - -/****************************************************************************** - * NtEnumerateKey [NTDLL.@] - * ZwEnumerateKey [NTDLL.@] - * - * NOTES - * the name copied into the buffer is NOT 0-terminated - */ -NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class, - void *info, DWORD length, DWORD *result_len ) -{ - /* -1 means query key, so avoid it here */ - if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES; - return enumerate_key( handle, index, info_class, info, length, result_len ); -} - - /****************************************************************************** * RtlpNtEnumerateSubKey [NTDLL.@] * @@ -418,175 +127,6 @@ NTSTATUS WINAPI RtlpNtEnumerateSubKey( HANDLE handle, UNICODE_STRING *out, ULONG return ret; } -/****************************************************************************** - * NtQueryKey [NTDLL.@] - * ZwQueryKey [NTDLL.@] - */ -NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class, - void *info, DWORD length, DWORD *result_len ) -{ - return enumerate_key( handle, -1, info_class, info, length, result_len ); -} - - -/* fill the key value info structure for a specific info class */ -static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class, void *info, - DWORD length, int type, int name_len, int data_len ) -{ - switch(info_class) - { - case KeyValueBasicInformation: - { - KEY_VALUE_BASIC_INFORMATION keyinfo; - keyinfo.TitleIndex = 0; - keyinfo.Type = type; - keyinfo.NameLength = name_len; - length = min( length, (char *)keyinfo.Name - (char *)&keyinfo ); - memcpy( info, &keyinfo, length ); - break; - } - case KeyValueFullInformation: - { - KEY_VALUE_FULL_INFORMATION keyinfo; - keyinfo.TitleIndex = 0; - keyinfo.Type = type; - keyinfo.DataOffset = (char *)keyinfo.Name - (char *)&keyinfo + name_len; - keyinfo.DataLength = data_len; - keyinfo.NameLength = name_len; - length = min( length, (char *)keyinfo.Name - (char *)&keyinfo ); - memcpy( info, &keyinfo, length ); - break; - } - case KeyValuePartialInformation: - { - KEY_VALUE_PARTIAL_INFORMATION keyinfo; - keyinfo.TitleIndex = 0; - keyinfo.Type = type; - keyinfo.DataLength = data_len; - length = min( length, (char *)keyinfo.Data - (char *)&keyinfo ); - memcpy( info, &keyinfo, length ); - break; - } - default: - break; - } -} - - -/****************************************************************************** - * NtEnumerateValueKey [NTDLL.@] - * ZwEnumerateValueKey [NTDLL.@] - */ -NTSTATUS WINAPI NtEnumerateValueKey( HANDLE handle, ULONG index, - KEY_VALUE_INFORMATION_CLASS info_class, - void *info, DWORD length, DWORD *result_len ) -{ - NTSTATUS ret; - void *ptr; - size_t fixed_size; - - TRACE( "(%p,%u,%d,%p,%d)\n", handle, index, info_class, info, length ); - - /* compute the length we want to retrieve */ - switch(info_class) - { - case KeyValueBasicInformation: ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break; - case KeyValueFullInformation: ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break; - case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break; - default: - FIXME( "Information class %d not implemented\n", info_class ); - return STATUS_INVALID_PARAMETER; - } - fixed_size = (char *)ptr - (char *)info; - - SERVER_START_REQ( enum_key_value ) - { - req->hkey = wine_server_obj_handle( handle ); - req->index = index; - req->info_class = info_class; - if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size ); - if (!(ret = wine_server_call( req ))) - { - copy_key_value_info( info_class, info, length, reply->type, reply->namelen, - wine_server_reply_size(reply) - reply->namelen ); - *result_len = fixed_size + reply->total; - if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW; - } - } - SERVER_END_REQ; - return ret; -} - - -/****************************************************************************** - * NtQueryValueKey [NTDLL.@] - * ZwQueryValueKey [NTDLL.@] - * - * NOTES - * the name in the KeyValueInformation is never set - */ -NTSTATUS WINAPI DECLSPEC_HOTPATCH NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name, - KEY_VALUE_INFORMATION_CLASS info_class, - void *info, DWORD length, DWORD *result_len ) -{ - NTSTATUS ret; - UCHAR *data_ptr; - unsigned int fixed_size, min_size; - - TRACE( "(%p,%s,%d,%p,%d)\n", handle, debugstr_us(name), info_class, info, length ); - - if (name->Length > MAX_VALUE_LENGTH) return STATUS_OBJECT_NAME_NOT_FOUND; - - /* compute the length we want to retrieve */ - switch(info_class) - { - case KeyValueBasicInformation: - { - KEY_VALUE_BASIC_INFORMATION *basic_info = info; - min_size = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name); - fixed_size = min_size + name->Length; - if (min_size < length) - memcpy(basic_info->Name, name->Buffer, min(length - min_size, name->Length)); - data_ptr = NULL; - break; - } - case KeyValueFullInformation: - { - KEY_VALUE_FULL_INFORMATION *full_info = info; - min_size = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name); - fixed_size = min_size + name->Length; - if (min_size < length) - memcpy(full_info->Name, name->Buffer, min(length - min_size, name->Length)); - data_ptr = (UCHAR *)full_info->Name + name->Length; - break; - } - case KeyValuePartialInformation: - min_size = fixed_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data); - data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; - break; - default: - FIXME( "Information class %d not implemented\n", info_class ); - return STATUS_INVALID_PARAMETER; - } - - SERVER_START_REQ( get_key_value ) - { - req->hkey = wine_server_obj_handle( handle ); - wine_server_add_data( req, name->Buffer, name->Length ); - if (length > fixed_size && data_ptr) wine_server_set_reply( req, data_ptr, length - fixed_size ); - if (!(ret = wine_server_call( req ))) - { - copy_key_value_info( info_class, info, length, reply->type, - name->Length, reply->total ); - *result_len = fixed_size + (info_class == KeyValueBasicInformation ? 0 : reply->total); - if (length < min_size) ret = STATUS_BUFFER_TOO_SMALL; - else if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW; - } - } - SERVER_END_REQ; - return ret; -} - /****************************************************************************** * RtlpNtQueryValueKey [NTDLL.@] * @@ -623,257 +163,6 @@ NTSTATUS WINAPI RtlpNtQueryValueKey( HANDLE handle, ULONG *result_type, PBYTE de return ret; } -/****************************************************************************** - * NtFlushKey [NTDLL.@] - * ZwFlushKey [NTDLL.@] - */ -NTSTATUS WINAPI NtFlushKey(HANDLE key) -{ - NTSTATUS ret; - - TRACE("key=%p\n", key); - - SERVER_START_REQ( flush_key ) - { - req->hkey = wine_server_obj_handle( key ); - ret = wine_server_call( req ); - } - SERVER_END_REQ; - - return ret; -} - -/****************************************************************************** - * NtLoadKey [NTDLL.@] - * ZwLoadKey [NTDLL.@] - */ -NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file ) -{ - NTSTATUS ret; - HANDLE hive; - IO_STATUS_BLOCK io; - data_size_t len; - struct object_attributes *objattr; - - TRACE("(%p,%p)\n", attr, file); - - ret = NtCreateFile(&hive, GENERIC_READ | SYNCHRONIZE, file, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0, - FILE_OPEN, 0, NULL, 0); - if (ret) return ret; - - if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; - - SERVER_START_REQ( load_registry ) - { - req->file = wine_server_obj_handle( hive ); - wine_server_add_data( req, objattr, len ); - ret = wine_server_call( req ); - } - SERVER_END_REQ; - - NtClose(hive); - RtlFreeHeap( GetProcessHeap(), 0, objattr ); - return ret; -} - -/****************************************************************************** - * NtLoadKey2 [NTDLL.@] - * ZwLoadKey2 [NTDLL.@] - */ -NTSTATUS WINAPI NtLoadKey2(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); -} - -/****************************************************************************** - * NtNotifyChangeMultipleKeys [NTDLL.@] - * ZwNotifyChangeMultipleKeys [NTDLL.@] - */ -NTSTATUS WINAPI NtNotifyChangeMultipleKeys( - HANDLE KeyHandle, - ULONG Count, - OBJECT_ATTRIBUTES *SubordinateObjects, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG CompletionFilter, - BOOLEAN WatchSubtree, - PVOID ChangeBuffer, - ULONG Length, - BOOLEAN Asynchronous) -{ - NTSTATUS ret; - - TRACE("(%p,%u,%p,%p,%p,%p,%p,0x%08x, 0x%08x,%p,0x%08x,0x%08x)\n", - KeyHandle, Count, SubordinateObjects, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter, - Asynchronous, ChangeBuffer, Length, WatchSubtree); - - if (Count || SubordinateObjects || ApcRoutine || ApcContext || ChangeBuffer || Length) - FIXME("Unimplemented optional parameter\n"); - - if (!Asynchronous) - { - OBJECT_ATTRIBUTES attr; - InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL ); - ret = NtCreateEvent( &Event, EVENT_ALL_ACCESS, &attr, SynchronizationEvent, FALSE ); - if (ret != STATUS_SUCCESS) - return ret; - } - - SERVER_START_REQ( set_registry_notification ) - { - req->hkey = wine_server_obj_handle( KeyHandle ); - req->event = wine_server_obj_handle( Event ); - req->subtree = WatchSubtree; - req->filter = CompletionFilter; - ret = wine_server_call( req ); - } - SERVER_END_REQ; - - if (!Asynchronous) - { - if (ret == STATUS_PENDING) - ret = NtWaitForSingleObject( Event, FALSE, NULL ); - NtClose( Event ); - } - - return ret; -} - -/****************************************************************************** - * NtNotifyChangeKey [NTDLL.@] - * ZwNotifyChangeKey [NTDLL.@] - */ -NTSTATUS WINAPI NtNotifyChangeKey( - IN HANDLE KeyHandle, - IN HANDLE Event, - IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, - IN PVOID ApcContext OPTIONAL, - OUT PIO_STATUS_BLOCK IoStatusBlock, - IN ULONG CompletionFilter, - IN BOOLEAN WatchSubtree, - OUT PVOID ChangeBuffer, - IN ULONG Length, - IN BOOLEAN Asynchronous) -{ - return NtNotifyChangeMultipleKeys(KeyHandle, 0, NULL, Event, ApcRoutine, ApcContext, - IoStatusBlock, CompletionFilter, WatchSubtree, - ChangeBuffer, Length, Asynchronous); -} - -/****************************************************************************** - * NtQueryMultipleValueKey [NTDLL] - * ZwQueryMultipleValueKey - */ - -NTSTATUS WINAPI NtQueryMultipleValueKey( - HANDLE KeyHandle, - PKEY_MULTIPLE_VALUE_INFORMATION ListOfValuesToQuery, - ULONG NumberOfItems, - PVOID MultipleValueInformation, - ULONG Length, - PULONG ReturnLength) -{ - FIXME("(%p,%p,0x%08x,%p,0x%08x,%p) stub!\n", - KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation, - Length,ReturnLength); - return STATUS_SUCCESS; -} - -/****************************************************************************** - * NtReplaceKey [NTDLL.@] - * ZwReplaceKey [NTDLL.@] - */ -NTSTATUS WINAPI NtReplaceKey( - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN HANDLE Key, - IN POBJECT_ATTRIBUTES ReplacedObjectAttributes) -{ - FIXME("(%s,%p,%s),stub!\n", debugstr_ObjectAttributes(ObjectAttributes), Key, - debugstr_ObjectAttributes(ReplacedObjectAttributes) ); - return STATUS_SUCCESS; -} -/****************************************************************************** - * NtRestoreKey [NTDLL.@] - * ZwRestoreKey [NTDLL.@] - */ -NTSTATUS WINAPI NtRestoreKey( - HANDLE KeyHandle, - HANDLE FileHandle, - ULONG RestoreFlags) -{ - FIXME("(%p,%p,0x%08x) stub\n", - KeyHandle, FileHandle, RestoreFlags); - return STATUS_SUCCESS; -} -/****************************************************************************** - * NtSaveKey [NTDLL.@] - * ZwSaveKey [NTDLL.@] - */ -NTSTATUS WINAPI NtSaveKey(IN HANDLE KeyHandle, IN HANDLE FileHandle) -{ - NTSTATUS ret; - - TRACE("(%p,%p)\n", KeyHandle, FileHandle); - - SERVER_START_REQ( save_registry ) - { - req->hkey = wine_server_obj_handle( KeyHandle ); - req->file = wine_server_obj_handle( FileHandle ); - ret = wine_server_call( req ); - } - SERVER_END_REQ; - - return ret; -} -/****************************************************************************** - * NtSetInformationKey [NTDLL.@] - * ZwSetInformationKey [NTDLL.@] - */ -NTSTATUS WINAPI NtSetInformationKey( - IN HANDLE KeyHandle, - IN const int KeyInformationClass, - IN PVOID KeyInformation, - IN ULONG KeyInformationLength) -{ - FIXME("(%p,0x%08x,%p,0x%08x) stub\n", - KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength); - return STATUS_SUCCESS; -} - - -/****************************************************************************** - * NtSetValueKey [NTDLL.@] - * ZwSetValueKey [NTDLL.@] - * - * NOTES - * win95 does not care about count for REG_SZ and finds out the len by itself (js) - * NT does definitely care (aj) - */ -NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG TitleIndex, - ULONG type, const void *data, ULONG count ) -{ - NTSTATUS ret; - - TRACE( "(%p,%s,%d,%p,%d)\n", hkey, debugstr_us(name), type, data, count ); - - if (name->Length > MAX_VALUE_LENGTH) return STATUS_INVALID_PARAMETER; - - SERVER_START_REQ( set_key_value ) - { - req->hkey = wine_server_obj_handle( hkey ); - req->type = type; - req->namelen = name->Length; - wine_server_add_data( req, name->Buffer, name->Length ); - wine_server_add_data( req, data, count ); - ret = wine_server_call( req ); - } - SERVER_END_REQ; - return ret; -} - /****************************************************************************** * RtlpNtSetValueKey [NTDLL.@] * @@ -887,26 +176,6 @@ NTSTATUS WINAPI RtlpNtSetValueKey( HANDLE hkey, ULONG type, const void *data, return NtSetValueKey( hkey, &name, 0, type, data, count ); } -/****************************************************************************** - * NtUnloadKey [NTDLL.@] - * ZwUnloadKey [NTDLL.@] - */ -NTSTATUS WINAPI NtUnloadKey(IN POBJECT_ATTRIBUTES attr) -{ - NTSTATUS ret; - - TRACE("(%p)\n", attr); - - SERVER_START_REQ( unload_registry ) - { - req->hkey = wine_server_obj_handle( attr->RootDirectory ); - ret = wine_server_call(req); - } - SERVER_END_REQ; - - return ret; -} - /****************************************************************************** * RtlFormatCurrentUserKeyPath [NTDLL.@] * @@ -1527,67 +796,3 @@ NTSTATUS WINAPI RtlWriteRegistryValue( ULONG RelativeTo, PCWSTR path, PCWSTR nam return status; } - -/************************************************************************* - * NtQueryLicenseValue [NTDLL.@] - * - * NOTES - * On Windows all license properties are stored in a single key, but - * unless there is some app which explicitly depends on that, there is - * no good reason to reproduce that. - */ -NTSTATUS WINAPI NtQueryLicenseValue( const UNICODE_STRING *name, ULONG *result_type, - PVOID data, ULONG length, ULONG *result_len ) -{ - static const WCHAR LicenseInformationW[] = {'M','a','c','h','i','n','e','\\', - 'S','o','f','t','w','a','r','e','\\', - 'W','i','n','e','\\','L','i','c','e','n','s','e', - 'I','n','f','o','r','m','a','t','i','o','n',0}; - KEY_VALUE_PARTIAL_INFORMATION *info; - NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; - DWORD info_length, count; - OBJECT_ATTRIBUTES attr; - UNICODE_STRING keyW; - HANDLE hkey; - - if (!name || !name->Buffer || !name->Length || !result_len) - return STATUS_INVALID_PARAMETER; - - info_length = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + length; - info = RtlAllocateHeap( GetProcessHeap(), 0, info_length ); - if (!info) return STATUS_NO_MEMORY; - - attr.Length = sizeof(attr); - attr.RootDirectory = 0; - attr.ObjectName = &keyW; - attr.Attributes = 0; - attr.SecurityDescriptor = NULL; - attr.SecurityQualityOfService = NULL; - RtlInitUnicodeString( &keyW, LicenseInformationW ); - - /* @@ Wine registry key: HKLM\Software\Wine\LicenseInformation */ - if (!NtOpenKey( &hkey, KEY_READ, &attr )) - { - status = NtQueryValueKey( hkey, name, KeyValuePartialInformation, - info, info_length, &count ); - if (!status || status == STATUS_BUFFER_OVERFLOW) - { - if (result_type) - *result_type = info->Type; - - *result_len = info->DataLength; - - if (status == STATUS_BUFFER_OVERFLOW) - status = STATUS_BUFFER_TOO_SMALL; - else - memcpy( data, info->Data, info->DataLength ); - } - NtClose( hkey ); - } - - if (status == STATUS_OBJECT_NAME_NOT_FOUND) - FIXME( "License key %s not found\n", debugstr_w(name->Buffer) ); - - RtlFreeHeap( GetProcessHeap(), 0, info ); - return status; -} diff --git a/dlls/ntdll/unix/registry.c b/dlls/ntdll/unix/registry.c new file mode 100644 index 00000000000..f94c8ff98ee --- /dev/null +++ b/dlls/ntdll/unix/registry.c @@ -0,0 +1,778 @@ +/* + * Registry functions + * + * Copyright 1999 Juergen Schmied + * Copyright 2000 Alexandre Julliard + * Copyright 2005 Ivan Leo Puoti, Laurent Pinchart + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#if 0 +#pragma makedep unix +#endif + +#include +#include + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "unix_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(reg); + +/* maximum length of a value name in bytes (without terminating null) */ +#define MAX_VALUE_LENGTH (16383 * sizeof(WCHAR)) + + +/****************************************************************************** + * NtCreateKey (NTDLL.@) + */ +NTSTATUS WINAPI NtCreateKey( HANDLE *key, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, + ULONG index, const UNICODE_STRING *class, ULONG options, ULONG *dispos ) +{ + NTSTATUS ret; + data_size_t len; + struct object_attributes *objattr; + + if (!key || !attr) return STATUS_ACCESS_VIOLATION; + if (attr->Length > sizeof(OBJECT_ATTRIBUTES)) return STATUS_INVALID_PARAMETER; + + TRACE( "(%p,%s,%s,%x,%x,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName), + debugstr_us(class), options, access, key ); + + if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; + + SERVER_START_REQ( create_key ) + { + req->access = access; + req->options = options; + wine_server_add_data( req, objattr, len ); + if (class) wine_server_add_data( req, class->Buffer, class->Length ); + ret = wine_server_call( req ); + *key = wine_server_ptr_handle( reply->hkey ); + if (dispos && !ret) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY; + } + SERVER_END_REQ; + + TRACE( "<- %p\n", *key ); + free( objattr ); + return ret; +} + + +/****************************************************************************** + * NtCreateKeyTransacted (NTDLL.@) + */ +NTSTATUS WINAPI NtCreateKeyTransacted( HANDLE *key, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, + ULONG index, const UNICODE_STRING *class, ULONG options, + HANDLE transacted, ULONG *dispos ) +{ + FIXME( "(%p,%s,%s,%x,%x,%p,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName), + debugstr_us(class), options, access, transacted, key ); + return STATUS_NOT_IMPLEMENTED; +} + + +/****************************************************************************** + * NtOpenKeyEx (NTDLL.@) + */ +NTSTATUS WINAPI NtOpenKeyEx( HANDLE *key, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, ULONG options ) +{ + NTSTATUS ret; + + if (!key || !attr || !attr->ObjectName) return STATUS_ACCESS_VIOLATION; + if (attr->Length != sizeof(*attr)) return STATUS_INVALID_PARAMETER; + if (attr->ObjectName->Length & 1) return STATUS_OBJECT_NAME_INVALID; + + TRACE( "(%p,%s,%x,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName), access, key ); + + if (options & ~REG_OPTION_OPEN_LINK) FIXME( "options %x not implemented\n", options ); + + SERVER_START_REQ( open_key ) + { + req->parent = wine_server_obj_handle( attr->RootDirectory ); + req->access = access; + req->attributes = attr->Attributes; + wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length ); + ret = wine_server_call( req ); + *key = wine_server_ptr_handle( reply->hkey ); + } + SERVER_END_REQ; + TRACE("<- %p\n", *key); + return ret; +} + + +/****************************************************************************** + * NtOpenKey (NTDLL.@) + */ +NTSTATUS WINAPI NtOpenKey( HANDLE *key, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr ) +{ + return NtOpenKeyEx( key, access, attr, 0 ); +} + + +/****************************************************************************** + * NtOpenKeyTransactedEx (NTDLL.@) + */ +NTSTATUS WINAPI NtOpenKeyTransactedEx( HANDLE *key, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, + ULONG options, HANDLE transaction ) +{ + FIXME( "(%p %x %p %x %p)\n", key, access, attr, options, transaction ); + return STATUS_NOT_IMPLEMENTED; +} + + +/****************************************************************************** + * NtOpenKeyTransacted (NTDLL.@) + */ +NTSTATUS WINAPI NtOpenKeyTransacted( HANDLE *key, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, + HANDLE transaction ) +{ + return NtOpenKeyTransactedEx( key, access, attr, 0, transaction ); +} + + +/****************************************************************************** + * NtDeleteKey (NTDLL.@) + */ +NTSTATUS WINAPI NtDeleteKey( HANDLE key ) +{ + NTSTATUS ret; + + TRACE( "(%p)\n", key ); + + SERVER_START_REQ( delete_key ) + { + req->hkey = wine_server_obj_handle( key ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; +} + + +/****************************************************************************** + * NtRenameKey (NTDLL.@) + */ +NTSTATUS WINAPI NtRenameKey( HANDLE handle, UNICODE_STRING *name ) +{ + FIXME( "(%p %s)\n", handle, debugstr_us(name) ); + return STATUS_NOT_IMPLEMENTED; +} + + +/****************************************************************************** + * enumerate_key + * + * Implementation of NtQueryKey and NtEnumerateKey + */ +static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS info_class, + void *info, DWORD length, DWORD *result_len ) + +{ + NTSTATUS ret; + void *data_ptr; + size_t fixed_size; + + switch (info_class) + { + case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break; + case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break; + case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break; + case KeyNameInformation: data_ptr = ((KEY_NAME_INFORMATION *)info)->Name; break; + case KeyCachedInformation: data_ptr = ((KEY_CACHED_INFORMATION *)info)+1; break; + default: + FIXME( "Information class %d not implemented\n", info_class ); + return STATUS_INVALID_PARAMETER; + } + fixed_size = (char *)data_ptr - (char *)info; + + SERVER_START_REQ( enum_key ) + { + req->hkey = wine_server_obj_handle( handle ); + req->index = index; + req->info_class = info_class; + if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size ); + if (!(ret = wine_server_call( req ))) + { + switch (info_class) + { + case KeyBasicInformation: + { + KEY_BASIC_INFORMATION keyinfo; + fixed_size = (char *)keyinfo.Name - (char *)&keyinfo; + keyinfo.LastWriteTime.QuadPart = reply->modif; + keyinfo.TitleIndex = 0; + keyinfo.NameLength = reply->namelen; + memcpy( info, &keyinfo, min( length, fixed_size ) ); + break; + } + + case KeyFullInformation: + { + KEY_FULL_INFORMATION keyinfo; + fixed_size = (char *)keyinfo.Class - (char *)&keyinfo; + keyinfo.LastWriteTime.QuadPart = reply->modif; + keyinfo.TitleIndex = 0; + keyinfo.ClassLength = wine_server_reply_size(reply); + keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1; + keyinfo.SubKeys = reply->subkeys; + keyinfo.MaxNameLen = reply->max_subkey; + keyinfo.MaxClassLen = reply->max_class; + keyinfo.Values = reply->values; + keyinfo.MaxValueNameLen = reply->max_value; + keyinfo.MaxValueDataLen = reply->max_data; + memcpy( info, &keyinfo, min( length, fixed_size ) ); + break; + } + + case KeyNodeInformation: + { + KEY_NODE_INFORMATION keyinfo; + fixed_size = (char *)keyinfo.Name - (char *)&keyinfo; + keyinfo.LastWriteTime.QuadPart = reply->modif; + keyinfo.TitleIndex = 0; + if (reply->namelen < wine_server_reply_size(reply)) + { + keyinfo.ClassLength = wine_server_reply_size(reply) - reply->namelen; + keyinfo.ClassOffset = fixed_size + reply->namelen; + } + else + { + keyinfo.ClassLength = 0; + keyinfo.ClassOffset = -1; + } + keyinfo.NameLength = reply->namelen; + memcpy( info, &keyinfo, min( length, fixed_size ) ); + break; + } + + case KeyNameInformation: + { + KEY_NAME_INFORMATION keyinfo; + fixed_size = (char *)keyinfo.Name - (char *)&keyinfo; + keyinfo.NameLength = reply->namelen; + memcpy( info, &keyinfo, min( length, fixed_size ) ); + break; + } + + case KeyCachedInformation: + { + KEY_CACHED_INFORMATION keyinfo; + fixed_size = sizeof(keyinfo); + keyinfo.LastWriteTime.QuadPart = reply->modif; + keyinfo.TitleIndex = 0; + keyinfo.SubKeys = reply->subkeys; + keyinfo.MaxNameLen = reply->max_subkey; + keyinfo.Values = reply->values; + keyinfo.MaxValueNameLen = reply->max_value; + keyinfo.MaxValueDataLen = reply->max_data; + keyinfo.NameLength = reply->namelen; + memcpy( info, &keyinfo, min( length, fixed_size ) ); + break; + } + + default: + break; + } + *result_len = fixed_size + reply->total; + if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW; + } + } + SERVER_END_REQ; + return ret; +} + + +/****************************************************************************** + * NtEnumerateKey (NTDLL.@) + */ +NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class, + void *info, DWORD length, DWORD *result_len ) +{ + /* -1 means query key, so avoid it here */ + if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES; + return enumerate_key( handle, index, info_class, info, length, result_len ); +} + + +/****************************************************************************** + * NtQueryKey (NTDLL.@) + */ +NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class, + void *info, DWORD length, DWORD *result_len ) +{ + return enumerate_key( handle, -1, info_class, info, length, result_len ); +} + + +/****************************************************************************** + * NtSetInformationKey (NTDLL.@) + */ +NTSTATUS WINAPI NtSetInformationKey( HANDLE key, int class, void *info, ULONG length ) +{ + FIXME( "(%p,0x%08x,%p,0x%08x) stub\n", key, class, info, length ); + return STATUS_SUCCESS; +} + + +/* fill the key value info structure for a specific info class */ +static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class, void *info, + DWORD length, int type, int name_len, int data_len ) +{ + switch (info_class) + { + case KeyValueBasicInformation: + { + KEY_VALUE_BASIC_INFORMATION keyinfo; + keyinfo.TitleIndex = 0; + keyinfo.Type = type; + keyinfo.NameLength = name_len; + length = min( length, (char *)keyinfo.Name - (char *)&keyinfo ); + memcpy( info, &keyinfo, length ); + break; + } + + case KeyValueFullInformation: + { + KEY_VALUE_FULL_INFORMATION keyinfo; + keyinfo.TitleIndex = 0; + keyinfo.Type = type; + keyinfo.DataOffset = (char *)keyinfo.Name - (char *)&keyinfo + name_len; + keyinfo.DataLength = data_len; + keyinfo.NameLength = name_len; + length = min( length, (char *)keyinfo.Name - (char *)&keyinfo ); + memcpy( info, &keyinfo, length ); + break; + } + + case KeyValuePartialInformation: + { + KEY_VALUE_PARTIAL_INFORMATION keyinfo; + keyinfo.TitleIndex = 0; + keyinfo.Type = type; + keyinfo.DataLength = data_len; + length = min( length, (char *)keyinfo.Data - (char *)&keyinfo ); + memcpy( info, &keyinfo, length ); + break; + } + + default: + break; + } +} + + +/****************************************************************************** + * NtEnumerateValueKey (NTDLL.@) + */ +NTSTATUS WINAPI NtEnumerateValueKey( HANDLE handle, ULONG index, KEY_VALUE_INFORMATION_CLASS info_class, + void *info, DWORD length, DWORD *result_len ) +{ + NTSTATUS ret; + void *ptr; + size_t fixed_size; + + TRACE( "(%p,%u,%d,%p,%d)\n", handle, index, info_class, info, length ); + + /* compute the length we want to retrieve */ + switch (info_class) + { + case KeyValueBasicInformation: ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break; + case KeyValueFullInformation: ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break; + case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break; + default: + FIXME( "Information class %d not implemented\n", info_class ); + return STATUS_INVALID_PARAMETER; + } + fixed_size = (char *)ptr - (char *)info; + + SERVER_START_REQ( enum_key_value ) + { + req->hkey = wine_server_obj_handle( handle ); + req->index = index; + req->info_class = info_class; + if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size ); + if (!(ret = wine_server_call( req ))) + { + copy_key_value_info( info_class, info, length, reply->type, reply->namelen, + wine_server_reply_size(reply) - reply->namelen ); + *result_len = fixed_size + reply->total; + if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW; + } + } + SERVER_END_REQ; + return ret; +} + + +/****************************************************************************** + * NtQueryValueKey (NTDLL.@) + */ +NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name, + KEY_VALUE_INFORMATION_CLASS info_class, + void *info, DWORD length, DWORD *result_len ) +{ + NTSTATUS ret; + UCHAR *data_ptr; + unsigned int fixed_size, min_size; + + TRACE( "(%p,%s,%d,%p,%d)\n", handle, debugstr_us(name), info_class, info, length ); + + if (name->Length > MAX_VALUE_LENGTH) return STATUS_OBJECT_NAME_NOT_FOUND; + + /* compute the length we want to retrieve */ + switch(info_class) + { + case KeyValueBasicInformation: + { + KEY_VALUE_BASIC_INFORMATION *basic_info = info; + min_size = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name); + fixed_size = min_size + name->Length; + if (min_size < length) + memcpy(basic_info->Name, name->Buffer, min(length - min_size, name->Length)); + data_ptr = NULL; + break; + } + + case KeyValueFullInformation: + { + KEY_VALUE_FULL_INFORMATION *full_info = info; + min_size = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name); + fixed_size = min_size + name->Length; + if (min_size < length) + memcpy(full_info->Name, name->Buffer, min(length - min_size, name->Length)); + data_ptr = (UCHAR *)full_info->Name + name->Length; + break; + } + + case KeyValuePartialInformation: + min_size = fixed_size = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data); + data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; + break; + + default: + FIXME( "Information class %d not implemented\n", info_class ); + return STATUS_INVALID_PARAMETER; + } + + SERVER_START_REQ( get_key_value ) + { + req->hkey = wine_server_obj_handle( handle ); + wine_server_add_data( req, name->Buffer, name->Length ); + if (length > fixed_size && data_ptr) wine_server_set_reply( req, data_ptr, length - fixed_size ); + if (!(ret = wine_server_call( req ))) + { + copy_key_value_info( info_class, info, length, reply->type, + name->Length, reply->total ); + *result_len = fixed_size + (info_class == KeyValueBasicInformation ? 0 : reply->total); + if (length < min_size) ret = STATUS_BUFFER_TOO_SMALL; + else if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW; + } + } + SERVER_END_REQ; + return ret; +} + + +/****************************************************************************** + * NtQueryMultipleValueKey (NTDLL.@) + */ +NTSTATUS WINAPI NtQueryMultipleValueKey( HANDLE key, KEY_MULTIPLE_VALUE_INFORMATION *info, + ULONG count, void *buffer, ULONG length, ULONG *retlen ) +{ + FIXME( "(%p,%p,0x%08x,%p,0x%08x,%p) stub!\n", key, info, count, buffer, length, retlen ); + return STATUS_SUCCESS; +} + + +/****************************************************************************** + * NtSetValueKey (NTDLL.@) + */ +NTSTATUS WINAPI NtSetValueKey( HANDLE key, const UNICODE_STRING *name, ULONG index, + ULONG type, const void *data, ULONG count ) +{ + NTSTATUS ret; + + TRACE( "(%p,%s,%d,%p,%d)\n", key, debugstr_us(name), type, data, count ); + + if (name->Length > MAX_VALUE_LENGTH) return STATUS_INVALID_PARAMETER; + + SERVER_START_REQ( set_key_value ) + { + req->hkey = wine_server_obj_handle( key ); + req->type = type; + req->namelen = name->Length; + wine_server_add_data( req, name->Buffer, name->Length ); + wine_server_add_data( req, data, count ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; +} + + +/****************************************************************************** + * NtDeleteValueKey (NTDLL.@) + */ +NTSTATUS WINAPI NtDeleteValueKey( HANDLE key, const UNICODE_STRING *name ) +{ + NTSTATUS ret; + + TRACE( "(%p,%s)\n", key, debugstr_us(name) ); + + if (name->Length > MAX_VALUE_LENGTH) return STATUS_OBJECT_NAME_NOT_FOUND; + + SERVER_START_REQ( delete_key_value ) + { + req->hkey = wine_server_obj_handle( key ); + wine_server_add_data( req, name->Buffer, name->Length ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; +} + + +/****************************************************************************** + * NtNotifyChangeMultipleKeys (NTDLL.@) + */ +NTSTATUS WINAPI NtNotifyChangeMultipleKeys( HANDLE key, ULONG count, OBJECT_ATTRIBUTES *attr, + HANDLE event, PIO_APC_ROUTINE apc, void *apc_context, + IO_STATUS_BLOCK *io, ULONG filter, BOOLEAN subtree, + void *buffer, ULONG length, BOOLEAN async ) +{ + NTSTATUS ret; + + TRACE( "(%p,%u,%p,%p,%p,%p,%p,0x%08x, 0x%08x,%p,0x%08x,0x%08x)\n", + key, count, attr, event, apc, apc_context, io, filter, async, buffer, length, subtree ); + + if (count || attr || apc || apc_context || buffer || length) + FIXME( "Unimplemented optional parameter\n" ); + + if (!async) + { + OBJECT_ATTRIBUTES attr; + InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL ); + ret = NtCreateEvent( &event, EVENT_ALL_ACCESS, &attr, SynchronizationEvent, FALSE ); + if (ret) return ret; + } + + SERVER_START_REQ( set_registry_notification ) + { + req->hkey = wine_server_obj_handle( key ); + req->event = wine_server_obj_handle( event ); + req->subtree = subtree; + req->filter = filter; + ret = wine_server_call( req ); + } + SERVER_END_REQ; + + if (!async) + { + if (ret == STATUS_PENDING) ret = NtWaitForSingleObject( event, FALSE, NULL ); + NtClose( event ); + } + return ret; +} + + +/****************************************************************************** + * NtNotifyChangeKey (NTDLL.@) + */ +NTSTATUS WINAPI NtNotifyChangeKey( HANDLE key, HANDLE event, PIO_APC_ROUTINE apc, void *apc_context, + IO_STATUS_BLOCK *io, ULONG filter, BOOLEAN subtree, + void *buffer, ULONG length, BOOLEAN async ) +{ + return NtNotifyChangeMultipleKeys( key, 0, NULL, event, apc, apc_context, + io, filter, subtree, buffer, length, async ); +} + + +/****************************************************************************** + * NtFlushKey (NTDLL.@) + */ +NTSTATUS WINAPI NtFlushKey( HANDLE key ) +{ + NTSTATUS ret; + + TRACE( "key=%p\n", key ); + + SERVER_START_REQ( flush_key ) + { + req->hkey = wine_server_obj_handle( key ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; +} + + +/****************************************************************************** + * NtLoadKey (NTDLL.@) + */ +NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, OBJECT_ATTRIBUTES *file ) +{ + NTSTATUS ret; + HANDLE key; + IO_STATUS_BLOCK io; + data_size_t len; + struct object_attributes *objattr; + + TRACE("(%p,%p)\n", attr, file); + + ret = NtCreateFile( &key, GENERIC_READ | SYNCHRONIZE, file, &io, NULL, FILE_ATTRIBUTE_NORMAL, 0, + FILE_OPEN, 0, NULL, 0); + if (ret) return ret; + + if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret; + + SERVER_START_REQ( load_registry ) + { + req->file = wine_server_obj_handle( key ); + wine_server_add_data( req, objattr, len ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + + NtClose( key ); + free( objattr ); + 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 ); +} + + +/****************************************************************************** + * NtUnloadKey (NTDLL.@) + */ +NTSTATUS WINAPI NtUnloadKey( OBJECT_ATTRIBUTES *attr ) +{ + NTSTATUS ret; + + TRACE( "(%p)\n", attr ); + + SERVER_START_REQ( unload_registry ) + { + req->hkey = wine_server_obj_handle( attr->RootDirectory ); + ret = wine_server_call(req); + } + SERVER_END_REQ; + return ret; +} + + +/****************************************************************************** + * NtSaveKey (NTDLL.@) + */ +NTSTATUS WINAPI NtSaveKey( HANDLE key, HANDLE file ) +{ + NTSTATUS ret; + + TRACE( "(%p,%p)\n", key, file ); + + SERVER_START_REQ( save_registry ) + { + req->hkey = wine_server_obj_handle( key ); + req->file = wine_server_obj_handle( file ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + return ret; +} + + +/****************************************************************************** + * NtRestoreKey (NTDLL.@) + */ +NTSTATUS WINAPI NtRestoreKey( HANDLE key, HANDLE file, ULONG flags ) +{ + FIXME( "(%p,%p,0x%08x) stub\n", key, file, flags ); + return STATUS_SUCCESS; +} + + +/****************************************************************************** + * NtReplaceKey (NTDLL.@) + */ +NTSTATUS WINAPI NtReplaceKey( OBJECT_ATTRIBUTES *attr, HANDLE key, OBJECT_ATTRIBUTES *replace ) +{ + FIXME( "(%s,%p,%s),stub!\n", debugstr_us(attr->ObjectName), key, debugstr_us(replace->ObjectName) ); + return STATUS_SUCCESS; +} + +/****************************************************************************** + * NtQueryLicenseValue (NTDLL.@) + * + * NOTES + * On Windows all license properties are stored in a single key, but + * unless there is some app which explicitly depends on that, there is + * no good reason to reproduce that. + */ +NTSTATUS WINAPI NtQueryLicenseValue( const UNICODE_STRING *name, ULONG *type, + void *data, ULONG length, ULONG *retlen ) +{ + static const WCHAR nameW[] = {'M','a','c','h','i','n','e','\\', + 'S','o','f','t','w','a','r','e','\\', + 'W','i','n','e','\\','L','i','c','e','n','s','e', + 'I','n','f','o','r','m','a','t','i','o','n',0}; + UNICODE_STRING keyW = { sizeof(nameW) - sizeof(WCHAR), sizeof(nameW), (WCHAR *)nameW }; + KEY_VALUE_PARTIAL_INFORMATION *info; + NTSTATUS status = STATUS_OBJECT_NAME_NOT_FOUND; + DWORD info_length, count; + OBJECT_ATTRIBUTES attr; + HANDLE key; + + if (!name || !name->Buffer || !name->Length || !retlen) return STATUS_INVALID_PARAMETER; + + info_length = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data ) + length; + if (!(info = malloc( info_length ))) return STATUS_NO_MEMORY; + + InitializeObjectAttributes( &attr, &keyW, 0, 0, NULL ); + + /* @@ Wine registry key: HKLM\Software\Wine\LicenseInformation */ + if (!NtOpenKey( &key, KEY_READ, &attr )) + { + status = NtQueryValueKey( key, name, KeyValuePartialInformation, info, info_length, &count ); + if (!status || status == STATUS_BUFFER_OVERFLOW) + { + if (type) *type = info->Type; + *retlen = info->DataLength; + if (status == STATUS_BUFFER_OVERFLOW) + status = STATUS_BUFFER_TOO_SMALL; + else + memcpy( data, info->Data, info->DataLength ); + } + NtClose( key ); + } + + if (status == STATUS_OBJECT_NAME_NOT_FOUND) + FIXME( "License key %s not found\n", debugstr_w(name->Buffer) ); + + free( info ); + return status; +}