-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/cm/ntfunc.c
- * PURPOSE: Ntxxx function for registry access
- * UPDATE HISTORY:
-*/
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/cm/ntfunc.c
+ * PURPOSE: Ntxxx function for registry access
+ *
+ * PROGRAMMERS: No programmer listed.
+ */
/* INCLUDES *****************************************************************/
-#define NTOS_MODE_KERNEL
-#include <ntos.h>
-#include <roscfg.h>
-#include <internal/ob.h>
-#include <limits.h>
-#include <string.h>
-#include <internal/se.h>
-#include <internal/registry.h>
-
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
extern POBJECT_TYPE CmiKeyType;
extern PREGISTRY_HIVE CmiVolatileHive;
+extern LIST_ENTRY CmiKeyObjectListHead;
static BOOLEAN CmiRegistryInitialized = FALSE;
+LIST_ENTRY CmiCallbackHead;
+FAST_MUTEX CmiCallbackLock;
/* FUNCTIONS ****************************************************************/
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
+ IN PVOID Context,
+ IN OUT PLARGE_INTEGER Cookie)
+{
+ PREGISTRY_CALLBACK Callback;
+
+ PAGED_CODE();
+
+ ASSERT(Function && Cookie);
+
+ Callback = ExAllocatePoolWithTag(PagedPool,
+ sizeof(REGISTRY_CALLBACK),
+ TAG('C', 'M', 'c', 'b'));
+ if(Callback != NULL)
+ {
+ /* initialize the callback */
+ ExInitializeRundownProtection(&Callback->RundownRef);
+ Callback->Function = Function;
+ Callback->Context = Context;
+ Callback->PendingDelete = FALSE;
+
+ /* add it to the callback list and receive a cookie for the callback */
+ ExAcquireFastMutex(&CmiCallbackLock);
+ /* FIXME - to receive a unique cookie we'll just return the pointer to the
+ callback object */
+ Callback->Cookie.QuadPart = (ULONG_PTR)Callback;
+ InsertTailList(&CmiCallbackHead, &Callback->ListEntry);
+
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ *Cookie = Callback->Cookie;
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
+{
+ PLIST_ENTRY CurrentEntry;
+
+ PAGED_CODE();
+
+ ExAcquireFastMutex(&CmiCallbackLock);
+
+ for(CurrentEntry = CmiCallbackHead.Flink;
+ CurrentEntry != &CmiCallbackHead;
+ CurrentEntry = CurrentEntry->Flink)
+ {
+ PREGISTRY_CALLBACK CurrentCallback;
+
+ CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
+ if(CurrentCallback->Cookie.QuadPart == Cookie.QuadPart)
+ {
+ if(!CurrentCallback->PendingDelete)
+ {
+ /* found the callback, don't unlink it from the list yet so we don't screw
+ the calling loop */
+ CurrentCallback->PendingDelete = TRUE;
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ /* if the callback is currently executing, wait until it finished */
+ ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef);
+
+ /* time to unlink it. It's now safe because every attempt to acquire a
+ runtime protection on this callback will fail */
+ ExAcquireFastMutex(&CmiCallbackLock);
+ RemoveEntryList(&CurrentCallback->ListEntry);
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ /* free the callback */
+ ExFreePool(CurrentCallback);
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ /* pending delete, pretend like it already is deleted */
+ ExReleaseFastMutex(&CmiCallbackLock);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ }
+
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+NTSTATUS
+CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
+ IN PVOID Argument2)
+{
+ PLIST_ENTRY CurrentEntry;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ PAGED_CODE();
+
+ ExAcquireFastMutex(&CmiCallbackLock);
+
+ for(CurrentEntry = CmiCallbackHead.Flink;
+ CurrentEntry != &CmiCallbackHead;
+ CurrentEntry = CurrentEntry->Flink)
+ {
+ PREGISTRY_CALLBACK CurrentCallback;
+
+ CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
+ if(!CurrentCallback->PendingDelete &&
+ ExAcquireRundownProtectionEx(&CurrentCallback->RundownRef, 1))
+ {
+ /* don't hold locks during the callbacks! */
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ Status = CurrentCallback->Function(CurrentCallback->Context,
+ Argument1,
+ Argument2);
+
+ ExAcquireFastMutex(&CmiCallbackLock);
+ /* don't release the rundown protection before holding the callback lock
+ so the pointer to the next callback isn't cleared in case this callback
+ get's deleted */
+ ExReleaseRundownProtectionEx(&CurrentCallback->RundownRef, 1);
+ if(!NT_SUCCESS(Status))
+ {
+ /* one callback returned failure, don't call any more callbacks */
+ break;
+ }
+ }
+ }
+
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ return Status;
+}
+
+
NTSTATUS STDCALL
NtCreateKey(OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN ULONG CreateOptions,
OUT PULONG Disposition)
{
- UNICODE_STRING RemainingPath;
+ UNICODE_STRING RemainingPath = {0};
+ BOOLEAN FreeRemainingPath = TRUE;
+ ULONG LocalDisposition;
PKEY_OBJECT KeyObject;
- NTSTATUS Status;
- PVOID Object;
- PWSTR End;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PVOID Object = NULL;
PWSTR Start;
+ UNICODE_STRING ObjectName;
+ OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+ unsigned i;
+ REG_PRE_CREATE_KEY_INFORMATION PreCreateKeyInfo;
+ REG_POST_CREATE_KEY_INFORMATION PostCreateKeyInfo;
+ KPROCESSOR_MODE PreviousMode;
+ UNICODE_STRING CapturedClass = {0};
+ HANDLE hKey;
+
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(KeyHandle);
+ if (Disposition != NULL)
+ {
+ ProbeForWriteUlong(Disposition);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ if (Class != NULL)
+ {
+ Status = ProbeAndCaptureUnicodeString(&CapturedClass,
+ PreviousMode,
+ Class);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ /* Capture all the info */
+ DPRINT("Capturing Create Info\n");
+ Status = ObpCaptureObjectAttributes(ObjectAttributes,
+ PreviousMode,
+ CmiKeyType,
+ &ObjectCreateInfo,
+ &ObjectName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
+ return Status;
+ }
- DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n",
- ObjectAttributes->ObjectName,
- KeyHandle,
- ObjectAttributes->RootDirectory);
-
- Status = ObFindObject(ObjectAttributes,
- &Object,
- &RemainingPath,
- CmiKeyType);
+ PostCreateKeyInfo.CompleteName = &ObjectName;
+ PreCreateKeyInfo.CompleteName = &ObjectName;
+ Status = CmiCallRegisteredCallbacks(RegNtPreCreateKey, &PreCreateKeyInfo);
if (!NT_SUCCESS(Status))
{
- return(Status);
+ goto Cleanup;
+ }
+
+ Status = ObFindObject(&ObjectCreateInfo,
+ &ObjectName,
+ (PVOID*)&Object,
+ &RemainingPath,
+ CmiKeyType);
+ if (!NT_SUCCESS(Status))
+ {
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+
+ DPRINT1("CmpFindObject failed, Status: 0x%x\n", Status);
+ goto Cleanup;
}
DPRINT("RemainingPath %wZ\n", &RemainingPath);
- if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] == 0))
+ if (RemainingPath.Length == 0)
{
/* Fail if the key has been deleted */
if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE)
{
- ObDereferenceObject(Object);
- return(STATUS_UNSUCCESSFUL);
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+
+ DPRINT1("Object marked for delete!\n");
+ Status = STATUS_UNSUCCESSFUL;
+ goto Cleanup;
}
- if (Disposition)
- *Disposition = REG_OPENED_EXISTING_KEY;
+ Status = ObpCreateHandle(Object,
+ DesiredAccess,
+ ObjectCreateInfo.Attributes,
+ &hKey);
+
+ if (!NT_SUCCESS(Status))
+ DPRINT1("ObpCreateHandle failed Status 0x%x\n", Status);
- Status = ObCreateHandle(PsGetCurrentProcess(),
- Object,
- DesiredAccess,
- FALSE,
- KeyHandle);
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- DPRINT("Status %x\n", Status);
- ObDereferenceObject(Object);
- return Status;
+ LocalDisposition = REG_OPENED_EXISTING_KEY;
+ goto SuccessReturn;
}
/* If RemainingPath contains \ we must return error
- because NtCreateKey don't create trees */
+ because NtCreateKey doesn't create trees */
Start = RemainingPath.Buffer;
if (*Start == L'\\')
Start++;
- End = wcschr(Start, L'\\');
- if (End != NULL)
+ for (i = 1; i < RemainingPath.Length / sizeof(WCHAR); i++)
{
- ObDereferenceObject(Object);
- return STATUS_OBJECT_NAME_NOT_FOUND;
+ if (L'\\' == RemainingPath.Buffer[i])
+ {
+ DPRINT("NtCreateKey() doesn't create trees! (found \'\\\' in remaining path: \"%wZ\"!)\n", &RemainingPath);
+
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ goto Cleanup;
+ }
}
- DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath.Buffer, Object);
+ DPRINT("RemainingPath %S ParentObject 0x%p\n", RemainingPath.Buffer, Object);
- Status = ObCreateObject(ExGetPreviousMode(),
+ Status = ObCreateObject(PreviousMode,
CmiKeyType,
NULL,
- ExGetPreviousMode(),
+ PreviousMode,
NULL,
sizeof(KEY_OBJECT),
0,
(PVOID*)&KeyObject);
if (!NT_SUCCESS(Status))
{
- return(Status);
+ DPRINT1("ObCreateObject() failed!\n");
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+
+ goto Cleanup;
}
Status = ObInsertObject((PVOID)KeyObject,
DesiredAccess,
0,
NULL,
- KeyHandle);
+ &hKey);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(KeyObject);
- return(Status);
+ DPRINT1("ObInsertObject() failed!\n");
+
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+
+ goto Cleanup;
}
KeyObject->ParentKey = Object;
KeyObject->SubKeys = NULL;
/* Acquire hive lock */
- ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
+ InsertTailList(&CmiKeyObjectListHead, &KeyObject->ListEntry);
/* add key to subkeys of parent if needed */
Status = CmiAddSubKey(KeyObject->RegistryHive,
KeyObject,
&RemainingPath,
TitleIndex,
- Class,
+ &CapturedClass,
CreateOptions);
if (!NT_SUCCESS(Status))
{
- DPRINT("CmiAddSubKey() failed (Status %lx)\n", Status);
+ DPRINT1("CmiAddSubKey() failed (Status %lx)\n", Status);
/* Release hive lock */
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
- ObDereferenceObject(Object);
- return STATUS_UNSUCCESSFUL;
+
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+
+ Status = STATUS_UNSUCCESSFUL;
+ goto Cleanup;
}
- RtlCreateUnicodeString(&KeyObject->Name,
- Start);
+ if (Start == RemainingPath.Buffer)
+ {
+ KeyObject->Name = RemainingPath;
+ FreeRemainingPath = FALSE;
+ }
+ else
+ {
+ RtlpCreateUnicodeString(&KeyObject->Name, Start, NonPagedPool);
+ }
if (KeyObject->RegistryHive == KeyObject->ParentKey->RegistryHive)
{
- KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->BlockOffset;
+ KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->KeyCellOffset;
KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset;
}
else
KeyObject->KeyCell->SecurityKeyOffset = -1;
/* This key must remain in memory unless it is deleted
or file is unloaded */
- ObReferenceObjectByPointer(KeyObject,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- UserMode);
+ ObReferenceObject(KeyObject);
}
CmiAddKeyToList(KeyObject->ParentKey, KeyObject);
VERIFY_KEY_OBJECT(KeyObject);
/* Release hive lock */
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
-
- ObDereferenceObject(KeyObject);
- ObDereferenceObject(Object);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
- if (Disposition)
- *Disposition = REG_CREATED_NEW_KEY;
+ PostCreateKeyInfo.Object = KeyObject;
+ PostCreateKeyInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
CmiSyncHives();
+
+ LocalDisposition = REG_CREATED_NEW_KEY;
+
+SuccessReturn:
+ _SEH_TRY
+ {
+ *KeyHandle = hKey;
+ if (Disposition != NULL)
+ {
+ *Disposition = LocalDisposition;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+Cleanup:
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+ if (Class != NULL)
+ {
+ ReleaseCapturedUnicodeString(&CapturedClass,
+ PreviousMode);
+ }
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+ if (FreeRemainingPath) RtlFreeUnicodeString(&RemainingPath);
+ if (Object != NULL) ObDereferenceObject(Object);
return Status;
}
NTSTATUS STDCALL
NtDeleteKey(IN HANDLE KeyHandle)
{
+ KPROCESSOR_MODE PreviousMode;
PKEY_OBJECT KeyObject;
NTSTATUS Status;
+ REG_DELETE_KEY_INFORMATION DeleteKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
+
+ PAGED_CODE();
- DPRINT("KeyHandle %x\n", KeyHandle);
+ DPRINT("NtDeleteKey(KeyHandle 0x%p) called\n", KeyHandle);
+
+ PreviousMode = ExGetPreviousMode();
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_WRITE,
+ DELETE,
CmiKeyType,
- UserMode,
+ PreviousMode,
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
{
- return(Status);
+ DPRINT1("ObReferenceObjectByHandle() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ DeleteKeyInfo.Object = (PVOID)KeyObject;
+ Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &DeleteKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtDeleteKey, &PostOperationInfo);
+ ObDereferenceObject(KeyObject);
+ return Status;
}
/* Acquire hive lock */
- ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
}
/* Release hive lock */
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
- /* Dereference the object */
+ /* Remove the keep-alive reference */
ObDereferenceObject(KeyObject);
- if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
+
+ if (KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
ObDereferenceObject(KeyObject);
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo);
+
+ /* Dereference the object */
+ ObDereferenceObject(KeyObject);
+
DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
+ DPRINT("HandleCount %lu\n", ObGetObjectHandleCount((PVOID)KeyObject));
/*
* Note:
* have been released.
*/
- return(Status);
+ return Status;
}
IN ULONG Length,
OUT PULONG ResultLength)
{
- PKEY_OBJECT KeyObject;
+ PKEY_OBJECT KeyObject;
+ PKEY_OBJECT SubKeyObject;
PREGISTRY_HIVE RegistryHive;
PKEY_CELL KeyCell, SubKeyCell;
PHASH_TABLE_CELL HashTableBlock;
PKEY_BASIC_INFORMATION BasicInformation;
PKEY_NODE_INFORMATION NodeInformation;
PKEY_FULL_INFORMATION FullInformation;
- PDATA_CELL ClassData;
- ULONG NameSize;
+ PDATA_CELL ClassCell;
+ ULONG NameSize, ClassSize;
+ KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
+ REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
+
+ PAGED_CODE();
- DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
+ PreviousMode = ExGetPreviousMode();
+
+ DPRINT("KH 0x%p I %d KIC %x KI 0x%p L %d RL 0x%p\n",
KeyHandle,
Index,
KeyInformationClass,
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_ENUMERATE_SUB_KEYS,
CmiKeyType,
- UserMode,
+ PreviousMode,
(PVOID *) &KeyObject,
NULL);
if (!NT_SUCCESS(Status))
return(Status);
}
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ EnumerateKeyInfo.Object = (PVOID)KeyObject;
+ EnumerateKeyInfo.Index = Index;
+ EnumerateKeyInfo.KeyInformationClass = KeyInformationClass;
+ EnumerateKeyInfo.Length = Length;
+ EnumerateKeyInfo.ResultLength = ResultLength;
+
+ Status = CmiCallRegisteredCallbacks(RegNtEnumerateKey, &EnumerateKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(KeyObject);
+ return Status;
+ }
+
/* Acquire hive lock */
- ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
KeyCell = KeyObject->KeyCell;
RegistryHive = KeyObject->RegistryHive;
+ SubKeyObject = NULL;
+
+ /* Check for hightest possible sub key index */
+ if (Index >= KeyCell->NumberOfSubKeys + KeyObject->NumberOfSubKeys)
+ {
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
+ CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo);
+ ObDereferenceObject(KeyObject);
+ DPRINT("No more volatile entries\n");
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
/* Get pointer to SubKey */
if (Index >= KeyCell->NumberOfSubKeys)
{
- if (RegistryHive == CmiVolatileHive)
- {
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
- ObDereferenceObject(KeyObject);
- DPRINT("No more volatile entries\n");
- return(STATUS_NO_MORE_ENTRIES);
- }
- else
- {
- ULONG i;
- PKEY_OBJECT CurKey = NULL;
+ PKEY_OBJECT CurKey = NULL;
+ ULONG i;
+ ULONG j;
- /* Search volatile keys */
- for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
- {
- CurKey = KeyObject->SubKeys[i];
- if (CurKey->RegistryHive == CmiVolatileHive)
- {
- if (Index-- == KeyCell->NumberOfSubKeys)
- break;
- }
- }
- if (Index >= KeyCell->NumberOfSubKeys)
+ /* Search for volatile or 'foreign' keys */
+ j = KeyCell->NumberOfSubKeys;
+ for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
+ {
+ CurKey = KeyObject->SubKeys[i];
+ if (CurKey->RegistryHive != RegistryHive)
{
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
- ObDereferenceObject(KeyObject);
- DPRINT("No more non-volatile entries\n");
- return(STATUS_NO_MORE_ENTRIES);
+ if (j == Index)
+ break;
+ j++;
}
- SubKeyCell = CurKey->KeyCell;
}
+
+ if (i >= KeyObject->NumberOfSubKeys)
+ {
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
+ CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
+ ObDereferenceObject(KeyObject);
+ DPRINT("No more non-volatile entries\n");
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ SubKeyObject = CurKey;
+ SubKeyCell = CurKey->KeyCell;
}
else
{
if (KeyCell->HashTableOffset == (BLOCK_OFFSET)-1)
{
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
+ CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
- return(STATUS_NO_MORE_ENTRIES);
+ return STATUS_NO_MORE_ENTRIES;
}
- HashTableBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
+ HashTableBlock = CmiGetCell (RegistryHive, KeyCell->HashTableOffset, NULL);
if (HashTableBlock == NULL)
{
DPRINT("CmiGetBlock() failed\n");
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = STATUS_UNSUCCESSFUL;
+ CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
return STATUS_UNSUCCESSFUL;
}
+
SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive,
HashTableBlock,
Index);
if (SubKeyCell == NULL)
{
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
+ CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
DPRINT("No more entries\n");
- return(STATUS_NO_MORE_ENTRIES);
+ return STATUS_NO_MORE_ENTRIES;
}
Status = STATUS_SUCCESS;
{
case KeyBasicInformation:
/* Check size of buffer */
- NameSize = SubKeyCell->NameSize;
- if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ if (SubKeyObject != NULL)
{
- NameSize *= sizeof(WCHAR);
+ NameSize = SubKeyObject->Name.Length;
+ }
+ else
+ {
+ NameSize = SubKeyCell->NameSize;
+ if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ NameSize *= sizeof(WCHAR);
+ }
}
- *ResultLength = sizeof(KEY_BASIC_INFORMATION) + NameSize;
- if (Length < *ResultLength)
+ *ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) + NameSize;
+
+ /*
+ * NOTE: It's perfetly valid to call NtEnumerateKey to get
+ * all the information but name. Actually the NT4 sound
+ * framework does that while querying parameters from registry.
+ * -- Filip Navara, 19/07/2004
+ */
+ if (Length < FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]))
{
- Status = STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
BasicInformation->TitleIndex = Index;
BasicInformation->NameLength = NameSize;
- if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ if (Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) < NameSize)
{
- CmiCopyPackedName(BasicInformation->Name,
- SubKeyCell->Name,
- SubKeyCell->NameSize);
+ NameSize = Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
}
- else
+
+ if (SubKeyObject != NULL)
{
RtlCopyMemory(BasicInformation->Name,
- SubKeyCell->Name,
- SubKeyCell->NameSize);
+ SubKeyObject->Name.Buffer,
+ NameSize);
+ }
+ else
+ {
+ if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ CmiCopyPackedName(BasicInformation->Name,
+ SubKeyCell->Name,
+ NameSize / sizeof(WCHAR));
+ }
+ else
+ {
+ RtlCopyMemory(BasicInformation->Name,
+ SubKeyCell->Name,
+ NameSize);
+ }
}
}
break;
case KeyNodeInformation:
/* Check size of buffer */
- if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ if (SubKeyObject != NULL)
{
- NameSize = SubKeyCell->NameSize * sizeof(WCHAR);
+ NameSize = SubKeyObject->Name.Length;
}
else
{
NameSize = SubKeyCell->NameSize;
+ if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ NameSize *= sizeof(WCHAR);
+ }
}
- *ResultLength = sizeof(KEY_NODE_INFORMATION) +
- NameSize + SubKeyCell->ClassSize;
+ ClassSize = SubKeyCell->ClassSize;
- if (Length < *ResultLength)
+ *ResultLength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) +
+ NameSize + ClassSize;
+
+ if (Length < FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]))
{
- Status = STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
NodeInformation->ClassLength = SubKeyCell->ClassSize;
NodeInformation->NameLength = NameSize;
- if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) < NameSize)
{
- CmiCopyPackedName(NodeInformation->Name,
- SubKeyCell->Name,
- SubKeyCell->NameSize);
+ NameSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]);
+ ClassSize = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
}
- else
+ else if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
+ NameSize < ClassSize)
+ {
+ ClassSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
+ NameSize;
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
+ if (SubKeyObject != NULL)
{
RtlCopyMemory(NodeInformation->Name,
- SubKeyCell->Name,
- SubKeyCell->NameSize);
+ SubKeyObject->Name.Buffer,
+ NameSize);
+ }
+ else
+ {
+ if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
+ {
+ CmiCopyPackedName(NodeInformation->Name,
+ SubKeyCell->Name,
+ NameSize / sizeof(WCHAR));
+ }
+ else
+ {
+ RtlCopyMemory(NodeInformation->Name,
+ SubKeyCell->Name,
+ NameSize);
+ }
}
- if (SubKeyCell->ClassSize != 0)
+ if (ClassSize != 0)
{
- ClassData=CmiGetBlock(KeyObject->RegistryHive,
- SubKeyCell->ClassNameOffset,
- NULL);
- wcsncpy(NodeInformation->Name + SubKeyCell->NameSize,
- (PWCHAR)ClassData->Data,
- SubKeyCell->ClassSize);
+ ClassCell = CmiGetCell (KeyObject->RegistryHive,
+ SubKeyCell->ClassNameOffset,
+ NULL);
+ RtlCopyMemory (NodeInformation->Name + SubKeyCell->NameSize,
+ ClassCell->Data,
+ ClassSize);
}
}
break;
case KeyFullInformation:
- /* Check size of buffer */
- *ResultLength = sizeof(KEY_FULL_INFORMATION) +
- SubKeyCell->ClassSize;
+ ClassSize = SubKeyCell->ClassSize;
- if (Length < *ResultLength)
+ *ResultLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) +
+ ClassSize;
+
+ /* Check size of buffer */
+ if (Length < FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]))
{
- Status = STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
sizeof(WCHAR);
FullInformation->ClassLength = SubKeyCell->ClassSize;
- FullInformation->SubKeys = SubKeyCell->NumberOfSubKeys;
+ FullInformation->SubKeys = CmiGetNumberOfSubKeys(KeyObject); //SubKeyCell->NumberOfSubKeys;
FullInformation->MaxNameLen = CmiGetMaxNameLength(KeyObject);
FullInformation->MaxClassLen = CmiGetMaxClassLength(KeyObject);
FullInformation->Values = SubKeyCell->NumberOfValues;
CmiGetMaxValueNameLength(RegistryHive, SubKeyCell);
FullInformation->MaxValueDataLen =
CmiGetMaxValueDataLength(RegistryHive, SubKeyCell);
- if (SubKeyCell->ClassSize != 0)
+
+ if (Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) < ClassSize)
+ {
+ ClassSize = Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
+ if (ClassSize != 0)
{
- ClassData = CmiGetBlock(KeyObject->RegistryHive,
+ ClassCell = CmiGetCell (KeyObject->RegistryHive,
SubKeyCell->ClassNameOffset,
NULL);
- wcsncpy(FullInformation->Class,
- (PWCHAR)ClassData->Data,
- SubKeyCell->ClassSize);
+ RtlCopyMemory (FullInformation->Class,
+ ClassCell->Data,
+ ClassSize);
}
}
break;
break;
}
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
+
ObDereferenceObject(KeyObject);
DPRINT("Returning status %x\n", Status);
PKEY_CELL KeyCell;
PVALUE_CELL ValueCell;
PDATA_CELL DataCell;
- ULONG NameSize;
+ ULONG NameSize, DataSize;
PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
- DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
+ PAGED_CODE();
+
+ DPRINT("KH 0x%p I %d KVIC %x KVI 0x%p L %d RL 0x%p\n",
KeyHandle,
Index,
KeyValueInformationClass,
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *) &KeyObject,
NULL);
}
/* Acquire hive lock */
- ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
if (!NT_SUCCESS(Status))
{
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
return Status;
}
case KeyValueBasicInformation:
NameSize = ValueCell->NameSize;
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
- {
+ {
NameSize *= sizeof(WCHAR);
}
- *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameSize;
- if (Length < *ResultLength)
+
+ *ResultLength = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) + NameSize;
+
+ if (Length < FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]))
{
- Status = STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
- ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
+ ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
KeyValueInformation;
ValueBasicInformation->TitleIndex = 0;
ValueBasicInformation->Type = ValueCell->DataType;
ValueBasicInformation->NameLength = NameSize;
+
+ if (Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) <
+ NameSize)
+ {
+ NameSize = Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
{
CmiCopyPackedName(ValueBasicInformation->Name,
ValueCell->Name,
- ValueCell->NameSize);
+ NameSize / sizeof(WCHAR));
}
else
{
break;
case KeyValuePartialInformation:
- *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
- (ValueCell->DataSize & LONG_MAX);
- if (Length < *ResultLength)
+ DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+
+ *ResultLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) +
+ DataSize;
+
+ if (Length < FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]))
{
- Status = STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
KeyValueInformation;
ValuePartialInformation->TitleIndex = 0;
ValuePartialInformation->Type = ValueCell->DataType;
- ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX;
- if(ValueCell->DataSize >0)
+ ValuePartialInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+
+ if (Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) <
+ DataSize)
+ {
+ DataSize = Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
+ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
{
- DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
- RtlCopyMemory(ValuePartialInformation->Data,
+ DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
+ RtlCopyMemory(ValuePartialInformation->Data,
DataCell->Data,
- ValueCell->DataSize & LONG_MAX);
+ DataSize);
}
else
{
- RtlCopyMemory(ValuePartialInformation->Data,
- &ValueCell->DataOffset,
- ValueCell->DataSize & LONG_MAX);
+ RtlCopyMemory(ValuePartialInformation->Data,
+ &ValueCell->DataOffset,
+ DataSize);
}
- DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
}
break;
{
NameSize *= sizeof(WCHAR);
}
- *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
- NameSize + (ValueCell->DataSize & LONG_MAX);
- if (Length < *ResultLength)
+ DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+
+ *ResultLength = ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
+ Name[0]) + NameSize, sizeof(PVOID)) + DataSize;
+
+ if (Length < FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]))
{
- Status = STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
- ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
+ ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
KeyValueInformation;
ValueFullInformation->TitleIndex = 0;
ValueFullInformation->Type = ValueCell->DataType;
ValueFullInformation->NameLength = NameSize;
+ ValueFullInformation->DataOffset =
+ (ULONG_PTR)ValueFullInformation->Name -
+ (ULONG_PTR)ValueFullInformation +
+ ValueFullInformation->NameLength;
+ ValueFullInformation->DataOffset =
+ ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID));
+ ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+
+ if (Length < ValueFullInformation->DataOffset)
+ {
+ NameSize = Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
+ DataSize = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+ else if (Length - ValueFullInformation->DataOffset < DataSize)
+ {
+ DataSize = Length - ValueFullInformation->DataOffset;
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
{
CmiCopyPackedName(ValueFullInformation->Name,
ValueCell->Name,
- ValueCell->NameSize);
+ NameSize / sizeof(WCHAR));
}
else
{
RtlCopyMemory(ValueFullInformation->Name,
ValueCell->Name,
- ValueCell->NameSize);
+ NameSize);
}
- ValueFullInformation->DataOffset =
- (ULONG)ValueFullInformation->Name - (ULONG)ValueFullInformation +
- ValueFullInformation->NameLength;
- ValueFullInformation->DataOffset =
- (ValueFullInformation->DataOffset + 3) & 0xfffffffc;
- ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX;
- if (ValueCell->DataSize > 0)
+
+ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
{
- DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
+ DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
RtlCopyMemory((PCHAR) ValueFullInformation
+ ValueFullInformation->DataOffset,
- DataCell->Data,
- ValueCell->DataSize & LONG_MAX);
+ DataCell->Data, DataSize);
}
else
{
RtlCopyMemory((PCHAR) ValueFullInformation
+ ValueFullInformation->DataOffset,
- &ValueCell->DataOffset,
- ValueCell->DataSize & LONG_MAX);
+ &ValueCell->DataOffset, DataSize);
}
}
break;
Status = STATUS_UNSUCCESSFUL;
}
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
return Status;
NTSTATUS Status;
PKEY_OBJECT KeyObject;
PREGISTRY_HIVE RegistryHive;
+ KPROCESSOR_MODE PreviousMode;
+
+ PAGED_CODE();
DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle);
+ PreviousMode = ExGetPreviousMode();
+
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_QUERY_VALUE,
+ 0,
CmiKeyType,
- UserMode,
+ PreviousMode,
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
RegistryHive = KeyObject->RegistryHive;
/* Acquire hive lock */
- ExAcquireResourceExclusiveLite(&RegistryHive->HiveResource,
- TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
if (IsNoFileHive(RegistryHive))
{
Status = CmiFlushRegistryHive(RegistryHive);
}
- ExReleaseResourceLite(&RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
IN POBJECT_ATTRIBUTES ObjectAttributes)
{
UNICODE_STRING RemainingPath;
- NTSTATUS Status;
- PVOID Object;
-
- DPRINT("NtOpenFile(KH %x DA %x OA %x OA->ON '%wZ'\n",
+ KPROCESSOR_MODE PreviousMode;
+ PVOID Object = NULL;
+ HANDLE hKey = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+ UNICODE_STRING ObjectName;
+ OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+ REG_PRE_OPEN_KEY_INFORMATION PreOpenKeyInfo;
+ REG_POST_OPEN_KEY_INFORMATION PostOpenKeyInfo;
+
+ PAGED_CODE();
+
+ DPRINT("NtOpenKey(KH 0x%p DA %x OA 0x%p OA->ON '%wZ'\n",
KeyHandle,
DesiredAccess,
ObjectAttributes,
ObjectAttributes ? ObjectAttributes->ObjectName : NULL);
+ /* Check place for result handle, if it's null - return immediately */
+ if (KeyHandle == NULL)
+ return(STATUS_INVALID_PARAMETER);
+
+ PreviousMode = ExGetPreviousMode();
+
+ if(PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWriteHandle(KeyHandle);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if(!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
+ /* WINE checks for the length also */
+ /*if (ObjectAttributes->ObjectName->Length > MAX_NAME_LENGTH)
+ return(STATUS_BUFFER_OVERFLOW);*/
+
+ /* Capture all the info */
+ DPRINT("Capturing Create Info\n");
+ Status = ObpCaptureObjectAttributes(ObjectAttributes,
+ PreviousMode,
+ CmiKeyType,
+ &ObjectCreateInfo,
+ &ObjectName);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
+ return Status;
+ }
+
+ PostOpenKeyInfo.CompleteName = &ObjectName;
+ PreOpenKeyInfo.CompleteName = &ObjectName;
+ Status = CmiCallRegisteredCallbacks(RegNtPreOpenKey, &PreOpenKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+ return Status;
+ }
+
+
RemainingPath.Buffer = NULL;
- Status = ObFindObject(ObjectAttributes,
- &Object,
- &RemainingPath,
- CmiKeyType);
+
+ Status = ObFindObject(&ObjectCreateInfo,
+ &ObjectName,
+ (PVOID*)&Object,
+ &RemainingPath,
+ CmiKeyType);
if (!NT_SUCCESS(Status))
{
- return(Status);
+ DPRINT("CmpFindObject() returned 0x%08lx\n", Status);
+ Status = STATUS_INVALID_HANDLE; /* Because ObFindObject returns STATUS_UNSUCCESSFUL */
+ goto openkey_cleanup;
}
VERIFY_KEY_OBJECT((PKEY_OBJECT) Object);
if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0))
{
- ObDereferenceObject(Object);
- return(STATUS_UNSUCCESSFUL);
+ RtlFreeUnicodeString(&RemainingPath);
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ goto openkey_cleanup;
}
+ RtlFreeUnicodeString(&RemainingPath);
+
/* Fail if the key has been deleted */
if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
{
- ObDereferenceObject(Object);
- return(STATUS_UNSUCCESSFUL);
+ Status = STATUS_UNSUCCESSFUL;
+ goto openkey_cleanup;
}
- Status = ObCreateHandle(PsGetCurrentProcess(),
- Object,
- DesiredAccess,
- FALSE,
- KeyHandle);
- ObDereferenceObject(Object);
+ Status = ObpCreateHandle(Object,
+ DesiredAccess,
+ ObjectCreateInfo.Attributes,
+ &hKey);
- if (!NT_SUCCESS(Status))
+openkey_cleanup:
+
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+ PostOpenKeyInfo.Object = NT_SUCCESS(Status) ? (PVOID)Object : NULL;
+ PostOpenKeyInfo.Status = Status;
+ CmiCallRegisteredCallbacks (RegNtPostOpenKey, &PostOpenKeyInfo);
+ if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
+ if (Object)
{
- return(Status);
+ ObDereferenceObject(Object);
+ }
+
+ if (NT_SUCCESS(Status))
+ {
+ _SEH_TRY
+ {
+ *KeyHandle = hKey;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
}
+ _SEH_END;
+ }
- return(STATUS_SUCCESS);
+ return Status;
}
PKEY_NODE_INFORMATION NodeInformation;
PKEY_FULL_INFORMATION FullInformation;
PREGISTRY_HIVE RegistryHive;
- PDATA_CELL ClassData;
+ PDATA_CELL ClassCell;
PKEY_OBJECT KeyObject;
PKEY_CELL KeyCell;
+ ULONG NameSize, ClassSize;
NTSTATUS Status;
+ REG_QUERY_KEY_INFORMATION QueryKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
- DPRINT("NtQueryKey(KH %x KIC %x KI %x L %d RL %x)\n",
+ PAGED_CODE();
+
+ DPRINT("NtQueryKey(KH 0x%p KIC %x KI 0x%p L %d RL 0x%p)\n",
KeyHandle,
KeyInformationClass,
KeyInformation,
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_READ,
+ (KeyInformationClass != KeyNameInformation ? KEY_QUERY_VALUE : 0),
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *) &KeyObject,
NULL);
if (!NT_SUCCESS(Status))
return Status;
}
- /* Acquire hive lock */
- ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
-
- VERIFY_KEY_OBJECT(KeyObject);
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ QueryKeyInfo.Object = (PVOID)KeyObject;
+ QueryKeyInfo.KeyInformationClass = KeyInformationClass;
+ QueryKeyInfo.KeyInformation = KeyInformation;
+ QueryKeyInfo.Length = Length;
+ QueryKeyInfo.ResultLength = ResultLength;
+
+ Status = CmiCallRegisteredCallbacks(RegNtQueryKey, &QueryKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(KeyObject);
+ return Status;
+ }
+
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
+
+ VERIFY_KEY_OBJECT(KeyObject);
/* Get pointer to KeyCell */
KeyCell = KeyObject->KeyCell;
switch (KeyInformationClass)
{
case KeyBasicInformation:
- /* Check size of buffer */
- *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
- KeyObject->Name.Length;
+ NameSize = KeyObject->Name.Length;
- if (Length < *ResultLength)
+ *ResultLength = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
+
+ /* Check size of buffer */
+ if (Length < FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]))
{
- Status = STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
BasicInformation->TitleIndex = 0;
BasicInformation->NameLength = KeyObject->Name.Length;
- if (KeyCell->Flags & REG_KEY_NAME_PACKED)
- {
- CmiCopyPackedName(BasicInformation->Name,
- KeyCell->Name,
- KeyCell->NameSize);
- }
- else
+ if (Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) <
+ NameSize)
{
- RtlCopyMemory(BasicInformation->Name,
- KeyCell->Name,
- KeyCell->NameSize);
+ NameSize = Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
}
+
+ RtlCopyMemory(BasicInformation->Name,
+ KeyObject->Name.Buffer,
+ NameSize);
}
break;
case KeyNodeInformation:
- /* Check size of buffer */
- *ResultLength = sizeof(KEY_NODE_INFORMATION) +
- KeyObject->Name.Length + KeyCell->ClassSize;
+ NameSize = KeyObject->Name.Length;
+ ClassSize = KeyCell->ClassSize;
+
+ *ResultLength = FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) +
+ NameSize + ClassSize;
+ /* Check size of buffer */
if (Length < *ResultLength)
{
- Status = STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
NodeInformation->ClassLength = KeyCell->ClassSize;
NodeInformation->NameLength = KeyObject->Name.Length;
- if (KeyCell->Flags & REG_KEY_NAME_PACKED)
+ if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) < NameSize)
{
- CmiCopyPackedName(NodeInformation->Name,
- KeyCell->Name,
- KeyCell->NameSize);
+ NameSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]);
+ ClassSize = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
}
- else
+ else if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
+ NameSize < ClassSize)
{
- RtlCopyMemory(NodeInformation->Name,
- KeyCell->Name,
- KeyCell->NameSize);
+ ClassSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) -
+ NameSize;
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
}
- if (KeyCell->ClassSize != 0)
+ RtlCopyMemory(NodeInformation->Name,
+ KeyObject->Name.Buffer,
+ NameSize);
+
+ if (ClassSize != 0)
{
- ClassData = CmiGetBlock(KeyObject->RegistryHive,
+ ClassCell = CmiGetCell (KeyObject->RegistryHive,
KeyCell->ClassNameOffset,
NULL);
- wcsncpy(NodeInformation->Name + KeyObject->Name.Length,
- (PWCHAR)ClassData->Data,
- KeyCell->ClassSize);
+ RtlCopyMemory (NodeInformation->Name + KeyObject->Name.Length,
+ ClassCell->Data,
+ ClassSize);
}
}
break;
case KeyFullInformation:
- /* Check size of buffer */
- *ResultLength = sizeof(KEY_FULL_INFORMATION) +
- KeyCell->ClassSize;
+ ClassSize = KeyCell->ClassSize;
- if (Length < *ResultLength)
+ *ResultLength = FIELD_OFFSET(KEY_FULL_INFORMATION, Class) +
+ ClassSize;
+
+ /* Check size of buffer */
+ if (Length < FIELD_OFFSET(KEY_FULL_INFORMATION, Class))
{
- Status = STATUS_BUFFER_OVERFLOW;
+ Status = STATUS_BUFFER_TOO_SMALL;
}
else
{
FullInformation->TitleIndex = 0;
FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR);
FullInformation->ClassLength = KeyCell->ClassSize;
- FullInformation->SubKeys = KeyCell->NumberOfSubKeys;
+ FullInformation->SubKeys = CmiGetNumberOfSubKeys(KeyObject); //KeyCell->NumberOfSubKeys;
FullInformation->MaxNameLen = CmiGetMaxNameLength(KeyObject);
FullInformation->MaxClassLen = CmiGetMaxClassLength(KeyObject);
FullInformation->Values = KeyCell->NumberOfValues;
CmiGetMaxValueNameLength(RegistryHive, KeyCell);
FullInformation->MaxValueDataLen =
CmiGetMaxValueDataLength(RegistryHive, KeyCell);
- if (KeyCell->ClassSize != 0)
+
+ if (Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]) < ClassSize)
{
- ClassData=CmiGetBlock(KeyObject->RegistryHive,
- KeyCell->ClassNameOffset,
- NULL);
- wcsncpy(FullInformation->Class,
- (PWCHAR)ClassData->Data,
- KeyCell->ClassSize);
+ ClassSize = Length - FIELD_OFFSET(KEY_FULL_INFORMATION, Class[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
+ if (ClassSize)
+ {
+ ClassCell = CmiGetCell (KeyObject->RegistryHive,
+ KeyCell->ClassNameOffset,
+ NULL);
+ RtlCopyMemory (FullInformation->Class,
+ ClassCell->Data, ClassSize);
}
}
break;
- default:
- DPRINT1("Not handling 0x%x\n", KeyInformationClass);
+
+ case KeyNameInformation:
+ case KeyCachedInformation:
+ case KeyFlagsInformation:
+ DPRINT1("Key information class 0x%x not yet implemented!\n", KeyInformationClass);
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ default:
+ DPRINT1("Not handling 0x%x\n", KeyInformationClass);
+ Status = STATUS_INVALID_INFO_CLASS;
break;
}
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo);
+
ObDereferenceObject(KeyObject);
return(Status);
OUT PULONG ResultLength)
{
NTSTATUS Status;
- ULONG NameSize;
+ ULONG NameSize, DataSize;
PKEY_OBJECT KeyObject;
PREGISTRY_HIVE RegistryHive;
PKEY_CELL KeyCell;
PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
+ REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
- DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
+ PAGED_CODE();
+
+ DPRINT("NtQueryValueKey(KeyHandle 0x%p ValueName %S Length %x)\n",
KeyHandle, ValueName->Buffer, Length);
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
{
- DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
+ DPRINT1("ObReferenceObjectByHandle() failed with status %x %p\n", Status, KeyHandle);
+ return Status;
+ }
+
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ QueryValueKeyInfo.Object = (PVOID)KeyObject;
+ QueryValueKeyInfo.ValueName = ValueName;
+ QueryValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass;
+ QueryValueKeyInfo.Length = Length;
+ QueryValueKeyInfo.ResultLength = ResultLength;
+
+ Status = CmiCallRegisteredCallbacks(RegNtPreQueryValueKey, &QueryValueKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(KeyObject);
return Status;
}
/* Acquire hive lock */
- ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
KeyCell = KeyObject->KeyCell;
RegistryHive = KeyObject->RegistryHive;
- /* Get Value block of interest */
+ /* Get value cell by name */
Status = CmiScanKeyForValue(RegistryHive,
KeyCell,
ValueName,
if (!NT_SUCCESS(Status))
{
DPRINT("CmiScanKeyForValue() failed with status %x\n", Status);
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
- ObDereferenceObject(KeyObject);
- return(Status);
+ goto ByeBye;
}
- else if (ValueCell != NULL)
+
+ Status = STATUS_SUCCESS;
+ switch (KeyValueInformationClass)
{
- switch (KeyValueInformationClass)
- {
- case KeyValueBasicInformation:
- NameSize = ValueCell->NameSize;
- if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
- {
- NameSize *= sizeof(WCHAR);
- }
- *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameSize;
- if (Length < *ResultLength)
- {
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
- KeyValueInformation;
- ValueBasicInformation->TitleIndex = 0;
- ValueBasicInformation->Type = ValueCell->DataType;
- ValueBasicInformation->NameLength = NameSize;
- if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
- {
- CmiCopyPackedName(ValueBasicInformation->Name,
- ValueCell->Name,
- ValueCell->NameSize);
- }
- else
- {
- RtlCopyMemory(ValueBasicInformation->Name,
- ValueCell->Name,
- ValueCell->NameSize * sizeof(WCHAR));
- }
- }
- break;
+ case KeyValueBasicInformation:
+ NameSize = ValueCell->NameSize;
+ if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+ {
+ NameSize *= sizeof(WCHAR);
+ }
- case KeyValuePartialInformation:
- *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
- + (ValueCell->DataSize & LONG_MAX);
- if (Length < *ResultLength)
- {
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
- KeyValueInformation;
- ValuePartialInformation->TitleIndex = 0;
- ValuePartialInformation->Type = ValueCell->DataType;
- ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX;
- if (ValueCell->DataSize > 0)
- {
- DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
- RtlCopyMemory(ValuePartialInformation->Data,
- DataCell->Data,
- ValueCell->DataSize & LONG_MAX);
- }
- else
- {
- RtlCopyMemory(ValuePartialInformation->Data,
- &ValueCell->DataOffset,
- ValueCell->DataSize & LONG_MAX);
- }
- }
- break;
+ *ResultLength = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) +
+ NameSize;
- case KeyValueFullInformation:
- NameSize = ValueCell->NameSize;
- if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
- {
- NameSize *= sizeof(WCHAR);
- }
- *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
- NameSize + (ValueCell->DataSize & LONG_MAX);
- if (Length < *ResultLength)
- {
- Status = STATUS_BUFFER_TOO_SMALL;
- }
- else
- {
- ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
- KeyValueInformation;
- ValueFullInformation->TitleIndex = 0;
- ValueFullInformation->Type = ValueCell->DataType;
- ValueFullInformation->NameLength = NameSize;
- if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
- {
- CmiCopyPackedName(ValueFullInformation->Name,
- ValueCell->Name,
- ValueCell->NameSize);
- }
- else
- {
- RtlCopyMemory(ValueFullInformation->Name,
- ValueCell->Name,
- ValueCell->NameSize);
- }
- ValueFullInformation->DataOffset =
- (ULONG)ValueFullInformation->Name - (ULONG)ValueFullInformation +
- ValueFullInformation->NameLength;
- ValueFullInformation->DataOffset =
- (ValueFullInformation->DataOffset + 3) & 0xfffffffc;
- ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX;
- if (ValueCell->DataSize > 0)
- {
- DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
- RtlCopyMemory((PCHAR) ValueFullInformation
- + ValueFullInformation->DataOffset,
- DataCell->Data,
- ValueCell->DataSize & LONG_MAX);
- }
- else
- {
- RtlCopyMemory((PCHAR) ValueFullInformation
- + ValueFullInformation->DataOffset,
- &ValueCell->DataOffset,
- ValueCell->DataSize & LONG_MAX);
- }
- }
- break;
- default:
- DPRINT1("Not handling 0x%x\n", KeyValueInformationClass);
- break;
- }
- }
- else
- {
- Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ if (Length < FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]))
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
+ KeyValueInformation;
+ ValueBasicInformation->TitleIndex = 0;
+ ValueBasicInformation->Type = ValueCell->DataType;
+ ValueBasicInformation->NameLength = NameSize;
+
+ if (Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]) <
+ NameSize)
+ {
+ NameSize = Length - FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
+ if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+ {
+ CmiCopyPackedName(ValueBasicInformation->Name,
+ ValueCell->Name,
+ NameSize / sizeof(WCHAR));
+ }
+ else
+ {
+ RtlCopyMemory(ValueBasicInformation->Name,
+ ValueCell->Name,
+ NameSize);
+ }
+ }
+ break;
+
+ case KeyValuePartialInformation:
+ DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+
+ *ResultLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) +
+ DataSize;
+
+ if (Length < FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]))
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
+ KeyValueInformation;
+ ValuePartialInformation->TitleIndex = 0;
+ ValuePartialInformation->Type = ValueCell->DataType;
+ ValuePartialInformation->DataLength = DataSize;
+
+ if (Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) <
+ DataSize)
+ {
+ DataSize = Length - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
+ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
+ {
+ DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
+ RtlCopyMemory(ValuePartialInformation->Data,
+ DataCell->Data,
+ DataSize);
+ }
+ else
+ {
+ RtlCopyMemory(ValuePartialInformation->Data,
+ &ValueCell->DataOffset,
+ DataSize);
+ }
+ }
+ break;
+
+ case KeyValueFullInformation:
+ NameSize = ValueCell->NameSize;
+ if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+ {
+ NameSize *= sizeof(WCHAR);
+ }
+ DataSize = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+
+ *ResultLength = ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
+ Name[0]) + NameSize, sizeof(PVOID)) + DataSize;
+
+ if (Length < FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]))
+ {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
+ KeyValueInformation;
+ ValueFullInformation->TitleIndex = 0;
+ ValueFullInformation->Type = ValueCell->DataType;
+ ValueFullInformation->NameLength = NameSize;
+ ValueFullInformation->DataOffset =
+ (ULONG_PTR)ValueFullInformation->Name -
+ (ULONG_PTR)ValueFullInformation +
+ ValueFullInformation->NameLength;
+ ValueFullInformation->DataOffset =
+ ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID));
+ ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+
+ if (Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) <
+ NameSize)
+ {
+ NameSize = Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]);
+ DataSize = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+ else if (ROUND_UP(Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
+ Name[0]) - NameSize, sizeof(PVOID)) < DataSize)
+ {
+ DataSize = ROUND_UP(Length - FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION,
+ Name[0]) - NameSize, sizeof(PVOID));
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
+ if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
+ {
+ CmiCopyPackedName(ValueFullInformation->Name,
+ ValueCell->Name,
+ NameSize / sizeof(WCHAR));
+ }
+ else
+ {
+ RtlCopyMemory(ValueFullInformation->Name,
+ ValueCell->Name,
+ NameSize);
+ }
+ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
+ {
+ DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
+ RtlCopyMemory((PCHAR) ValueFullInformation
+ + ValueFullInformation->DataOffset,
+ DataCell->Data,
+ DataSize);
+ }
+ else
+ {
+ RtlCopyMemory((PCHAR) ValueFullInformation
+ + ValueFullInformation->DataOffset,
+ &ValueCell->DataOffset,
+ DataSize);
+ }
+ }
+ break;
+
+ default:
+ DPRINT1("Not handling 0x%x\n", KeyValueInformationClass);
+ Status = STATUS_INVALID_INFO_CLASS;
+ break;
}
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ByeBye:;
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
return Status;
PREGISTRY_HIVE RegistryHive;
PKEY_CELL KeyCell;
PVALUE_CELL ValueCell;
- BLOCK_OFFSET VBOffset;
+ BLOCK_OFFSET ValueCellOffset;
PDATA_CELL DataCell;
PDATA_CELL NewDataCell;
- PHBIN pBin;
ULONG DesiredAccess;
+ REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
+ ULONG DataCellSize;
+
+ PAGED_CODE();
- DPRINT("NtSetValueKey(KeyHandle %x ValueName '%wZ' Type %d)\n",
+ DPRINT("NtSetValueKey(KeyHandle 0x%p ValueName '%wZ' Type %d)\n",
KeyHandle, ValueName, Type);
DesiredAccess = KEY_SET_VALUE;
- if (Type == REG_LINK)
- DesiredAccess |= KEY_CREATE_LINK;
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
DesiredAccess,
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
return(Status);
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ SetValueKeyInfo.Object = (PVOID)KeyObject;
+ SetValueKeyInfo.ValueName = ValueName;
+ SetValueKeyInfo.TitleIndex = TitleIndex;
+ SetValueKeyInfo.Type = Type;
+ SetValueKeyInfo.Data = Data;
+ SetValueKeyInfo.DataSize = DataSize;
+ Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(KeyObject);
+ return Status;
+ }
+
/* Acquire hive lock exclucively */
- ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
KeyCell,
ValueName,
&ValueCell,
- &VBOffset);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Value not found. Status 0x%X\n", Status);
-
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
- ObDereferenceObject(KeyObject);
- return(Status);
- }
-
- if (ValueCell == NULL)
+ &ValueCellOffset);
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
{
DPRINT("Allocate new value cell\n");
Status = CmiAddValueToKey(RegistryHive,
KeyCell,
+ KeyObject->KeyCellOffset,
ValueName,
&ValueCell,
- &VBOffset);
- if (NT_SUCCESS(Status))
- {
- CmiMarkBlockDirty(RegistryHive, VBOffset);
- }
+ &ValueCellOffset);
}
if (!NT_SUCCESS(Status))
{
DPRINT("Cannot add value. Status 0x%X\n", Status);
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
- return(Status);
+ return Status;
}
DPRINT("DataSize %lu\n", DataSize);
DPRINT("ValueCell %p\n", ValueCell);
DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
- if (DataSize <= 4)
+ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
+ (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
+ {
+ DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
+ DataCellSize = (DataCell->CellSize < 0 ? -DataCell->CellSize : DataCell->CellSize) - sizeof(CELL_HEADER);
+ }
+ else
+ {
+ DataCell = NULL;
+ DataCellSize = 0;
+ }
+
+
+ if (DataSize <= sizeof(BLOCK_OFFSET))
{
- /* If datasize <= 4 then write in valueblock directly */
+ /* If data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */
DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
- if ((ValueCell->DataSize >= 0) &&
- (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
+ if (DataCell)
{
- CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
+ CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
}
RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize);
- ValueCell->DataSize = DataSize | 0x80000000;
- ValueCell->DataType = Type;
- RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize);
- CmiMarkBlockDirty(RegistryHive, VBOffset);
- }
- else if (DataSize <= (ULONG) (ValueCell->DataSize & 0x7fffffff))
- {
- /* If new data size is <= current then overwrite current data */
- DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin);
- RtlZeroMemory(DataCell->Data, ValueCell->DataSize);
- RtlCopyMemory(DataCell->Data, Data, DataSize);
- ValueCell->DataSize = DataSize;
+ ValueCell->DataSize = DataSize | REG_DATA_IN_OFFSET;
ValueCell->DataType = Type;
-
- /* Update time of heap */
- if (!IsNoFileHive(RegistryHive))
- {
- NtQuerySystemTime(&pBin->DateModified);
- }
- CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
+ CmiMarkBlockDirty(RegistryHive, ValueCellOffset);
}
- else
+ else
{
- /*
- * New data size is larger than the current, destroy current
- * data block and allocate a new one.
- */
- BLOCK_OFFSET NewOffset;
-
- DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+ if (DataSize > DataCellSize)
+ {
+ /*
+ * New data size is larger than the current, destroy current
+ * data block and allocate a new one.
+ */
+ BLOCK_OFFSET NewOffset;
+
+ DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+
+ Status = CmiAllocateCell (RegistryHive,
+ sizeof(CELL_HEADER) + DataSize,
+ (PVOID *)&NewDataCell,
+ &NewOffset);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
- if ((ValueCell->DataSize >= 0) &&
- (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
- {
- CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
- ValueCell->DataSize = 0;
- ValueCell->DataType = 0;
- ValueCell->DataOffset = 0xffffffff;
- }
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
+ ObDereferenceObject(KeyObject);
- Status = CmiAllocateBlock(RegistryHive,
- (PVOID *)&NewDataCell,
- DataSize,
- &NewOffset);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
- ObDereferenceObject(KeyObject);
+ if (DataCell)
+ {
+ CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
+ }
- return(Status);
- }
+ ValueCell->DataOffset = NewOffset;
+ DataCell = NewDataCell;
+ }
- RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize);
- ValueCell->DataSize = DataSize;
+ RtlCopyMemory(DataCell->Data, Data, DataSize);
+ ValueCell->DataSize = DataSize & REG_DATA_SIZE_MASK;
ValueCell->DataType = Type;
- ValueCell->DataOffset = NewOffset;
CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
+ CmiMarkBlockDirty(RegistryHive, ValueCellOffset);
}
/* Mark link key */
- if ((_wcsicmp(ValueName->Buffer, L"SymbolicLinkValue") == 0) &&
- (Type == REG_LINK))
+ if ((Type == REG_LINK) &&
+ (_wcsicmp(ValueName->Buffer, L"SymbolicLinkValue") == 0))
{
KeyCell->Flags |= REG_KEY_LINK_CELL;
- CmiMarkBlockDirty(RegistryHive, KeyObject->BlockOffset);
}
- /* Update time of heap */
- if (!IsNoFileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
- {
- NtQuerySystemTime(&pBin->DateModified);
- }
+ KeQuerySystemTime (&KeyCell->LastWriteTime);
+ CmiMarkBlockDirty (RegistryHive, KeyObject->KeyCellOffset);
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
CmiSyncHives();
DPRINT("Return Status 0x%X\n", Status);
- return(Status);
+ return Status;
}
{
PKEY_OBJECT KeyObject;
NTSTATUS Status;
+ REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
+ KPROCESSOR_MODE PreviousMode;
+ UNICODE_STRING CapturedValueName;
+
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
- KEY_QUERY_VALUE,
+ KEY_SET_VALUE,
CmiKeyType,
- UserMode,
+ PreviousMode,
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
return Status;
}
+ Status = ProbeAndCaptureUnicodeString(&CapturedValueName,
+ PreviousMode,
+ ValueName);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Fail;
+ }
+ DeleteValueKeyInfo.Object = (PVOID)KeyObject;
+ DeleteValueKeyInfo.ValueName = &CapturedValueName;
+
+ /* FIXME - check if value exists before calling the callbacks? */
+ Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey, &DeleteValueKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ReleaseCapturedUnicodeString(&CapturedValueName,
+ PreviousMode);
+Fail:
+ ObDereferenceObject(KeyObject);
+ return Status;
+ }
+
/* Acquire hive lock */
- ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
Status = CmiDeleteValueFromKey(KeyObject->RegistryHive,
KeyObject->KeyCell,
- KeyObject->BlockOffset,
+ KeyObject->KeyCellOffset,
ValueName);
+ KeQuerySystemTime (&KeyObject->KeyCell->LastWriteTime);
+ CmiMarkBlockDirty (KeyObject->RegistryHive, KeyObject->KeyCellOffset);
+
/* Release hive lock */
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
- ObDereferenceObject(KeyObject);
+ ReleaseCapturedUnicodeString(&CapturedValueName,
+ PreviousMode);
- CmiSyncHives();
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ PostOperationInfo.Status = Status;
+
+ CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey, &PostOperationInfo);
+
+ ObDereferenceObject (KeyObject);
+
+ CmiSyncHives ();
return Status;
}
ULONG Length;
NTSTATUS Status;
+ PAGED_CODE();
+
DPRINT ("NtLoadKey2() called\n");
#if 0
- if (!SeSinglePrivilegeCheck (SeRestorePrivilege, KeGetPreviousMode ()))
+ if (!SeSinglePrivilegeCheck (SeRestorePrivilege, ExGetPreviousMode ()))
return STATUS_PRIVILEGE_NOT_HELD;
#endif
if (Buffer == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
- Status = NtQueryObject (FileObjectAttributes->RootDirectory,
+ Status = ZwQueryObject (FileObjectAttributes->RootDirectory,
ObjectNameInformation,
Buffer,
BufferSize,
DPRINT ("Full name: '%wZ'\n", NamePointer);
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
Status = CmiLoadHive (KeyObjectAttributes,
NamePointer,
Flags);
DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status);
}
+ /* Release hive lock */
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
if (Buffer != NULL)
ExFreePool (Buffer);
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG CompletionFilter,
- IN BOOLEAN Asynchroneous,
- OUT PVOID ChangeBuffer,
+ IN BOOLEAN WatchSubtree,
+ OUT PVOID Buffer,
IN ULONG Length,
- IN BOOLEAN WatchSubtree)
+ IN BOOLEAN Asynchronous)
{
UNIMPLEMENTED;
return(STATUS_NOT_IMPLEMENTED);
}
+#if 0
+NTSTATUS STDCALL
+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 Buffer,
+ IN ULONG Length,
+ IN BOOLEAN Asynchronous)
+{
+ return NtNotifyChangeMultipleKeys(KeyHandle,
+ 0,
+ NULL,
+ Event,
+ ApcRoutine,
+ ApcContext,
+ IoStatusBlock,
+ CompletionFilter,
+ WatchTree,
+ Buffer,
+ Length,
+ Asynchronous);
+}
+
+#endif
NTSTATUS STDCALL
NtQueryMultipleValueKey (IN HANDLE KeyHandle,
NTSTATUS Status;
PUCHAR DataPtr;
ULONG i;
+ REG_QUERY_MULTIPLE_VALUE_KEY_INFORMATION QueryMultipleValueKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
+
+ PAGED_CODE();
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle(KeyHandle,
KEY_QUERY_VALUE,
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *) &KeyObject,
NULL);
if (!NT_SUCCESS(Status))
return(Status);
}
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ QueryMultipleValueKeyInfo.Object = (PVOID)KeyObject;
+ QueryMultipleValueKeyInfo.ValueEntries = ValueList;
+ QueryMultipleValueKeyInfo.EntryCount = NumberOfValues;
+ QueryMultipleValueKeyInfo.ValueBuffer = Buffer;
+ QueryMultipleValueKeyInfo.BufferLength = Length;
+ QueryMultipleValueKeyInfo.RequiredBufferLength = ReturnLength;
+
+ Status = CmiCallRegisteredCallbacks(RegNtPreQueryMultipleValueKey, &QueryMultipleValueKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(KeyObject);
+ return Status;
+ }
+
/* Acquire hive lock */
- ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
break;
}
- BufferLength = (BufferLength + 3) & 0xfffffffc;
+ BufferLength = ROUND_UP(BufferLength, sizeof(PVOID));
- if (BufferLength + (ValueCell->DataSize & LONG_MAX) <= *Length)
+ if (BufferLength + (ValueCell->DataSize & REG_DATA_SIZE_MASK) <= *Length)
{
- DataPtr = (PUCHAR)(((ULONG)DataPtr + 3) & 0xfffffffc);
+ DataPtr = (PUCHAR)ROUND_UP((ULONG_PTR)DataPtr, sizeof(PVOID));
ValueList[i].Type = ValueCell->DataType;
- ValueList[i].DataLength = ValueCell->DataSize & LONG_MAX;
- ValueList[i].DataOffset = (ULONG) DataPtr - (ULONG) Buffer;
+ ValueList[i].DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+ ValueList[i].DataOffset = (ULONG_PTR)DataPtr - (ULONG_PTR)Buffer;
- if (ValueCell->DataSize > 0)
+ if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
{
- DataCell = CmiGetBlock(RegistryHive,
+ DataCell = CmiGetCell (RegistryHive,
ValueCell->DataOffset,
NULL);
RtlCopyMemory(DataPtr,
DataCell->Data,
- ValueCell->DataSize & LONG_MAX);
+ ValueCell->DataSize & REG_DATA_SIZE_MASK);
}
else
{
RtlCopyMemory(DataPtr,
&ValueCell->DataOffset,
- ValueCell->DataSize & LONG_MAX);
+ ValueCell->DataSize & REG_DATA_SIZE_MASK);
}
- DataPtr += ValueCell->DataSize & LONG_MAX;
+ DataPtr += ValueCell->DataSize & REG_DATA_SIZE_MASK;
}
else
{
Status = STATUS_BUFFER_TOO_SMALL;
}
- BufferLength += ValueCell->DataSize & LONG_MAX;
+ BufferLength += ValueCell->DataSize & REG_DATA_SIZE_MASK;
}
if (NT_SUCCESS(Status))
*ReturnLength = BufferLength;
/* Release hive lock */
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostQueryMultipleValueKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
PKEY_OBJECT KeyObject;
NTSTATUS Status;
+ PAGED_CODE();
+
DPRINT ("NtSaveKey() called\n");
#if 0
- if (!SeSinglePrivilegeCheck (SeBackupPrivilege, KeGetPreviousMode ()))
+ if (!SeSinglePrivilegeCheck (SeBackupPrivilege, ExGetPreviousMode ()))
return STATUS_PRIVILEGE_NOT_HELD;
#endif
Status = ObReferenceObjectByHandle (KeyHandle,
0,
CmiKeyType,
- KeGetPreviousMode(),
+ ExGetPreviousMode(),
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS(Status))
}
/* Acquire hive lock exclucively */
- ExAcquireResourceExclusiveLite (&KeyObject->RegistryHive->HiveResource,
- TRUE);
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
/* Refuse to save a volatile key */
if (KeyObject->RegistryHive == CmiVolatileHive)
{
DPRINT1 ("Cannot save a volatile key\n");
- ExReleaseResourceLite (&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
ObDereferenceObject (KeyObject);
return STATUS_ACCESS_DENIED;
}
if (!NT_SUCCESS(Status))
{
DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status);
- ExReleaseResourceLite (&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
ObDereferenceObject (KeyObject);
return(Status);
}
{
DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status);
CmiRemoveRegistryHive (TempHive);
- ExReleaseResourceLite (&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
ObDereferenceObject (KeyObject);
return(Status);
}
CmiRemoveRegistryHive (TempHive);
/* Release hive lock */
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
ObDereferenceObject (KeyObject);
return STATUS_SUCCESS;
}
+/*
+ * @unimplemented
+ */
+NTSTATUS
+STDCALL
+NtSaveKeyEx(
+ IN HANDLE KeyHandle,
+ IN HANDLE FileHandle,
+ IN ULONG Flags // REG_STANDARD_FORMAT, etc..
+ )
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
NTSTATUS STDCALL
NtSetInformationKey (IN HANDLE KeyHandle,
- IN CINT KeyInformationClass,
+ IN KEY_SET_INFORMATION_CLASS KeyInformationClass,
IN PVOID KeyInformation,
IN ULONG KeyInformationLength)
{
- UNIMPLEMENTED;
- return(STATUS_NOT_IMPLEMENTED);
+ PKEY_OBJECT KeyObject;
+ NTSTATUS Status;
+ REG_SET_INFORMATION_KEY_INFORMATION SetInformationKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
+
+ PAGED_CODE();
+
+ /* Verify that the handle is valid and is a registry key */
+ Status = ObReferenceObjectByHandle (KeyHandle,
+ KEY_SET_VALUE,
+ CmiKeyType,
+ ExGetPreviousMode(),
+ (PVOID *)&KeyObject,
+ NULL);
+ if (!NT_SUCCESS (Status))
+ {
+ DPRINT ("ObReferenceObjectByHandle() failed with status %x\n", Status);
+ return Status;
+ }
+
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ SetInformationKeyInfo.Object = (PVOID)KeyObject;
+ SetInformationKeyInfo.KeySetInformationClass = KeyInformationClass;
+ SetInformationKeyInfo.KeySetInformation = KeyInformation;
+ SetInformationKeyInfo.KeySetInformationLength = KeyInformationLength;
+
+ Status = CmiCallRegisteredCallbacks(RegNtSetInformationKey, &SetInformationKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (KeyObject);
+ return Status;
+ }
+
+ if (KeyInformationClass != KeyWriteTimeInformation)
+ {
+ Status = STATUS_INVALID_INFO_CLASS;
+ }
+
+ else if (KeyInformationLength != sizeof (KEY_WRITE_TIME_INFORMATION))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else
+ {
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
+ VERIFY_KEY_OBJECT(KeyObject);
+
+ KeyObject->KeyCell->LastWriteTime.QuadPart =
+ ((PKEY_WRITE_TIME_INFORMATION)KeyInformation)->LastWriteTime.QuadPart;
+
+ CmiMarkBlockDirty (KeyObject->RegistryHive,
+ KeyObject->KeyCellOffset);
+
+ /* Release hive lock */
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ }
+
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostSetInformationKey, &PostOperationInfo);
+
+ ObDereferenceObject (KeyObject);
+
+ if (NT_SUCCESS(Status))
+ {
+ CmiSyncHives ();
+ }
+
+ DPRINT ("NtSaveKey() done\n");
+
+ return STATUS_SUCCESS;
}
PREGISTRY_HIVE RegistryHive;
NTSTATUS Status;
+ PAGED_CODE();
+
DPRINT ("NtUnloadKey() called\n");
#if 0
- if (!SeSinglePrivilegeCheck (SeRestorePrivilege, KeGetPreviousMode ()))
+ if (!SeSinglePrivilegeCheck (SeRestorePrivilege, ExGetPreviousMode ()))
return STATUS_PRIVILEGE_NOT_HELD;
#endif
+ /* Acquire registry lock exclusively */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
Status = CmiDisconnectHive (KeyObjectAttributes,
&RegistryHive);
if (!NT_SUCCESS (Status))
{
DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status);
+ ExReleaseResourceLite (&CmiRegistryLock);
+ KeLeaveCriticalRegion();
return Status;
}
DPRINT ("RegistryHive %p\n", RegistryHive);
- /* Acquire hive list lock exclusively */
- ExAcquireResourceExclusiveLite (&CmiHiveListLock,
- TRUE);
-
#if 0
/* Flush hive */
if (!IsNoFileHive (RegistryHive))
CmiFlushRegistryHive (RegistryHive);
#endif
- /* Release hive list lock */
- ExReleaseResourceLite (&CmiHiveListLock);
-
CmiRemoveRegistryHive (RegistryHive);
+ /* Release registry lock */
+ ExReleaseResourceLite (&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
DPRINT ("NtUnloadKey() done\n");
return STATUS_SUCCESS;
{
NTSTATUS Status;
+ PAGED_CODE();
+
if (CmiRegistryInitialized == TRUE)
return STATUS_ACCESS_DENIED;
- /* FIXME: save boot log file */
+ /* Save boot log file */
+ IopSaveBootLogToFile();
Status = CmiInitHives (SetUpBoot);