ntdll: Move the registry system calls to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-07-17 11:46:15 +02:00
parent 1960df8a2a
commit 7053b7c615
4 changed files with 831 additions and 847 deletions

View File

@ -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 \

View File

@ -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

View File

@ -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;
}

778
dlls/ntdll/unix/registry.c Normal file
View File

@ -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 <stdarg.h>
#include <string.h>
#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;
}