Author: ion Date: Thu Jun 29 04:30:36 2006 New Revision: 22682
URL: http://svn.reactos.org/svn/reactos?rev=22682&view=rev Log: - Add some hacks to Cm to allow creating registry keys that finish with a backslash (this works under NT). - Also add a REALLY nasty hack that forces OBJ_CASE_INSENSITIVE on all Registry APIs... this is needed because we seem to completely mess up case sensitivity otherwise and any user-mode caller that doesn't specify that flag will fail. - These two fixes fix all the WINE failures for the "ntdll reg" test and should increase compatibility with some applications. - Runtime Library Registry Wrappers Fixes and Optimizations: - Use an array of registry paths instead of duplicating them - Fix implenmentation of RTL_REGISTRY_HANDLE. - Verify all Appends for failure before continuing. - Use the strict minimum key permissions isntead of KEY_ALL_ACCESS. - Don't use OBJ_OPENIF - Use CAPS for \REGISTRY\USER (required to match a Windows quirk exposed by a WINE test) - Use the correct length in RtlpNtQueryValueKey - Generic cleanups, formatting and commenting.
Modified: trunk/reactos/lib/rtl/registry.c trunk/reactos/ntoskrnl/cm/ntfunc.c trunk/reactos/ntoskrnl/cm/regobj.c
Modified: trunk/reactos/lib/rtl/registry.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/rtl/registry.c?rev=2268... ============================================================================== --- trunk/reactos/lib/rtl/registry.c (original) +++ trunk/reactos/lib/rtl/registry.c Thu Jun 29 04:30:36 2006 @@ -21,350 +21,541 @@
#define TAG_RTLREGISTRY TAG('R', 't', 'l', 'R')
-/* FUNCTIONS ***************************************************************/ - -static NTSTATUS -RtlpGetRegistryHandle(ULONG RelativeTo, - PWSTR Path, - BOOLEAN Create, - PHANDLE KeyHandle) -{ - UNICODE_STRING KeyPath; - UNICODE_STRING KeyName; - WCHAR KeyBuffer[MAX_PATH]; - OBJECT_ATTRIBUTES ObjectAttributes; - NTSTATUS Status; - - DPRINT("RtlpGetRegistryHandle()\n"); - - if (RelativeTo & RTL_REGISTRY_HANDLE) - { - Status = ZwDuplicateObject(NtCurrentProcess(), - (HANDLE)Path, - NtCurrentProcess(), - KeyHandle, - 0, - 0, - DUPLICATE_SAME_ACCESS); -#ifndef NDEBUG - if(!NT_SUCCESS(Status)) - { - DPRINT("ZwDuplicateObject() failed! Status: 0x%x\n", Status); - } -#endif - - return(Status); - } - - if (RelativeTo & RTL_REGISTRY_OPTIONAL) - RelativeTo &= ~RTL_REGISTRY_OPTIONAL; - - if (RelativeTo >= RTL_REGISTRY_MAXIMUM) - { - DPRINT("Invalid relative flag, parameter invalid!\n"); - return(STATUS_INVALID_PARAMETER); - } - - KeyName.Length = 0; - KeyName.MaximumLength = sizeof(KeyBuffer); - KeyName.Buffer = KeyBuffer; - KeyBuffer[0] = 0; - - switch (RelativeTo) - { - case RTL_REGISTRY_ABSOLUTE: - /* nothing to prefix! */ - break; - - case RTL_REGISTRY_SERVICES: - RtlAppendUnicodeToString(&KeyName, - L"\Registry\Machine\System\CurrentControlSet\Services\"); - break; - - case RTL_REGISTRY_CONTROL: - RtlAppendUnicodeToString(&KeyName, - L"\Registry\Machine\System\CurrentControlSet\Control\"); - break; - - case RTL_REGISTRY_WINDOWS_NT: - RtlAppendUnicodeToString(&KeyName, - L"\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion\"); - break; - - case RTL_REGISTRY_DEVICEMAP: - RtlAppendUnicodeToString(&KeyName, - L"\Registry\Machine\Hardware\DeviceMap\"); - break; - - case RTL_REGISTRY_USER: - Status = RtlFormatCurrentUserKeyPath (&KeyPath); - if (!NT_SUCCESS(Status)) - return(Status); - RtlAppendUnicodeStringToString (&KeyName, - &KeyPath); - RtlFreeUnicodeString (&KeyPath); - RtlAppendUnicodeToString (&KeyName, - L"\"); - break; - } - - if (Path[0] == L'\' && RelativeTo != RTL_REGISTRY_ABSOLUTE) - { - Path++; - } - RtlAppendUnicodeToString(&KeyName, - Path); - - DPRINT("KeyName %wZ\n", &KeyName); - - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE | OBJ_OPENIF, - NULL, - NULL); - - if (Create) - { - Status = ZwCreateKey(KeyHandle, - KEY_ALL_ACCESS, - &ObjectAttributes, - 0, - NULL, - 0, - NULL); - } - else - { - Status = ZwOpenKey(KeyHandle, - KEY_ALL_ACCESS, - &ObjectAttributes); - } - -#ifndef NDEBUG - if(!NT_SUCCESS(Status)) - { - DPRINT("%s failed! Status: 0x%x\n", (Create ? "ZwCreateKey" : "ZwOpenKey"), Status); - } -#endif - - return(Status); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI +/* DATA **********************************************************************/ + +PCWSTR RtlpRegPaths[RTL_REGISTRY_MAXIMUM] = +{ + NULL, + L"\Registry\Machine\System\CurrentControlSet\Services", + L"\Registry\Machine\System\CurrentControlSet\Control", + L"\Registry\Machine\Software\Microsoft\Windows NT\CurrentVersion", + L"\Registry\Machine\Hardware\DeviceMap", + L"\Registry\User\.Default", +}; + +/* PRIVATE FUNCTIONS *********************************************************/ + +NTSTATUS +NTAPI +RtlpGetRegistryHandle(IN ULONG RelativeTo, + IN PCWSTR Path, + IN BOOLEAN Create, + IN PHANDLE KeyHandle) +{ + UNICODE_STRING KeyPath, KeyName; + WCHAR KeyBuffer[MAX_PATH]; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + + /* Check if we just want the handle */ + if (RelativeTo & RTL_REGISTRY_HANDLE) + { + *KeyHandle = (HANDLE)Path; + return STATUS_SUCCESS; + } + + /* Check for optional flag */ + if (RelativeTo & RTL_REGISTRY_OPTIONAL) + { + /* Mask it out */ + RelativeTo &= ~RTL_REGISTRY_OPTIONAL; + } + + /* Fail on invalid parameter */ + if (RelativeTo >= RTL_REGISTRY_MAXIMUM) return STATUS_INVALID_PARAMETER; + + /* Initialize the key name */ + RtlInitEmptyUnicodeString(&KeyName, KeyBuffer, sizeof(KeyBuffer)); + + /* Check if we have to lookup a path to prefix */ + if (RelativeTo != RTL_REGISTRY_ABSOLUTE) + { + /* Check if we need the current user key */ + if (RelativeTo == RTL_REGISTRY_USER) + { + /* Get the path */ + Status = RtlFormatCurrentUserKeyPath(&KeyPath); + if (!NT_SUCCESS(Status)) return(Status); + + /* Append it */ + Status = RtlAppendUnicodeStringToString(&KeyName, &KeyPath); + RtlFreeUnicodeString (&KeyPath); + } + else + { + /* Get one of the prefixes */ + Status = RtlAppendUnicodeToString(&KeyName, + RtlpRegPaths[RelativeTo]); + } + + /* Check for failure, otherwise, append the path separator */ + if (!NT_SUCCESS(Status)) return Status; + Status = RtlAppendUnicodeToString(&KeyName, L"\"); + if (!NT_SUCCESS(Status)) return Status; + } + + /* And now append the path */ + if (Path[0] == L'\' && RelativeTo != RTL_REGISTRY_ABSOLUTE) Path++; // HACK! + Status = RtlAppendUnicodeToString(&KeyName, Path); + if (!NT_SUCCESS(Status)) return Status; + + /* Initialize the object attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Check if we want to create it */ + if (Create) + { + /* Create the key with write privileges */ + Status = ZwCreateKey(KeyHandle, + GENERIC_WRITE, + &ObjectAttributes, + 0, + NULL, + 0, + NULL); + } + else + { + /* Otherwise, just open it with read access */ + Status = ZwOpenKey(KeyHandle, + MAXIMUM_ALLOWED | GENERIC_READ, + &ObjectAttributes); + } + + /* Return status */ + return Status; +} + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +NTSTATUS +NTAPI RtlCheckRegistryKey(IN ULONG RelativeTo, - IN PWSTR Path) -{ - HANDLE KeyHandle; - NTSTATUS Status; - - PAGED_CODE_RTL(); - - Status = RtlpGetRegistryHandle(RelativeTo, - Path, - FALSE, - &KeyHandle); - if (!NT_SUCCESS(Status)) - return(Status); - - ZwClose(KeyHandle); - - return(STATUS_SUCCESS); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI + IN PWSTR Path) +{ + HANDLE KeyHandle; + NTSTATUS Status; + PAGED_CODE_RTL(); + + /* Call the helper */ + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + FALSE, + &KeyHandle); + if (!NT_SUCCESS(Status)) return Status; + + /* All went well, close the handle and return success */ + ZwClose(KeyHandle); + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI RtlCreateRegistryKey(IN ULONG RelativeTo, - IN PWSTR Path) -{ - HANDLE KeyHandle; - NTSTATUS Status; - - PAGED_CODE_RTL(); - - Status = RtlpGetRegistryHandle(RelativeTo, - Path, - TRUE, - &KeyHandle); - if (!NT_SUCCESS(Status)) - return(Status); - - ZwClose(KeyHandle); - - return(STATUS_SUCCESS); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI + IN PWSTR Path) +{ + HANDLE KeyHandle; + NTSTATUS Status; + PAGED_CODE_RTL(); + + /* Call the helper */ + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) return Status; + + /* All went well, close the handle and return success */ + ZwClose(KeyHandle); + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI RtlDeleteRegistryValue(IN ULONG RelativeTo, - IN PCWSTR Path, - IN PCWSTR ValueName) -{ - HANDLE KeyHandle; - NTSTATUS Status; - UNICODE_STRING Name; - - PAGED_CODE_RTL(); - - Status = RtlpGetRegistryHandle(RelativeTo, - (PWSTR)Path, - FALSE, - &KeyHandle); - if (!NT_SUCCESS(Status)) - return(Status); - - RtlInitUnicodeString(&Name, - ValueName); - - Status = ZwDeleteValueKey(KeyHandle, - &Name); - - ZwClose(KeyHandle); - - return(Status); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI -RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath) -{ - HANDLE TokenHandle; - UCHAR Buffer[256]; - PSID_AND_ATTRIBUTES SidBuffer; - ULONG Length; - UNICODE_STRING SidString; - NTSTATUS Status; - - PAGED_CODE_RTL(); - - DPRINT ("RtlFormatCurrentUserKeyPath() called\n"); - - Status = ZwOpenThreadToken (NtCurrentThread (), - TOKEN_QUERY, - TRUE, - &TokenHandle); - if (!NT_SUCCESS (Status)) - { - if (Status != STATUS_NO_TOKEN) - { - DPRINT1 ("ZwOpenThreadToken() failed (Status %lx)\n", Status); - return Status; - } - - Status = ZwOpenProcessToken (NtCurrentProcess (), - TOKEN_QUERY, - &TokenHandle); - if (!NT_SUCCESS (Status)) - { - DPRINT1 ("ZwOpenProcessToken() failed (Status %lx)\n", Status); - return Status; - } - } - - SidBuffer = (PSID_AND_ATTRIBUTES)Buffer; - Status = ZwQueryInformationToken (TokenHandle, - TokenUser, - (PVOID)SidBuffer, - 256, - &Length); - ZwClose (TokenHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("ZwQueryInformationToken() failed (Status %lx)\n", Status); - return Status; - } - - Status = RtlConvertSidToUnicodeString (&SidString, - SidBuffer[0].Sid, - TRUE); - if (!NT_SUCCESS(Status)) - { - DPRINT1 ("RtlConvertSidToUnicodeString() failed (Status %lx)\n", Status); - return Status; - } - - DPRINT ("SidString: '%wZ'\n", &SidString); - - Length = SidString.Length + sizeof(L"\Registry\User\"); - DPRINT ("Length: %lu\n", Length); - - KeyPath->Length = 0; - KeyPath->MaximumLength = Length; - KeyPath->Buffer = RtlpAllocateStringMemory(KeyPath->MaximumLength, TAG_USTR); - if (KeyPath->Buffer == NULL) - { - DPRINT1 ("RtlpAllocateMemory() failed\n"); - RtlFreeUnicodeString (&SidString); - return STATUS_NO_TOKEN; - } - - RtlAppendUnicodeToString (KeyPath, - L"\Registry\User\"); - RtlAppendUnicodeStringToString (KeyPath, - &SidString); - RtlFreeUnicodeString (&SidString); - - return STATUS_SUCCESS; -} - - -/* - * @implemented - */ -NTSTATUS NTAPI + IN PCWSTR Path, + IN PCWSTR ValueName) +{ + HANDLE KeyHandle; + NTSTATUS Status; + UNICODE_STRING Name; + PAGED_CODE_RTL(); + + /* Call the helper */ + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) return Status; + + /* Initialize the key name and delete it */ + RtlInitUnicodeString(&Name, ValueName); + Status = ZwDeleteValueKey(KeyHandle, &Name); + + /* All went well, close the handle and return status */ + ZwClose(KeyHandle); + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlWriteRegistryValue(IN ULONG RelativeTo, + IN PCWSTR Path, + IN PCWSTR ValueName, + IN ULONG ValueType, + IN PVOID ValueData, + IN ULONG ValueLength) +{ + HANDLE KeyHandle; + NTSTATUS Status; + UNICODE_STRING Name; + PAGED_CODE_RTL(); + + /* Call the helper */ + Status = RtlpGetRegistryHandle(RelativeTo, + Path, + TRUE, + &KeyHandle); + if (!NT_SUCCESS(Status)) return Status; + + /* Initialize the key name and set it */ + RtlInitUnicodeString(&Name, ValueName); + Status = ZwSetValueKey(KeyHandle, + &Name, + 0, + ValueType, + ValueData, + ValueLength); + + /* All went well, close the handle and return status */ + ZwClose(KeyHandle); + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess, - OUT PHANDLE KeyHandle) -{ - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING KeyPath; - NTSTATUS Status; - - PAGED_CODE_RTL(); - - Status = RtlFormatCurrentUserKeyPath(&KeyPath); - if (NT_SUCCESS(Status)) - { - InitializeObjectAttributes(&ObjectAttributes, - &KeyPath, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = ZwOpenKey(KeyHandle, - DesiredAccess, - &ObjectAttributes); - RtlFreeUnicodeString(&KeyPath); - if (NT_SUCCESS(Status)) - { - return STATUS_SUCCESS; - } - } - - RtlInitUnicodeString (&KeyPath, - L"\Registry\User\.Default"); - InitializeObjectAttributes(&ObjectAttributes, - &KeyPath, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - Status = ZwOpenKey(KeyHandle, - DesiredAccess, - &ObjectAttributes); - - return Status; -} - + OUT PHANDLE KeyHandle) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyPath; + NTSTATUS Status; + PAGED_CODE_RTL(); + + /* Get the user key */ + Status = RtlFormatCurrentUserKeyPath(&KeyPath); + if (NT_SUCCESS(Status)) + { + /* Initialize the attributes and open it */ + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes); + + /* Free the path and return success if it worked */ + RtlFreeUnicodeString(&KeyPath); + if (NT_SUCCESS(Status)) return STATUS_SUCCESS; + } + + /* It didn't work, so use the default key */ + RtlInitUnicodeString(&KeyPath, RtlpRegPaths[RTL_REGISTRY_USER]); + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes); + + /* Return status */ + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlFormatCurrentUserKeyPath(OUT PUNICODE_STRING KeyPath) +{ + HANDLE TokenHandle; + UCHAR Buffer[256]; + PSID_AND_ATTRIBUTES SidBuffer; + ULONG Length; + UNICODE_STRING SidString; + NTSTATUS Status; + PAGED_CODE_RTL(); + + /* Open the thread token */ + Status = ZwOpenThreadToken(NtCurrentThread(), + TOKEN_QUERY, + TRUE, + &TokenHandle); + if (!NT_SUCCESS(Status)) + { + /* We failed, is it because we don't have a thread token? */ + if (Status != STATUS_NO_TOKEN) return Status; + + /* It is, so use the process token */ + Status = ZwOpenProcessToken(NtCurrentProcess(), + TOKEN_QUERY, + &TokenHandle); + if (!NT_SUCCESS(Status)) return Status; + } + + /* Now query the token information */ + SidBuffer = (PSID_AND_ATTRIBUTES)Buffer; + Status = ZwQueryInformationToken(TokenHandle, + TokenUser, + (PVOID)SidBuffer, + sizeof(Buffer), + &Length); + + /* Close the handle and handle failure */ + ZwClose(TokenHandle); + if (!NT_SUCCESS(Status)) return Status; + + /* Convert the SID */ + Status = RtlConvertSidToUnicodeString(&SidString, SidBuffer[0].Sid, TRUE); + if (!NT_SUCCESS(Status)) return Status; + + /* Add the length of the prefix */ + Length = SidString.Length + sizeof(L"\REGISTRY\USER\"); + + /* Initialize a string */ + RtlInitEmptyUnicodeString(KeyPath, + RtlpAllocateStringMemory(Length, TAG_USTR), + Length); + if (!KeyPath->Buffer) + { + /* Free the string and fail */ + RtlFreeUnicodeString(&SidString); + return STATUS_NO_MEMORY; + } + + /* Append the prefix and SID */ + RtlAppendUnicodeToString(KeyPath, L"\REGISTRY\USER\"); + RtlAppendUnicodeStringToString(KeyPath, &SidString); + + /* Free the temporary string and return success */ + RtlFreeUnicodeString(&SidString); + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlpNtCreateKey(OUT HANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG TitleIndex, + IN PUNICODE_STRING Class, + OUT PULONG Disposition) +{ + /* Check if we have object attributes */ + if (ObjectAttributes) + { + /* Mask out the unsupported flags */ + ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE); + } + + /* Create the key */ + return ZwCreateKey(KeyHandle, + DesiredAccess, + ObjectAttributes, + 0, + NULL, + 0, + Disposition); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlpNtEnumerateSubKey(IN HANDLE KeyHandle, + OUT PUNICODE_STRING SubKeyName, + IN ULONG Index, + IN ULONG Unused) +{ + PKEY_BASIC_INFORMATION KeyInfo = NULL; + ULONG BufferLength = 0; + ULONG ReturnedLength; + NTSTATUS Status; + + /* Check if we have a name */ + if (SubKeyName->MaximumLength) + { + /* Allocate a buffer for it */ + BufferLength = SubKeyName->MaximumLength + + sizeof(KEY_BASIC_INFORMATION); + KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength); + if (!KeyInfo) return STATUS_NO_MEMORY; + } + + /* Enumerate the key */ + Status = ZwEnumerateKey(KeyHandle, + Index, + KeyBasicInformation, + KeyInfo, + BufferLength, + &ReturnedLength); + if (NT_SUCCESS(Status)) + { + /* Check if the name fits */ + if (KeyInfo->NameLength <= SubKeyName->MaximumLength) + { + /* Set the length */ + SubKeyName->Length = KeyInfo->NameLength; + + /* Copy it */ + RtlMoveMemory(SubKeyName->Buffer, + KeyInfo->Name, + SubKeyName->Length); + } + else + { + /* Otherwise, we ran out of buffer space */ + Status = STATUS_BUFFER_OVERFLOW; + } + } + + /* Free the buffer and return status */ + if (KeyInfo) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo); + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlpNtMakeTemporaryKey(IN HANDLE KeyHandle) +{ + /* This just deletes the key */ + return ZwDeleteKey(KeyHandle); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlpNtOpenKey(OUT HANDLE KeyHandle, + IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, + IN ULONG Unused) +{ + /* Check if we have object attributes */ + if (ObjectAttributes) + { + /* Mask out the unsupported flags */ + ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE); + } + + /* Open the key */ + return ZwOpenKey(KeyHandle, DesiredAccess, ObjectAttributes); +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlpNtQueryValueKey(IN HANDLE KeyHandle, + OUT PULONG Type OPTIONAL, + OUT PVOID Data OPTIONAL, + IN OUT PULONG DataLength OPTIONAL, + IN ULONG Unused) +{ + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; + UNICODE_STRING ValueName; + ULONG BufferLength = 0; + NTSTATUS Status; + + /* Clear the value name */ + RtlInitEmptyUnicodeString(&ValueName, NULL, 0); + + /* Check if we were already given a length */ + if (DataLength) BufferLength = *DataLength; + + /* Add the size of the structure */ + BufferLength += FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data); + + /* Allocate memory for the value */ + ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength); + if (!ValueInfo) return STATUS_NO_MEMORY; + + /* Query the value */ + Status = ZwQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + ValueInfo, + BufferLength, + &BufferLength); + if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW)) + { + /* Return the length and type */ + if (DataLength) *DataLength = ValueInfo->DataLength; + if (Type) *Type = ValueInfo->Type; + } + + /* Check if the caller wanted data back, and we got it */ + if ((NT_SUCCESS(Status)) && (Data)) + { + /* Copy it */ + RtlMoveMemory(Data, ValueInfo->Data, ValueInfo->DataLength); + } + + /* Free the memory and return status */ + RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo); + return Status; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +RtlpNtSetValueKey(IN HANDLE KeyHandle, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataLength) +{ + UNICODE_STRING ValueName; + + /* Set the value */ + RtlInitEmptyUnicodeString(&ValueName, NULL, 0); + return ZwSetValueKey(KeyHandle, + &ValueName, + 0, + Type, + Data, + DataLength); +}
/* * @unimplemented @@ -869,234 +1060,4 @@ return(Status); }
- -/* - * @implemented - */ -NTSTATUS NTAPI -RtlWriteRegistryValue(IN ULONG RelativeTo, - IN PCWSTR Path, - IN PCWSTR ValueName, - IN ULONG ValueType, - IN PVOID ValueData, - IN ULONG ValueLength) -{ - HANDLE KeyHandle; - NTSTATUS Status; - UNICODE_STRING Name; - - PAGED_CODE_RTL(); - - Status = RtlpGetRegistryHandle(RelativeTo, - (PWSTR)Path, - TRUE, - &KeyHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlpGetRegistryHandle() failed! Status: 0x%lx\n", Status); - return(Status); - } - - RtlInitUnicodeString(&Name, - ValueName); - - Status = ZwSetValueKey(KeyHandle, - &Name, - 0, - ValueType, - ValueData, - ValueLength); - if (!NT_SUCCESS(Status)) - { - DPRINT1("ZwSetValueKey() failed! Status: 0x%lx\n", Status); - } - - ZwClose(KeyHandle); - - return(Status); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI -RtlpNtCreateKey(OUT HANDLE KeyHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG Unused1, - OUT PULONG Disposition, - IN ULONG Unused2) -{ - if (ObjectAttributes != NULL) - ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE); - - return(ZwCreateKey(KeyHandle, - DesiredAccess, - ObjectAttributes, - 0, - NULL, - 0, - Disposition)); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI -RtlpNtEnumerateSubKey(IN HANDLE KeyHandle, - OUT PUNICODE_STRING SubKeyName, - IN ULONG Index, - IN ULONG Unused) -{ - PKEY_BASIC_INFORMATION KeyInfo = NULL; - ULONG BufferLength = 0; - ULONG ReturnedLength; - NTSTATUS Status; - - if (SubKeyName->MaximumLength != 0) - { - BufferLength = SubKeyName->MaximumLength + - sizeof(KEY_BASIC_INFORMATION); - KeyInfo = RtlpAllocateMemory(BufferLength, TAG_RTLREGISTRY); - if (KeyInfo == NULL) - return(STATUS_NO_MEMORY); - } - - Status = ZwEnumerateKey(KeyHandle, - Index, - KeyBasicInformation, - KeyInfo, - BufferLength, - &ReturnedLength); - if (NT_SUCCESS(Status)) - { - if (KeyInfo->NameLength + sizeof(WCHAR) <= SubKeyName->MaximumLength) - { - memmove(SubKeyName->Buffer, - KeyInfo->Name, - KeyInfo->NameLength); - SubKeyName->Buffer[KeyInfo->NameLength / sizeof(WCHAR)] = 0; - SubKeyName->Length = KeyInfo->NameLength; - } - else - { - Status = STATUS_BUFFER_OVERFLOW; - } - } - - if (KeyInfo != NULL) - { - RtlpFreeMemory(KeyInfo, TAG_RTLREGISTRY); - } - - return(Status); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI -RtlpNtMakeTemporaryKey(IN HANDLE KeyHandle) -{ - return(ZwDeleteKey(KeyHandle)); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI -RtlpNtOpenKey(OUT HANDLE KeyHandle, - IN ACCESS_MASK DesiredAccess, - IN POBJECT_ATTRIBUTES ObjectAttributes, - IN ULONG Unused) -{ - if (ObjectAttributes != NULL) - ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE); - - return(ZwOpenKey(KeyHandle, - DesiredAccess, - ObjectAttributes)); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI -RtlpNtQueryValueKey(IN HANDLE KeyHandle, - OUT PULONG Type OPTIONAL, - OUT PVOID Data OPTIONAL, - IN OUT PULONG DataLength OPTIONAL, - IN ULONG Unused) -{ - PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; - UNICODE_STRING ValueName; - ULONG BufferLength; - ULONG ReturnedLength; - NTSTATUS Status; - - RtlInitUnicodeString(&ValueName, - NULL); - - BufferLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION); - if (DataLength != NULL) - BufferLength = *DataLength; - - ValueInfo = RtlpAllocateMemory(BufferLength, TAG_RTLREGISTRY); - if (ValueInfo == NULL) - return(STATUS_NO_MEMORY); - - Status = ZwQueryValueKey(KeyHandle, - &ValueName, - KeyValuePartialInformation, - ValueInfo, - BufferLength, - &ReturnedLength); - if (NT_SUCCESS(Status)) - { - if (DataLength != NULL) - *DataLength = ValueInfo->DataLength; - - if (Type != NULL) - *Type = ValueInfo->Type; - - if (Data != NULL) - { - memmove(Data, - ValueInfo->Data, - ValueInfo->DataLength); - } - } - - RtlpFreeMemory(ValueInfo, TAG_RTLREGISTRY); - - return(Status); -} - - -/* - * @implemented - */ -NTSTATUS NTAPI -RtlpNtSetValueKey(IN HANDLE KeyHandle, - IN ULONG Type, - IN PVOID Data, - IN ULONG DataLength) -{ - UNICODE_STRING ValueName; - - RtlInitUnicodeString(&ValueName, - NULL); - return(ZwSetValueKey(KeyHandle, - &ValueName, - 0, - Type, - Data, - DataLength)); -} - /* EOF */
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/ntfunc.c?rev=22... ============================================================================== --- trunk/reactos/ntoskrnl/cm/ntfunc.c (original) +++ trunk/reactos/ntoskrnl/cm/ntfunc.c Thu Jun 29 04:30:36 2006 @@ -411,13 +411,26 @@ because NtCreateKey doesn't create trees */ Start = RemainingPath.Buffer; if (*Start == L'\') + { Start++; + //RemainingPath.Length -= sizeof(WCHAR); + //RemainingPath.MaximumLength -= sizeof(WCHAR); + //RemainingPath.Buffer++; + //DPRINT1("String: %wZ\n", &RemainingPath); + } + + if (RemainingPath.Buffer[(RemainingPath.Length / sizeof(WCHAR)) - 1] == '\') + { + RemainingPath.Buffer[(RemainingPath.Length / sizeof(WCHAR)) - 1] = UNICODE_NULL; + RemainingPath.Length -= sizeof(WCHAR); + RemainingPath.MaximumLength -= sizeof(WCHAR); + }
for (i = 1; i < RemainingPath.Length / sizeof(WCHAR); i++) { if (L'\' == RemainingPath.Buffer[i]) { - DPRINT("NtCreateKey() doesn't create trees! (found '\' in remaining path: "%wZ"!)\n", &RemainingPath); + DPRINT1("NtCreateKey() doesn't create trees! (found '\' in remaining path: "%wZ"!)\n", &RemainingPath);
PostCreateKeyInfo.Object = NULL; PostCreateKeyInfo.Status = STATUS_OBJECT_NAME_NOT_FOUND; @@ -1395,6 +1408,13 @@ { return Status; } + } + + if (ObjectAttributes->ObjectName->Buffer[(ObjectAttributes->ObjectName->Length / sizeof(WCHAR)) - 1] == '\') + { + ObjectAttributes->ObjectName->Buffer[(ObjectAttributes->ObjectName->Length / sizeof(WCHAR)) - 1] = UNICODE_NULL; + ObjectAttributes->ObjectName->Length -= sizeof(WCHAR); + ObjectAttributes->ObjectName->MaximumLength -= sizeof(WCHAR); }
/* WINE checks for the length also */
Modified: trunk/reactos/ntoskrnl/cm/regobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cm/regobj.c?rev=22... ============================================================================== --- trunk/reactos/ntoskrnl/cm/regobj.c (original) +++ trunk/reactos/ntoskrnl/cm/regobj.c Thu Jun 29 04:30:36 2006 @@ -110,6 +110,7 @@ Attributes = ObjectCreateInfo->Attributes; if (ObjectType == ObSymbolicLinkType) Attributes |= OBJ_OPENLINK; + Attributes |= OBJ_CASE_INSENSITIVE; // hello! My name is ReactOS CM and I'm brain-dead!
while (TRUE) {