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

svn path=/trunk/; revision=22682
This commit is contained in:
Alex Ionescu 2006-06-29 00:30:36 +00:00
parent 96c859e6a6
commit bbfd29210c
3 changed files with 489 additions and 507 deletions

View file

@ -21,112 +21,97 @@
#define TAG_RTLREGISTRY TAG('R', 't', 'l', 'R')
/* FUNCTIONS ***************************************************************/
/* DATA **********************************************************************/
static NTSTATUS
RtlpGetRegistryHandle(ULONG RelativeTo,
PWSTR Path,
BOOLEAN Create,
PHANDLE KeyHandle)
PCWSTR RtlpRegPaths[RTL_REGISTRY_MAXIMUM] =
{
UNICODE_STRING KeyPath;
UNICODE_STRING KeyName;
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;
DPRINT("RtlpGetRegistryHandle()\n");
/* Check if we just want the handle */
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);
*KeyHandle = (HANDLE)Path;
return STATUS_SUCCESS;
}
/* Check for optional flag */
if (RelativeTo & RTL_REGISTRY_OPTIONAL)
{
/* Mask it out */
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;
/* Fail on invalid parameter */
if (RelativeTo >= RTL_REGISTRY_MAXIMUM) return STATUS_INVALID_PARAMETER;
switch (RelativeTo)
/* Initialize the key name */
RtlInitEmptyUnicodeString(&KeyName, KeyBuffer, sizeof(KeyBuffer));
/* Check if we have to lookup a path to prefix */
if (RelativeTo != RTL_REGISTRY_ABSOLUTE)
{
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:
/* 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);
RtlAppendUnicodeStringToString (&KeyName,
&KeyPath);
if (!NT_SUCCESS(Status)) return(Status);
/* Append it */
Status = RtlAppendUnicodeStringToString(&KeyName, &KeyPath);
RtlFreeUnicodeString (&KeyPath);
RtlAppendUnicodeToString (&KeyName,
L"\\");
break;
}
if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE)
else
{
Path++;
/* Get one of the prefixes */
Status = RtlAppendUnicodeToString(&KeyName,
RtlpRegPaths[RelativeTo]);
}
RtlAppendUnicodeToString(&KeyName,
Path);
DPRINT("KeyName %wZ\n", &KeyName);
/* 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 | OBJ_OPENIF,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
/* Check if we want to create it */
if (Create)
{
/* Create the key with write privileges */
Status = ZwCreateKey(KeyHandle,
KEY_ALL_ACCESS,
GENERIC_WRITE,
&ObjectAttributes,
0,
NULL,
@ -135,76 +120,71 @@ RtlpGetRegistryHandle(ULONG RelativeTo,
}
else
{
/* Otherwise, just open it with read access */
Status = ZwOpenKey(KeyHandle,
KEY_ALL_ACCESS,
MAXIMUM_ALLOWED | GENERIC_READ,
&ObjectAttributes);
}
#ifndef NDEBUG
if(!NT_SUCCESS(Status))
{
DPRINT("%s failed! Status: 0x%x\n", (Create ? "ZwCreateKey" : "ZwOpenKey"), Status);
}
#endif
return(Status);
/* Return status */
return Status;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
RtlCheckRegistryKey(IN ULONG RelativeTo,
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);
if (!NT_SUCCESS(Status)) return Status;
/* All went well, close the handle and return success */
ZwClose(KeyHandle);
return(STATUS_SUCCESS);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
RtlCreateRegistryKey(IN ULONG RelativeTo,
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);
if (!NT_SUCCESS(Status)) return Status;
/* All went well, close the handle and return success */
ZwClose(KeyHandle);
return(STATUS_SUCCESS);
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS NTAPI
NTSTATUS
NTAPI
RtlDeleteRegistryValue(IN ULONG RelativeTo,
IN PCWSTR Path,
IN PCWSTR ValueName)
@ -212,32 +192,110 @@ RtlDeleteRegistryValue(IN ULONG RelativeTo,
HANDLE KeyHandle;
NTSTATUS Status;
UNICODE_STRING Name;
PAGED_CODE_RTL();
/* Call the helper */
Status = RtlpGetRegistryHandle(RelativeTo,
(PWSTR)Path,
FALSE,
Path,
TRUE,
&KeyHandle);
if (!NT_SUCCESS(Status))
return(Status);
if (!NT_SUCCESS(Status)) return Status;
RtlInitUnicodeString(&Name,
ValueName);
Status = ZwDeleteValueKey(KeyHandle,
&Name);
/* 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);
return Status;
}
/*
* @implemented
*/
NTSTATUS NTAPI
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();
/* 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;
@ -246,125 +304,258 @@ RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath)
ULONG Length;
UNICODE_STRING SidString;
NTSTATUS Status;
PAGED_CODE_RTL();
DPRINT ("RtlFormatCurrentUserKeyPath() called\n");
/* Open the thread token */
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;
}
/* 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))
{
DPRINT1 ("ZwOpenProcessToken() failed (Status %lx)\n", Status);
return Status;
}
if (!NT_SUCCESS(Status)) return Status;
}
/* Now query the token information */
SidBuffer = (PSID_AND_ATTRIBUTES)Buffer;
Status = ZwQueryInformationToken(TokenHandle,
TokenUser,
(PVOID)SidBuffer,
256,
sizeof(Buffer),
&Length);
/* Close the handle and handle failure */
ZwClose(TokenHandle);
if (!NT_SUCCESS(Status))
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)
{
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");
/* Free the string and fail */
RtlFreeUnicodeString(&SidString);
return STATUS_NO_TOKEN;
return STATUS_NO_MEMORY;
}
RtlAppendUnicodeToString (KeyPath,
L"\\Registry\\User\\");
RtlAppendUnicodeStringToString (KeyPath,
&SidString);
RtlFreeUnicodeString (&SidString);
/* 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
RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess,
OUT PHANDLE KeyHandle)
NTSTATUS
NTAPI
RtlpNtCreateKey(OUT HANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG TitleIndex,
IN PUNICODE_STRING Class,
OUT PULONG Disposition)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyPath;
/* 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;
PAGED_CODE_RTL();
/* 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;
}
Status = RtlFormatCurrentUserKeyPath(&KeyPath);
/* Enumerate the key */
Status = ZwEnumerateKey(KeyHandle,
Index,
KeyBasicInformation,
KeyInfo,
BufferLength,
&ReturnedLength);
if (NT_SUCCESS(Status))
{
InitializeObjectAttributes(&ObjectAttributes,
&KeyPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(KeyHandle,
DesiredAccess,
&ObjectAttributes);
RtlFreeUnicodeString(&KeyPath);
if (NT_SUCCESS(Status))
/* Check if the name fits */
if (KeyInfo->NameLength <= SubKeyName->MaximumLength)
{
return STATUS_SUCCESS;
/* 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;
}
}
RtlInitUnicodeString (&KeyPath,
L"\\Registry\\User\\.Default");
InitializeObjectAttributes(&ObjectAttributes,
&KeyPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(KeyHandle,
DesiredAccess,
&ObjectAttributes);
/* 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 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
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 */

View file

@ -411,13 +411,26 @@ NtCreateKey(OUT PHANDLE KeyHandle,
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;
@ -1397,6 +1410,13 @@ NtOpenKey(OUT PHANDLE KeyHandle,
}
}
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 */
/*if (ObjectAttributes->ObjectName->Length > MAX_NAME_LENGTH)
return(STATUS_BUFFER_OVERFLOW);*/

View file

@ -110,6 +110,7 @@ CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
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)
{