- 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') #define TAG_RTLREGISTRY TAG('R', 't', 'l', 'R')
/* FUNCTIONS ***************************************************************/ /* DATA **********************************************************************/
static NTSTATUS PCWSTR RtlpRegPaths[RTL_REGISTRY_MAXIMUM] =
RtlpGetRegistryHandle(ULONG RelativeTo,
PWSTR Path,
BOOLEAN Create,
PHANDLE KeyHandle)
{ {
UNICODE_STRING KeyPath; NULL,
UNICODE_STRING KeyName; 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]; WCHAR KeyBuffer[MAX_PATH];
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status; NTSTATUS Status;
DPRINT("RtlpGetRegistryHandle()\n"); /* Check if we just want the handle */
if (RelativeTo & RTL_REGISTRY_HANDLE) if (RelativeTo & RTL_REGISTRY_HANDLE)
{ {
Status = ZwDuplicateObject(NtCurrentProcess(), *KeyHandle = (HANDLE)Path;
(HANDLE)Path, return STATUS_SUCCESS;
NtCurrentProcess(),
KeyHandle,
0,
0,
DUPLICATE_SAME_ACCESS);
#ifndef NDEBUG
if(!NT_SUCCESS(Status))
{
DPRINT("ZwDuplicateObject() failed! Status: 0x%x\n", Status);
}
#endif
return(Status);
} }
/* Check for optional flag */
if (RelativeTo & RTL_REGISTRY_OPTIONAL) if (RelativeTo & RTL_REGISTRY_OPTIONAL)
{
/* Mask it out */
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; /* Fail on invalid parameter */
KeyName.MaximumLength = sizeof(KeyBuffer); if (RelativeTo >= RTL_REGISTRY_MAXIMUM) return STATUS_INVALID_PARAMETER;
KeyName.Buffer = KeyBuffer;
KeyBuffer[0] = 0;
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: /* Check if we need the current user key */
/* nothing to prefix! */ if (RelativeTo == RTL_REGISTRY_USER)
break; {
/* Get the path */
Status = RtlFormatCurrentUserKeyPath(&KeyPath);
if (!NT_SUCCESS(Status)) return(Status);
case RTL_REGISTRY_SERVICES: /* Append it */
RtlAppendUnicodeToString(&KeyName, Status = RtlAppendUnicodeStringToString(&KeyName, &KeyPath);
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); RtlFreeUnicodeString (&KeyPath);
RtlAppendUnicodeToString (&KeyName,
L"\\");
break;
} }
else
if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE)
{ {
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, InitializeObjectAttributes(&ObjectAttributes,
&KeyName, &KeyName,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF, OBJ_CASE_INSENSITIVE,
NULL, NULL,
NULL); NULL);
/* Check if we want to create it */
if (Create) if (Create)
{ {
/* Create the key with write privileges */
Status = ZwCreateKey(KeyHandle, Status = ZwCreateKey(KeyHandle,
KEY_ALL_ACCESS, GENERIC_WRITE,
&ObjectAttributes, &ObjectAttributes,
0, 0,
NULL, NULL,
@ -135,76 +120,71 @@ RtlpGetRegistryHandle(ULONG RelativeTo,
} }
else else
{ {
/* Otherwise, just open it with read access */
Status = ZwOpenKey(KeyHandle, Status = ZwOpenKey(KeyHandle,
KEY_ALL_ACCESS, MAXIMUM_ALLOWED | GENERIC_READ,
&ObjectAttributes); &ObjectAttributes);
} }
#ifndef NDEBUG /* Return status */
if(!NT_SUCCESS(Status)) return Status;
{
DPRINT("%s failed! Status: 0x%x\n", (Create ? "ZwCreateKey" : "ZwOpenKey"), Status);
}
#endif
return(Status);
} }
/* PUBLIC FUNCTIONS **********************************************************/
/* /*
* @implemented * @implemented
*/ */
NTSTATUS NTAPI NTSTATUS
NTAPI
RtlCheckRegistryKey(IN ULONG RelativeTo, RtlCheckRegistryKey(IN ULONG RelativeTo,
IN PWSTR Path) IN PWSTR Path)
{ {
HANDLE KeyHandle; HANDLE KeyHandle;
NTSTATUS Status; NTSTATUS Status;
PAGED_CODE_RTL(); PAGED_CODE_RTL();
/* Call the helper */
Status = RtlpGetRegistryHandle(RelativeTo, Status = RtlpGetRegistryHandle(RelativeTo,
Path, Path,
FALSE, FALSE,
&KeyHandle); &KeyHandle);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
return(Status);
/* All went well, close the handle and return success */
ZwClose(KeyHandle); ZwClose(KeyHandle);
return STATUS_SUCCESS;
return(STATUS_SUCCESS);
} }
/* /*
* @implemented * @implemented
*/ */
NTSTATUS NTAPI NTSTATUS
NTAPI
RtlCreateRegistryKey(IN ULONG RelativeTo, RtlCreateRegistryKey(IN ULONG RelativeTo,
IN PWSTR Path) IN PWSTR Path)
{ {
HANDLE KeyHandle; HANDLE KeyHandle;
NTSTATUS Status; NTSTATUS Status;
PAGED_CODE_RTL(); PAGED_CODE_RTL();
/* Call the helper */
Status = RtlpGetRegistryHandle(RelativeTo, Status = RtlpGetRegistryHandle(RelativeTo,
Path, Path,
TRUE, TRUE,
&KeyHandle); &KeyHandle);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
return(Status);
/* All went well, close the handle and return success */
ZwClose(KeyHandle); ZwClose(KeyHandle);
return STATUS_SUCCESS;
return(STATUS_SUCCESS);
} }
/* /*
* @implemented * @implemented
*/ */
NTSTATUS NTAPI NTSTATUS
NTAPI
RtlDeleteRegistryValue(IN ULONG RelativeTo, RtlDeleteRegistryValue(IN ULONG RelativeTo,
IN PCWSTR Path, IN PCWSTR Path,
IN PCWSTR ValueName) IN PCWSTR ValueName)
@ -212,33 +192,111 @@ RtlDeleteRegistryValue(IN ULONG RelativeTo,
HANDLE KeyHandle; HANDLE KeyHandle;
NTSTATUS Status; NTSTATUS Status;
UNICODE_STRING Name; UNICODE_STRING Name;
PAGED_CODE_RTL(); PAGED_CODE_RTL();
/* Call the helper */
Status = RtlpGetRegistryHandle(RelativeTo, Status = RtlpGetRegistryHandle(RelativeTo,
(PWSTR)Path, Path,
FALSE, TRUE,
&KeyHandle); &KeyHandle);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status)) return Status;
return(Status);
RtlInitUnicodeString(&Name, /* Initialize the key name and delete it */
ValueName); RtlInitUnicodeString(&Name, ValueName);
Status = ZwDeleteValueKey(KeyHandle, &Name);
Status = ZwDeleteValueKey(KeyHandle,
&Name);
/* All went well, close the handle and return status */
ZwClose(KeyHandle); ZwClose(KeyHandle);
return Status;
return(Status);
} }
/* /*
* @implemented * @implemented
*/ */
NTSTATUS NTAPI NTSTATUS
RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath) 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; HANDLE TokenHandle;
UCHAR Buffer[256]; UCHAR Buffer[256];
@ -246,125 +304,258 @@ RtlFormatCurrentUserKeyPath (OUT PUNICODE_STRING KeyPath)
ULONG Length; ULONG Length;
UNICODE_STRING SidString; UNICODE_STRING SidString;
NTSTATUS Status; NTSTATUS Status;
PAGED_CODE_RTL(); PAGED_CODE_RTL();
DPRINT ("RtlFormatCurrentUserKeyPath() called\n"); /* Open the thread token */
Status = ZwOpenThreadToken(NtCurrentThread(),
Status = ZwOpenThreadToken (NtCurrentThread (),
TOKEN_QUERY, TOKEN_QUERY,
TRUE, TRUE,
&TokenHandle); &TokenHandle);
if (!NT_SUCCESS (Status)) if (!NT_SUCCESS(Status))
{ {
if (Status != STATUS_NO_TOKEN) /* We failed, is it because we don't have a thread token? */
{ if (Status != STATUS_NO_TOKEN) return Status;
DPRINT1 ("ZwOpenThreadToken() failed (Status %lx)\n", Status);
return Status;
}
Status = ZwOpenProcessToken (NtCurrentProcess (), /* It is, so use the process token */
Status = ZwOpenProcessToken(NtCurrentProcess(),
TOKEN_QUERY, TOKEN_QUERY,
&TokenHandle); &TokenHandle);
if (!NT_SUCCESS (Status)) if (!NT_SUCCESS(Status)) return Status;
{
DPRINT1 ("ZwOpenProcessToken() failed (Status %lx)\n", Status);
return Status;
}
} }
/* Now query the token information */
SidBuffer = (PSID_AND_ATTRIBUTES)Buffer; SidBuffer = (PSID_AND_ATTRIBUTES)Buffer;
Status = ZwQueryInformationToken (TokenHandle, Status = ZwQueryInformationToken(TokenHandle,
TokenUser, TokenUser,
(PVOID)SidBuffer, (PVOID)SidBuffer,
256, sizeof(Buffer),
&Length); &Length);
ZwClose (TokenHandle);
if (!NT_SUCCESS(Status)) /* 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)
{ {
DPRINT1 ("ZwQueryInformationToken() failed (Status %lx)\n", Status); /* Free the string and fail */
return Status; RtlFreeUnicodeString(&SidString);
return STATUS_NO_MEMORY;
} }
Status = RtlConvertSidToUnicodeString (&SidString, /* Append the prefix and SID */
SidBuffer[0].Sid, RtlAppendUnicodeToString(KeyPath, L"\\REGISTRY\\USER\\");
TRUE); RtlAppendUnicodeStringToString(KeyPath, &SidString);
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);
/* Free the temporary string and return success */
RtlFreeUnicodeString(&SidString);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/* /*
* @implemented * @implemented
*/ */
NTSTATUS NTAPI NTSTATUS
RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess, NTAPI
OUT PHANDLE KeyHandle) 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; /* Check if we have object attributes */
UNICODE_STRING KeyPath; 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; 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)) if (NT_SUCCESS(Status))
{ {
InitializeObjectAttributes(&ObjectAttributes, /* Check if the name fits */
&KeyPath, if (KeyInfo->NameLength <= SubKeyName->MaximumLength)
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(KeyHandle,
DesiredAccess,
&ObjectAttributes);
RtlFreeUnicodeString(&KeyPath);
if (NT_SUCCESS(Status))
{ {
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, /* Free the buffer and return status */
L"\\Registry\\User\\.Default"); if (KeyInfo) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
InitializeObjectAttributes(&ObjectAttributes,
&KeyPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = ZwOpenKey(KeyHandle,
DesiredAccess,
&ObjectAttributes);
return Status; 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 * @unimplemented
@ -869,234 +1060,4 @@ RtlQueryRegistryValues(IN ULONG RelativeTo,
return(Status); 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 */ /* EOF */

View file

@ -411,13 +411,26 @@ NtCreateKey(OUT PHANDLE KeyHandle,
because NtCreateKey doesn't create trees */ because NtCreateKey doesn't create trees */
Start = RemainingPath.Buffer; Start = RemainingPath.Buffer;
if (*Start == L'\\') if (*Start == L'\\')
{
Start++; 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++) for (i = 1; i < RemainingPath.Length / sizeof(WCHAR); i++)
{ {
if (L'\\' == RemainingPath.Buffer[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.Object = NULL;
PostCreateKeyInfo.Status = STATUS_OBJECT_NAME_NOT_FOUND; 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 */ /* WINE checks for the length also */
/*if (ObjectAttributes->ObjectName->Length > MAX_NAME_LENGTH) /*if (ObjectAttributes->ObjectName->Length > MAX_NAME_LENGTH)
return(STATUS_BUFFER_OVERFLOW);*/ return(STATUS_BUFFER_OVERFLOW);*/

View file

@ -110,6 +110,7 @@ CmFindObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo,
Attributes = ObjectCreateInfo->Attributes; Attributes = ObjectCreateInfo->Attributes;
if (ObjectType == ObSymbolicLinkType) if (ObjectType == ObSymbolicLinkType)
Attributes |= OBJ_OPENLINK; Attributes |= OBJ_OPENLINK;
Attributes |= OBJ_CASE_INSENSITIVE; // hello! My name is ReactOS CM and I'm brain-dead!
while (TRUE) while (TRUE)
{ {