-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/cm/regobj.c
- * PURPOSE: Registry object manipulation routines.
- * UPDATE HISTORY:
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/cm/regobj.c
+ * PURPOSE: Registry object manipulation routines.
+ *
+ * PROGRAMMERS: No programmer listed.
*/
-#define NTOS_MODE_KERNEL
-#include <ntos.h>
-#include <roscfg.h>
-#include <internal/ob.h>
-#include <limits.h>
-#include <string.h>
-#include <internal/registry.h>
-#include <ntos/minmax.h>
-
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
#include "cm.h"
+extern LIST_ENTRY CmiKeyObjectListHead;
+extern ULONG CmiTimer;
static NTSTATUS
CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
KeyName.Length);
KeyName.Buffer[KeyName.Length / sizeof(WCHAR)] = 0;
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
- FoundObject = CmiScanKeyList(ParsedKey,
- &KeyName,
- Attributes);
+ Status = CmiScanKeyList(ParsedKey,
+ &KeyName,
+ Attributes,
+ &FoundObject);
+ if (!NT_SUCCESS(Status))
+ {
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ RtlFreeUnicodeString(&KeyName);
+ return Status;
+ }
if (FoundObject == NULL)
{
Status = CmiScanForSubKey(ParsedKey->RegistryHive,
Attributes);
if (!NT_SUCCESS(Status) || (SubKeyCell == NULL))
{
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
RtlFreeUnicodeString(&KeyName);
return(STATUS_UNSUCCESSFUL);
}
&LinkPath);
if (NT_SUCCESS(Status))
{
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
DPRINT("LinkPath '%wZ'\n", &LinkPath);
/* build new FullPath for reparsing */
}
/* Create new key object and put into linked list */
- DPRINT("CmiObjectParse: %s\n", cPath);
- Status = ObRosCreateObject(NULL,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
+ DPRINT("CmiObjectParse: %S\n", *Path);
+ Status = ObCreateObject(KernelMode,
CmiKeyType,
+ NULL,
+ KernelMode,
+ NULL,
+ sizeof(KEY_OBJECT),
+ 0,
+ 0,
(PVOID*)&FoundObject);
if (!NT_SUCCESS(Status))
{
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
RtlFreeUnicodeString(&KeyName);
return(Status);
}
+ DPRINT("Inserting Key into Object Tree\n");
+ Status = ObInsertObject((PVOID)FoundObject,
+ NULL,
+ KEY_ALL_ACCESS,
+ 0,
+ NULL,
+ NULL);
+ DPRINT("Status %x\n", Status);
+
+ /* Add the keep-alive reference */
+ ObReferenceObject(FoundObject);
FoundObject->Flags = 0;
FoundObject->KeyCell = SubKeyCell;
- FoundObject->BlockOffset = BlockOffset;
+ FoundObject->KeyCellOffset = BlockOffset;
FoundObject->RegistryHive = ParsedKey->RegistryHive;
- RtlCreateUnicodeString(&FoundObject->Name,
- KeyName.Buffer);
+ InsertTailList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
+ RtlpCreateUnicodeString(&FoundObject->Name,
+ KeyName.Buffer, NonPagedPool);
CmiAddKeyToList(ParsedKey, FoundObject);
- DPRINT("Created object 0x%x\n", FoundObject);
+ DPRINT("Created object 0x%p\n", FoundObject);
}
else
{
{
DPRINT("LinkPath '%wZ'\n", &LinkPath);
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ ObDereferenceObject(FoundObject);
+
/* build new FullPath for reparsing */
TargetPath.MaximumLength = LinkPath.MaximumLength;
if (EndPtr != NULL)
return(STATUS_REPARSE);
}
}
-
- ObReferenceObjectByPointer(FoundObject,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- UserMode);
}
+ RemoveEntryList(&FoundObject->ListEntry);
+ InsertHeadList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
+ FoundObject->TimeStamp = CmiTimer;
+
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
DPRINT("CmiObjectParse: %s\n", FoundObject->Name);
*Path = EndPtr;
return(STATUS_SUCCESS);
}
-
-NTSTATUS STDCALL
-CmiObjectCreate(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- POBJECT_ATTRIBUTES ObjectAttributes)
-{
- PKEY_OBJECT KeyObject = ObjectBody;
- PWSTR Start;
-
- KeyObject->ParentKey = Parent;
- if (RemainingPath)
- {
- Start = RemainingPath;
- if(*Start == L'\\')
- Start++;
- RtlCreateUnicodeString(&KeyObject->Name,
- Start);
- }
- else
- {
- RtlInitUnicodeString(&KeyObject->Name,
- NULL);
- }
-
- return STATUS_SUCCESS;
-}
-
-
VOID STDCALL
CmiObjectDelete(PVOID DeletedObject)
{
+ PKEY_OBJECT ParentKeyObject;
PKEY_OBJECT KeyObject;
DPRINT("Delete key object (%p)\n", DeletedObject);
KeyObject = (PKEY_OBJECT) DeletedObject;
+ ParentKeyObject = KeyObject->ParentKey;
+
+ ObReferenceObject (ParentKeyObject);
+
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
if (!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
{
DPRINT1("Key not found in parent list ???\n");
}
+ RemoveEntryList(&KeyObject->ListEntry);
RtlFreeUnicodeString(&KeyObject->Name);
if (KeyObject->Flags & KO_MARKED_FOR_DELETE)
DPRINT("delete really key\n");
CmiRemoveSubKey(KeyObject->RegistryHive,
- KeyObject->ParentKey,
+ ParentKeyObject,
KeyObject);
- if (!IsNoFileHive(KeyObject->RegistryHive))
+ KeQuerySystemTime (&ParentKeyObject->KeyCell->LastWriteTime);
+ CmiMarkBlockDirty (ParentKeyObject->RegistryHive,
+ ParentKeyObject->KeyCellOffset);
+
+ if (!IsNoFileHive (KeyObject->RegistryHive) ||
+ !IsNoFileHive (ParentKeyObject->RegistryHive))
{
- CmiSyncHives();
+ CmiSyncHives ();
}
}
+
+ ObDereferenceObject (ParentKeyObject);
+
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ if (KeyObject->NumberOfSubKeys)
+ {
+ KEBUGCHECK(REGISTRY_ERROR);
+ }
+
+ if (KeyObject->SizeOfSubKeys)
+ {
+ ExFreePool(KeyObject->SubKeys);
+ }
+}
+
+
+static NTSTATUS
+CmiQuerySecurityDescriptor(PKEY_OBJECT KeyObject,
+ SECURITY_INFORMATION SecurityInformation,
+ PISECURITY_DESCRIPTOR SecurityDescriptor,
+ PULONG BufferLength)
+{
+ ULONG_PTR Current;
+ ULONG SidSize;
+ ULONG SdSize;
+ NTSTATUS Status;
+
+ DPRINT("CmiQuerySecurityDescriptor() called\n");
+
+ /*
+ * FIXME:
+ * This is a big hack!!
+ * We need to retrieve the security descriptor from the keys security cell!
+ */
+
+ if (SecurityInformation == 0)
+ {
+ return STATUS_ACCESS_DENIED;
+ }
+
+ SidSize = RtlLengthSid(SeWorldSid);
+ SdSize = sizeof(SECURITY_DESCRIPTOR) + (2 * SidSize);
+
+ if (*BufferLength < SdSize)
+ {
+ *BufferLength = SdSize;
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ *BufferLength = SdSize;
+
+ Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ SecurityDescriptor->Control |= SE_SELF_RELATIVE;
+ Current = (ULONG_PTR)SecurityDescriptor + sizeof(SECURITY_DESCRIPTOR);
+
+ if (SecurityInformation & OWNER_SECURITY_INFORMATION)
+ {
+ RtlCopyMemory((PVOID)Current,
+ SeWorldSid,
+ SidSize);
+ SecurityDescriptor->Owner = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
+ Current += SidSize;
+ }
+
+ if (SecurityInformation & GROUP_SECURITY_INFORMATION)
+ {
+ RtlCopyMemory((PVOID)Current,
+ SeWorldSid,
+ SidSize);
+ SecurityDescriptor->Group = (PSID)((ULONG_PTR)Current - (ULONG_PTR)SecurityDescriptor);
+ Current += SidSize;
+ }
+
+ if (SecurityInformation & DACL_SECURITY_INFORMATION)
+ {
+ SecurityDescriptor->Control |= SE_DACL_PRESENT;
+ }
+
+ if (SecurityInformation & SACL_SECURITY_INFORMATION)
+ {
+ SecurityDescriptor->Control |= SE_SACL_PRESENT;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+CmiAssignSecurityDescriptor(PKEY_OBJECT KeyObject,
+ PSECURITY_DESCRIPTOR SecurityDescriptor)
+{
+#if 0
+ PREGISTRY_HIVE Hive;
+
+ DPRINT1("CmiAssignSecurityDescriptor() callled\n");
+
+ DPRINT1("KeyObject %p\n", KeyObject);
+ DPRINT1("KeyObject->RegistryHive %p\n", KeyObject->RegistryHive);
+
+ Hive = KeyObject->RegistryHive;
+ if (Hive == NULL)
+ {
+ DPRINT1("Create new root security cell\n");
+ return STATUS_SUCCESS;
+ }
+
+ if (Hive->RootSecurityCell == NULL)
+ {
+ DPRINT1("Create new root security cell\n");
+
+ }
+ else
+ {
+ DPRINT1("Search for security cell\n");
+
+ }
+#endif
+
+ return STATUS_SUCCESS;
}
SECURITY_OPERATION_CODE OperationCode,
SECURITY_INFORMATION SecurityInformation,
PSECURITY_DESCRIPTOR SecurityDescriptor,
- PULONG BufferLength)
+ PULONG BufferLength,
+ PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
+ POOL_TYPE PoolType,
+ PGENERIC_MAPPING GenericMapping)
{
- DPRINT1 ("CmiObjectSecurity() called\n");
+ DPRINT("CmiObjectSecurity() called\n");
- return STATUS_SUCCESS;
+ switch (OperationCode)
+ {
+ case SetSecurityDescriptor:
+ DPRINT("Set security descriptor\n");
+ return STATUS_SUCCESS;
+
+ case QuerySecurityDescriptor:
+ DPRINT("Query security descriptor\n");
+ return CmiQuerySecurityDescriptor((PKEY_OBJECT)ObjectBody,
+ SecurityInformation,
+ SecurityDescriptor,
+ BufferLength);
+
+ case DeleteSecurityDescriptor:
+ DPRINT("Delete security descriptor\n");
+ return STATUS_SUCCESS;
+
+ case AssignSecurityDescriptor:
+ DPRINT("Assign security descriptor\n");
+ return CmiAssignSecurityDescriptor((PKEY_OBJECT)ObjectBody,
+ SecurityDescriptor);
+ }
+
+ return STATUS_UNSUCCESSFUL;
}
ULONG Length,
PULONG ReturnLength)
{
- POBJECT_NAME_INFORMATION LocalInfo;
PKEY_OBJECT KeyObject;
- ULONG LocalReturnLength;
NTSTATUS Status;
DPRINT ("CmiObjectQueryName() called\n");
KeyObject = (PKEY_OBJECT)ObjectBody;
- LocalInfo = ExAllocatePool (NonPagedPool,
- sizeof(OBJECT_NAME_INFORMATION) +
- MAX_PATH * sizeof(WCHAR));
- if (LocalInfo == NULL)
- return STATUS_INSUFFICIENT_RESOURCES;
-
if (KeyObject->ParentKey != KeyObject)
{
Status = ObQueryNameString (KeyObject->ParentKey,
- LocalInfo,
- MAX_PATH * sizeof(WCHAR),
- &LocalReturnLength);
+ ObjectNameInfo,
+ Length,
+ ReturnLength);
}
else
{
/* KeyObject is the root key */
- Status = ObQueryNameString (BODY_TO_HEADER(KeyObject)->Parent,
- LocalInfo,
- MAX_PATH * sizeof(WCHAR),
- &LocalReturnLength);
+ Status = ObQueryNameString (HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(KeyObject))->Directory,
+ ObjectNameInfo,
+ Length,
+ ReturnLength);
}
- if (!NT_SUCCESS (Status))
+ if (!NT_SUCCESS(Status) && Status != STATUS_INFO_LENGTH_MISMATCH)
{
- ExFreePool (LocalInfo);
return Status;
}
- DPRINT ("Parent path: %wZ\n", &LocalInfo->Name);
+ (*ReturnLength) += sizeof(WCHAR) + KeyObject->Name.Length;
- Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
- &LocalInfo->Name);
- ExFreePool (LocalInfo);
- if (!NT_SUCCESS (Status))
- return Status;
+ if (Status == STATUS_INFO_LENGTH_MISMATCH || *ReturnLength > Length)
+ {
+ return STATUS_INFO_LENGTH_MISMATCH;
+ }
+
+ if (ObjectNameInfo->Name.Buffer == NULL)
+ {
+ ObjectNameInfo->Name.Buffer = (PWCHAR)(ObjectNameInfo + 1);
+ ObjectNameInfo->Name.Length = 0;
+ ObjectNameInfo->Name.MaximumLength = Length - sizeof(OBJECT_NAME_INFORMATION);
+ }
+
+
+ DPRINT ("Parent path: %wZ\n", ObjectNameInfo->Name);
Status = RtlAppendUnicodeToString (&ObjectNameInfo->Name,
L"\\");
CmiAddKeyToList(PKEY_OBJECT ParentKey,
PKEY_OBJECT NewKey)
{
- KIRQL OldIrql;
DPRINT("ParentKey %.08x\n", ParentKey);
- KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
{
/* to allow a dichotomic search */
ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
- DPRINT("Reference parent key: 0x%x\n", ParentKey);
+ DPRINT("Reference parent key: 0x%p\n", ParentKey);
ObReferenceObjectByPointer(ParentKey,
STANDARD_RIGHTS_REQUIRED,
NULL,
UserMode);
NewKey->ParentKey = ParentKey;
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
}
CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
{
PKEY_OBJECT ParentKey;
- KIRQL OldIrql;
DWORD Index;
ParentKey = KeyToRemove->ParentKey;
- KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
/* FIXME: If list maintained in alphabetic order, use dichotomic search */
for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++)
{
&ParentKey->SubKeys[Index + 1],
(ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT));
ParentKey->NumberOfSubKeys--;
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
DPRINT("Dereference parent key: 0x%x\n", ParentKey);
-
+
ObDereferenceObject(ParentKey);
return STATUS_SUCCESS;
}
}
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
return STATUS_UNSUCCESSFUL;
}
-PKEY_OBJECT
+NTSTATUS
CmiScanKeyList(PKEY_OBJECT Parent,
PUNICODE_STRING KeyName,
- ULONG Attributes)
+ ULONG Attributes,
+ PKEY_OBJECT* ReturnedObject)
{
PKEY_OBJECT CurKey;
- KIRQL OldIrql;
ULONG Index;
DPRINT("Scanning key list for: %wZ (Parent: %wZ)\n",
KeyName, &Parent->Name);
- KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
/* FIXME: if list maintained in alphabetic order, use dichotomic search */
for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
{
if ((KeyName->Length == CurKey->Name.Length)
&& (_wcsicmp(KeyName->Buffer, CurKey->Name.Buffer) == 0))
{
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- return CurKey;
+ break;
}
}
else
if ((KeyName->Length == CurKey->Name.Length)
&& (wcscmp(KeyName->Buffer, CurKey->Name.Buffer) == 0))
{
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- return CurKey;
+ break;
}
}
}
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- return NULL;
+ if (Index < Parent->NumberOfSubKeys)
+ {
+ if (CurKey->Flags & KO_MARKED_FOR_DELETE)
+ {
+ *ReturnedObject = NULL;
+ return STATUS_UNSUCCESSFUL;
+ }
+ ObReferenceObject(CurKey);
+ *ReturnedObject = CurKey;
+ }
+ else
+ {
+ *ReturnedObject = NULL;
+ }
+ return STATUS_SUCCESS;
}
PKEY_CELL KeyCell,
PUNICODE_STRING TargetPath)
{
- UNICODE_STRING LinkName = UNICODE_STRING_INITIALIZER(L"SymbolicLinkValue");
+ UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
PVALUE_CELL ValueCell;
PDATA_CELL DataCell;
NTSTATUS Status;
if (ValueCell->DataSize > 0)
{
- DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
+ DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
RtlCopyMemory(TargetPath->Buffer,
DataCell->Data,
TargetPath->Length);