-/*
- * 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 <string.h>
-#include <roscfg.h>
-#include <internal/ob.h>
-#include <internal/se.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 ****************************************************************/
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS STDCALL
CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
- IN PVOID Context,
- IN OUT PLARGE_INTEGER Cookie
- )
+ IN PVOID Context,
+ IN OUT PLARGE_INTEGER Cookie)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ 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;
}
+
/*
- * @unimplemented
+ * @implemented
*/
-
NTSTATUS STDCALL
-CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
+CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ 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;
}
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);
+ goto Cleanup;
+ }
- 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);
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+ goto Cleanup;
+ }
+
+ Status = ObFindObject(&ObjectCreateInfo,
+ &ObjectName,
+ (PVOID*)&Object,
+ &RemainingPath,
+ CmiKeyType);
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+ 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);
- RtlFreeUnicodeString(&RemainingPath);
- return(STATUS_UNSUCCESSFUL);
- }
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
- if (Disposition)
- *Disposition = REG_OPENED_EXISTING_KEY;
+ DPRINT1("Object marked for delete!\n");
+ Status = STATUS_UNSUCCESSFUL;
+ goto Cleanup;
+ }
- Status = ObCreateHandle(PsGetCurrentProcess(),
+ Status = ObpCreateHandle(PsGetCurrentProcess(),
Object,
DesiredAccess,
TRUE,
- KeyHandle);
+ &hKey);
- DPRINT("Status %x\n", Status);
- ObDereferenceObject(Object);
- RtlFreeUnicodeString(&RemainingPath);
- return Status;
+ if (!NT_SUCCESS(Status))
+ DPRINT1("ObpCreateHandle failed Status 0x%x\n", Status);
+
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+
+ 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);
- RtlFreeUnicodeString(&RemainingPath);
- 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);
- RtlFreeUnicodeString(&RemainingPath);
- return(Status);
+ DPRINT1("ObInsertObject() failed!\n");
+
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+
+ goto Cleanup;
}
KeyObject->ParentKey = Object;
/* Acquire hive lock */
KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ 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);
- RtlFreeUnicodeString(&RemainingPath);
- return STATUS_UNSUCCESSFUL;
+
+ PostCreateKeyInfo.Object = NULL;
+ PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
+ CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+
+ Status = STATUS_UNSUCCESSFUL;
+ goto Cleanup;
}
if (Start == RemainingPath.Buffer)
{
KeyObject->Name = RemainingPath;
+ FreeRemainingPath = FALSE;
}
else
{
- RtlCreateUnicodeString(&KeyObject->Name,
- Start);
- RtlFreeUnicodeString(&RemainingPath);
+ RtlpCreateUnicodeString(&KeyObject->Name, Start, NonPagedPool);
}
if (KeyObject->RegistryHive == KeyObject->ParentKey->RegistryHive)
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);
+ ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
- ObDereferenceObject(KeyObject);
- ObDereferenceObject(Object);
-
- 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:
+ 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 */
KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ 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;
}
PKEY_NODE_INFORMATION NodeInformation;
PKEY_FULL_INFORMATION FullInformation;
PDATA_CELL ClassCell;
- ULONG NameSize;
+ ULONG NameSize, ClassSize;
+ KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
+ REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
+
+ PAGED_CODE();
+
+ PreviousMode = ExGetPreviousMode();
- DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
+ 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 */
KeEnterCriticalRegion();
- ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
/* Check for hightest possible sub key index */
if (Index >= KeyCell->NumberOfSubKeys + KeyObject->NumberOfSubKeys)
{
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ 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;
for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
{
CurKey = KeyObject->SubKeys[i];
- if (CurKey->RegistryHive == CmiVolatileHive ||
- CurKey->RegistryHive != RegistryHive)
+ if (CurKey->RegistryHive != RegistryHive)
{
if (j == Index)
break;
if (i >= KeyObject->NumberOfSubKeys)
{
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ 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;
{
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;
}
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;
}
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;
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 (Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) < NameSize)
+ {
+ NameSize = Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
if (SubKeyObject != NULL)
{
- BasicInformation->NameLength = SubKeyObject->Name.Length;
RtlCopyMemory(BasicInformation->Name,
SubKeyObject->Name.Buffer,
- SubKeyObject->Name.Length);
+ NameSize);
}
else
{
- BasicInformation->NameLength = NameSize;
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
{
CmiCopyPackedName(BasicInformation->Name,
SubKeyCell->Name,
- SubKeyCell->NameSize);
+ NameSize / sizeof(WCHAR));
}
else
{
RtlCopyMemory(BasicInformation->Name,
SubKeyCell->Name,
- SubKeyCell->NameSize);
+ NameSize);
}
}
}
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->TitleIndex = Index;
NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + NameSize;
NodeInformation->ClassLength = SubKeyCell->ClassSize;
+ NodeInformation->NameLength = NameSize;
+
+ if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) < NameSize)
+ {
+ NameSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]);
+ ClassSize = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+ 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)
{
- NodeInformation->NameLength = SubKeyObject->Name.Length;
RtlCopyMemory(NodeInformation->Name,
SubKeyObject->Name.Buffer,
- SubKeyObject->Name.Length);
+ NameSize);
}
else
{
- NodeInformation->NameLength = NameSize;
if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
{
CmiCopyPackedName(NodeInformation->Name,
SubKeyCell->Name,
- SubKeyCell->NameSize);
+ NameSize / sizeof(WCHAR));
}
else
{
RtlCopyMemory(NodeInformation->Name,
SubKeyCell->Name,
- SubKeyCell->NameSize);
+ NameSize);
}
}
- if (SubKeyCell->ClassSize != 0)
+ if (ClassSize != 0)
{
ClassCell = CmiGetCell (KeyObject->RegistryHive,
SubKeyCell->ClassNameOffset,
NULL);
RtlCopyMemory (NodeInformation->Name + SubKeyCell->NameSize,
ClassCell->Data,
- SubKeyCell->ClassSize);
+ 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
{
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)
{
ClassCell = CmiGetCell (KeyObject->RegistryHive,
SubKeyCell->ClassNameOffset,
NULL);
RtlCopyMemory (FullInformation->Class,
ClassCell->Data,
- SubKeyCell->ClassSize);
+ 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 */
KeEnterCriticalRegion();
- ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ 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 & REG_DATA_SIZE_MASK);
- 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
{
ValuePartialInformation->TitleIndex = 0;
ValuePartialInformation->Type = ValueCell->DataType;
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 = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
- RtlCopyMemory(ValuePartialInformation->Data,
+ RtlCopyMemory(ValuePartialInformation->Data,
DataCell->Data,
- ValueCell->DataSize & REG_DATA_SIZE_MASK);
+ DataSize);
}
else
{
- RtlCopyMemory(ValuePartialInformation->Data,
- &ValueCell->DataOffset,
- ValueCell->DataSize & REG_DATA_SIZE_MASK);
+ RtlCopyMemory(ValuePartialInformation->Data,
+ &ValueCell->DataOffset,
+ DataSize);
}
}
break;
{
NameSize *= sizeof(WCHAR);
}
- *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
- NameSize + (ValueCell->DataSize & REG_DATA_SIZE_MASK);
- 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 =
- ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID));
- ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
{
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
RtlCopyMemory((PCHAR) ValueFullInformation
+ ValueFullInformation->DataOffset,
- DataCell->Data,
- ValueCell->DataSize & REG_DATA_SIZE_MASK);
+ DataCell->Data, DataSize);
}
else
{
RtlCopyMemory((PCHAR) ValueFullInformation
+ ValueFullInformation->DataOffset,
- &ValueCell->DataOffset,
- ValueCell->DataSize & REG_DATA_SIZE_MASK);
+ &ValueCell->DataOffset, DataSize);
}
}
break;
Status = STATUS_UNSUCCESSFUL;
}
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
ObDereferenceObject(KeyObject);
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))
/* Acquire hive lock */
KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&RegistryHive->HiveResource,
- TRUE);
+ 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("NtOpenKey(KH %x DA %x OA %x OA->ON '%wZ'\n",
+ KPROCESSOR_MODE PreviousMode;
+ PVOID Object = NULL;
+ HANDLE hKey;
+ 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);
+ ObpReleaseCapturedAttributes(&ObjectCreateInfo);
if (!NT_SUCCESS(Status))
{
- return(Status);
+ DPRINT("CmpFindObject() returned 0x%08lx\n", Status);
+ Status = STATUS_INVALID_HANDLE; /* Because CmpFindObject returns STATUS_UNSUCCESSFUL */
+ hKey = *KeyHandle; /* Preserve hkResult value */
+ goto openkey_cleanup;
}
VERIFY_KEY_OBJECT((PKEY_OBJECT) Object);
if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0))
{
- ObDereferenceObject(Object);
RtlFreeUnicodeString(&RemainingPath);
- return STATUS_OBJECT_NAME_NOT_FOUND;
+ Status = STATUS_OBJECT_NAME_NOT_FOUND;
+ hKey = NULL;
+ 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;
+ hKey = NULL;
+ goto openkey_cleanup;
}
- Status = ObCreateHandle(PsGetCurrentProcess(),
+ Status = ObpCreateHandle(PsGetCurrentProcess(),
Object,
DesiredAccess,
TRUE,
- KeyHandle);
- ObDereferenceObject(Object);
+ &hKey);
if (!NT_SUCCESS(Status))
+ hKey = NULL;
+
+openkey_cleanup:
+
+ 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);
}
- return(STATUS_SUCCESS);
+ _SEH_TRY
+ {
+ *KeyHandle = hKey;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ return Status;
}
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;
}
+ 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(&KeyObject->RegistryHive->HiveResource, TRUE);
+ ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
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_TOO_SMALL;
}
BasicInformation->TitleIndex = 0;
BasicInformation->NameLength = KeyObject->Name.Length;
+ if (Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]) <
+ NameSize)
+ {
+ NameSize = Length - FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+
RtlCopyMemory(BasicInformation->Name,
KeyObject->Name.Buffer,
- KeyObject->Name.Length);
+ 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_TOO_SMALL;
NodeInformation->ClassLength = KeyCell->ClassSize;
NodeInformation->NameLength = KeyObject->Name.Length;
+ if (Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]) < NameSize)
+ {
+ NameSize = Length - FIELD_OFFSET(KEY_NODE_INFORMATION, Name[0]);
+ ClassSize = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ CHECKPOINT;
+ }
+ 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;
+ }
+
RtlCopyMemory(NodeInformation->Name,
KeyObject->Name.Buffer,
- KeyObject->Name.Length);
+ NameSize);
- if (KeyCell->ClassSize != 0)
+ if (ClassSize != 0)
{
ClassCell = CmiGetCell (KeyObject->RegistryHive,
KeyCell->ClassNameOffset,
NULL);
RtlCopyMemory (NodeInformation->Name + KeyObject->Name.Length,
ClassCell->Data,
- KeyCell->ClassSize);
+ 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_TOO_SMALL;
}
CmiGetMaxValueNameLength(RegistryHive, KeyCell);
FullInformation->MaxValueDataLen =
CmiGetMaxValueDataLength(RegistryHive, KeyCell);
- if (KeyCell->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)
{
ClassCell = CmiGetCell (KeyObject->RegistryHive,
KeyCell->ClassNameOffset,
NULL);
RtlCopyMemory (FullInformation->Class,
- ClassCell->Data,
- KeyCell->ClassSize);
+ ClassCell->Data, ClassSize);
}
}
break;
+ 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;
+
+ PAGED_CODE();
- DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
+ 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))
{
- DPRINT1("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 */
KeEnterCriticalRegion();
- ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
{
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_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
{
RtlCopyMemory(ValueBasicInformation->Name,
ValueCell->Name,
- ValueCell->NameSize * sizeof(WCHAR));
+ NameSize);
}
}
break;
case KeyValuePartialInformation:
- *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
- + (ValueCell->DataSize & REG_DATA_SIZE_MASK);
- 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_TOO_SMALL;
}
KeyValueInformation;
ValuePartialInformation->TitleIndex = 0;
ValuePartialInformation->Type = ValueCell->DataType;
- ValuePartialInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
+ 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,
- ValueCell->DataSize & REG_DATA_SIZE_MASK);
+ DataSize);
}
else
{
RtlCopyMemory(ValuePartialInformation->Data,
&ValueCell->DataOffset,
- ValueCell->DataSize & REG_DATA_SIZE_MASK);
+ DataSize);
}
}
break;
{
NameSize *= sizeof(WCHAR);
}
- *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
- NameSize + (ValueCell->DataSize & REG_DATA_SIZE_MASK);
- 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_TOO_SMALL;
}
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,
- 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 =
- ROUND_UP(ValueFullInformation->DataOffset, sizeof(PVOID));
- ValueFullInformation->DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
{
DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
RtlCopyMemory((PCHAR) ValueFullInformation
+ ValueFullInformation->DataOffset,
DataCell->Data,
- ValueCell->DataSize & REG_DATA_SIZE_MASK);
+ DataSize);
}
else
{
RtlCopyMemory((PCHAR) ValueFullInformation
+ ValueFullInformation->DataOffset,
&ValueCell->DataOffset,
- ValueCell->DataSize & REG_DATA_SIZE_MASK);
+ DataSize);
}
}
break;
}
ByeBye:;
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
+
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
return Status;
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 */
KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
{
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;
}
DPRINT("ValueCell %p\n", ValueCell);
DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
+ 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 data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */
DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
- if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
- (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
+ if (DataCell)
{
- DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
}
RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize);
ValueCell->DataSize = DataSize | REG_DATA_IN_OFFSET;
ValueCell->DataType = Type;
- RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize);
CmiMarkBlockDirty(RegistryHive, ValueCellOffset);
}
- else if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET) &&
- (DataSize <= (ValueCell->DataSize & REG_DATA_SIZE_MASK)))
- {
- /* If new data size is <= current then overwrite current data */
- DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset,&pBin);
- RtlZeroMemory(DataCell->Data, ValueCell->DataSize);
- RtlCopyMemory(DataCell->Data, Data, DataSize);
- ValueCell->DataSize = DataSize;
- ValueCell->DataType = Type;
- }
- 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 & REG_DATA_IN_OFFSET) &&
- (ValueCell->DataSize & REG_DATA_SIZE_MASK) != 0)
- {
- DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
- CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
- ValueCell->DataSize = 0;
- ValueCell->DataType = 0;
- ValueCell->DataOffset = (BLOCK_OFFSET)-1;
- }
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
+ ObDereferenceObject(KeyObject);
- Status = CmiAllocateCell (RegistryHive,
- sizeof(CELL_HEADER) + DataSize,
- (PVOID *)&NewDataCell,
- &NewOffset);
- if (!NT_SUCCESS(Status))
- {
- DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
+ return Status;
+ }
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
- KeLeaveCriticalRegion();
- ObDereferenceObject(KeyObject);
+ if (DataCell)
+ {
+ CmiDestroyCell(RegistryHive, DataCell, ValueCell->DataOffset);
+ }
- return Status;
- }
+ ValueCell->DataOffset = NewOffset;
+ DataCell = NewDataCell;
+ }
- RtlCopyMemory(&NewDataCell->Data[0], Data, 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);
}
KeyCell->Flags |= REG_KEY_LINK_CELL;
}
- NtQuerySystemTime (&KeyCell->LastWriteTime);
+ KeQuerySystemTime (&KeyCell->LastWriteTime);
CmiMarkBlockDirty (RegistryHive, KeyObject->KeyCellOffset);
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
ObDereferenceObject(KeyObject);
CmiSyncHives();
{
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 */
KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
KeyObject->KeyCellOffset,
ValueName);
- NtQuerySystemTime (&KeyObject->KeyCell->LastWriteTime);
+ KeQuerySystemTime (&KeyObject->KeyCell->LastWriteTime);
CmiMarkBlockDirty (KeyObject->RegistryHive, KeyObject->KeyCellOffset);
/* Release hive lock */
- ExReleaseResourceLite (&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
+ ReleaseCapturedUnicodeString(&CapturedValueName,
+ PreviousMode);
+
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ PostOperationInfo.Status = Status;
+
+ CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey, &PostOperationInfo);
+
ObDereferenceObject (KeyObject);
CmiSyncHives ();
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 */
KeEnterCriticalRegion();
- ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
+ ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
VERIFY_KEY_OBJECT(KeyObject);
if (BufferLength + (ValueCell->DataSize & REG_DATA_SIZE_MASK) <= *Length)
{
- DataPtr = (PUCHAR)ROUND_UP((ULONG)DataPtr, sizeof(PVOID));
+ DataPtr = (PUCHAR)ROUND_UP((ULONG_PTR)DataPtr, sizeof(PVOID));
ValueList[i].Type = ValueCell->DataType;
ValueList[i].DataLength = ValueCell->DataSize & REG_DATA_SIZE_MASK;
- ValueList[i].DataOffset = (ULONG) DataPtr - (ULONG) Buffer;
+ ValueList[i].DataOffset = (ULONG_PTR)DataPtr - (ULONG_PTR)Buffer;
if (!(ValueCell->DataSize & REG_DATA_IN_OFFSET))
{
*ReturnLength = BufferLength;
/* Release hive lock */
- ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
+ ExReleaseResourceLite(&CmiRegistryLock);
KeLeaveCriticalRegion();
+ PostOperationInfo.Status = Status;
+ CmiCallRegisteredCallbacks(RegNtPostQueryMultipleValueKey, &PostOperationInfo);
+
ObDereferenceObject(KeyObject);
DPRINT("Return Status 0x%X\n", Status);
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 */
KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite (&KeyObject->RegistryHive->HiveResource,
- TRUE);
+ 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);
{
PKEY_OBJECT KeyObject;
NTSTATUS Status;
+ REG_SET_INFORMATION_KEY_INFORMATION SetInformationKeyInfo;
+ REG_POST_OPERATION_INFORMATION PostOperationInfo;
- if (KeyInformationClass != KeyLastWriteTimeInformation)
- return STATUS_INVALID_INFO_CLASS;
-
- if (KeyInformationLength != sizeof (KEY_LAST_WRITE_TIME_INFORMATION))
- return STATUS_INFO_LENGTH_MISMATCH;
+ PAGED_CODE();
/* Verify that the handle is valid and is a registry key */
Status = ObReferenceObjectByHandle (KeyHandle,
KEY_SET_VALUE,
CmiKeyType,
- UserMode,
+ ExGetPreviousMode(),
(PVOID *)&KeyObject,
NULL);
if (!NT_SUCCESS (Status))
return Status;
}
- /* Acquire hive lock */
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite (&KeyObject->RegistryHive->HiveResource, TRUE);
+ PostOperationInfo.Object = (PVOID)KeyObject;
+ SetInformationKeyInfo.Object = (PVOID)KeyObject;
+ SetInformationKeyInfo.KeySetInformationClass = KeyInformationClass;
+ SetInformationKeyInfo.KeySetInformation = KeyInformation;
+ SetInformationKeyInfo.KeySetInformationLength = KeyInformationLength;
- VERIFY_KEY_OBJECT(KeyObject);
+ Status = CmiCallRegisteredCallbacks(RegNtSetInformationKey, &SetInformationKeyInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject (KeyObject);
+ return Status;
+ }
- KeyObject->KeyCell->LastWriteTime.QuadPart =
- ((PKEY_LAST_WRITE_TIME_INFORMATION)KeyInformation)->LastWriteTime.QuadPart;
+ if (KeyInformationClass != KeyWriteTimeInformation)
+ {
+ Status = STATUS_INVALID_INFO_CLASS;
+ }
- CmiMarkBlockDirty (KeyObject->RegistryHive,
- KeyObject->KeyCellOffset);
+ else if (KeyInformationLength != sizeof (KEY_WRITE_TIME_INFORMATION))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else
+ {
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
- /* Release hive lock */
- ExReleaseResourceLite (&KeyObject->RegistryHive->HiveResource);
- KeLeaveCriticalRegion();
+ 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);
- CmiSyncHives ();
+ if (NT_SUCCESS(Status))
+ {
+ CmiSyncHives ();
+ }
DPRINT ("NtSaveKey() done\n");
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 */
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite (&CmiHiveListLock,
- TRUE);
-
#if 0
/* Flush hive */
if (!IsNoFileHive (RegistryHive))
CmiFlushRegistryHive (RegistryHive);
#endif
- /* Release hive list lock */
- ExReleaseResourceLite (&CmiHiveListLock);
- KeLeaveCriticalRegion();
-
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);