-/*
- * 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.
*/
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
#include "cm.h"
-extern POBJECT_TYPE CmiKeyType;
-extern KSPIN_LOCK CmiKeyListLock;
+extern LIST_ENTRY CmiKeyObjectListHead;
+extern ULONG CmiTimer;
+
+static NTSTATUS
+CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
+ PKEY_CELL KeyCell,
+ PUNICODE_STRING TargetPath);
-NTSTATUS CmiObjectParse(PVOID ParsedObject,
- PVOID *NextObject,
- PUNICODE_STRING FullPath,
- PWSTR *Path,
- POBJECT_TYPE ObjectType,
- ULONG Attributes)
+/* FUNCTONS *****************************************************************/
+
+NTSTATUS STDCALL
+CmiObjectParse(PVOID ParsedObject,
+ PVOID *NextObject,
+ PUNICODE_STRING FullPath,
+ PWSTR *Path,
+ ULONG Attributes)
{
- CHAR cPath[MAX_PATH];
- PWSTR end;
- PKEY_OBJECT FoundObject;
- PKEY_OBJECT ParsedKey=ParsedObject;
- PKEY_BLOCK SubKeyBlock;
- BLOCK_OFFSET BlockOffset;
- NTSTATUS Status;
- *NextObject = NULL;
- if ((*Path) == NULL)
- {
- return STATUS_UNSUCCESSFUL;
- }
-
- if((*Path[0])=='\\')
- {
- end = wcschr((*Path)+1, '\\');
- if (end != NULL)
- *end = 0;
- wcstombs(cPath,(*Path)+1,wcslen((*Path)+1));
- cPath[wcslen( (*Path)+1)]=0;
- }
- else
- {
- end = wcschr((*Path), '\\');
- if (end != NULL)
- *end = 0;
- wcstombs(cPath,(*Path),wcslen((*Path)));
- cPath[wcslen( (*Path))]=0;
- }
-
- FoundObject = CmiScanKeyList(ParsedKey,cPath,Attributes);
- if (FoundObject == NULL)
- {
- Status = CmiScanForSubKey(ParsedKey->RegistryFile,
- ParsedKey->KeyBlock,
- &SubKeyBlock,
- &BlockOffset,
- cPath,
- 0,
- Attributes);
- if(!NT_SUCCESS(Status) || SubKeyBlock == NULL)
- {
- if (end != NULL)
- {
- *end = '\\';
- }
- return STATUS_UNSUCCESSFUL;
- }
- /* Create new key object and put into linked list */
-DPRINT("CmiObjectParse %s\n",cPath);
- Status = ObCreateObject(NULL,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- CmiKeyType,
- (PVOID*)&FoundObject);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- FoundObject->Flags = 0;
- FoundObject->Name = SubKeyBlock->Name;
- FoundObject->NameSize = SubKeyBlock->NameSize;
- FoundObject->KeyBlock = SubKeyBlock;
- FoundObject->BlockOffset = BlockOffset;
- FoundObject->RegistryFile = ParsedKey->RegistryFile;
- CmiAddKeyToList(ParsedKey,FoundObject);
- }
- else
- ObReferenceObjectByPointer(FoundObject,
- STANDARD_RIGHTS_REQUIRED,
+ BLOCK_OFFSET BlockOffset;
+ PKEY_OBJECT FoundObject;
+ PKEY_OBJECT ParsedKey;
+ PKEY_CELL SubKeyCell;
+ NTSTATUS Status;
+ PWSTR StartPtr;
+ PWSTR EndPtr;
+ ULONG Length;
+ UNICODE_STRING LinkPath;
+ UNICODE_STRING TargetPath;
+ UNICODE_STRING KeyName;
+
+ ParsedKey = ParsedObject;
+
+ VERIFY_KEY_OBJECT(ParsedKey);
+
+ *NextObject = NULL;
+
+ if ((*Path) == NULL)
+ {
+ DPRINT("*Path is NULL\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ DPRINT("Path '%S'\n", *Path);
+
+ /* Extract relevant path name */
+ StartPtr = *Path;
+ if (*StartPtr == L'\\')
+ StartPtr++;
+
+ EndPtr = wcschr(StartPtr, L'\\');
+ if (EndPtr != NULL)
+ Length = ((PCHAR)EndPtr - (PCHAR)StartPtr) / sizeof(WCHAR);
+ else
+ Length = wcslen(StartPtr);
+
+
+ KeyName.Length = Length * sizeof(WCHAR);
+ KeyName.MaximumLength = KeyName.Length + sizeof(WCHAR);
+ KeyName.Buffer = ExAllocatePool(NonPagedPool,
+ KeyName.MaximumLength);
+ RtlCopyMemory(KeyName.Buffer,
+ StartPtr,
+ KeyName.Length);
+ KeyName.Buffer[KeyName.Length / sizeof(WCHAR)] = 0;
+
+ /* Acquire hive lock */
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+
+
+ Status = CmiScanKeyList(ParsedKey,
+ &KeyName,
+ Attributes,
+ &FoundObject);
+ if (!NT_SUCCESS(Status))
+ {
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ RtlFreeUnicodeString(&KeyName);
+ return Status;
+ }
+ if (FoundObject == NULL)
+ {
+ Status = CmiScanForSubKey(ParsedKey->RegistryHive,
+ ParsedKey->KeyCell,
+ &SubKeyCell,
+ &BlockOffset,
+ &KeyName,
+ 0,
+ Attributes);
+ if (!NT_SUCCESS(Status) || (SubKeyCell == NULL))
+ {
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+ RtlFreeUnicodeString(&KeyName);
+ return(STATUS_UNSUCCESSFUL);
+ }
+
+ if ((SubKeyCell->Flags & REG_KEY_LINK_CELL) &&
+ !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL)))
+ {
+ RtlInitUnicodeString(&LinkPath, NULL);
+ Status = CmiGetLinkTarget(ParsedKey->RegistryHive,
+ SubKeyCell,
+ &LinkPath);
+ if (NT_SUCCESS(Status))
+ {
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ DPRINT("LinkPath '%wZ'\n", &LinkPath);
+
+ /* build new FullPath for reparsing */
+ TargetPath.MaximumLength = LinkPath.MaximumLength;
+ if (EndPtr != NULL)
+ {
+ TargetPath.MaximumLength += (wcslen(EndPtr) * sizeof(WCHAR));
+ }
+ TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
+ TargetPath.Buffer = ExAllocatePool(NonPagedPool,
+ TargetPath.MaximumLength);
+ wcscpy(TargetPath.Buffer, LinkPath.Buffer);
+ if (EndPtr != NULL)
+ {
+ wcscat(TargetPath.Buffer, EndPtr);
+ }
+
+ RtlFreeUnicodeString(FullPath);
+ RtlFreeUnicodeString(&LinkPath);
+ FullPath->Length = TargetPath.Length;
+ FullPath->MaximumLength = TargetPath.MaximumLength;
+ FullPath->Buffer = TargetPath.Buffer;
+
+ DPRINT("FullPath '%wZ'\n", FullPath);
+
+ /* reinitialize Path for reparsing */
+ *Path = FullPath->Buffer;
+
+ *NextObject = NULL;
+
+ RtlFreeUnicodeString(&KeyName);
+ return(STATUS_REPARSE);
+ }
+ }
+
+ /* Create new key object and put into linked list */
+ DPRINT("CmiObjectParse: %S\n", *Path);
+ Status = ObCreateObject(KernelMode,
+ CmiKeyType,
NULL,
- UserMode);
-DPRINT("CmiObjectParse %s\n",FoundObject->Name);
- if (end != NULL)
- {
- *end = '\\';
- *Path = end;
- }
- else
- {
- *Path = 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);
- *NextObject = FoundObject;
+ /* Add the keep-alive reference */
+ ObReferenceObject(FoundObject);
- return STATUS_SUCCESS;
-}
+ FoundObject->Flags = 0;
+ FoundObject->KeyCell = SubKeyCell;
+ FoundObject->KeyCellOffset = BlockOffset;
+ FoundObject->RegistryHive = ParsedKey->RegistryHive;
+ InsertTailList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
+ RtlpCreateUnicodeString(&FoundObject->Name,
+ KeyName.Buffer, NonPagedPool);
+ CmiAddKeyToList(ParsedKey, FoundObject);
+ DPRINT("Created object 0x%p\n", FoundObject);
+ }
+ else
+ {
+ if ((FoundObject->KeyCell->Flags & REG_KEY_LINK_CELL) &&
+ !((Attributes & OBJ_OPENLINK) && (EndPtr == NULL)))
+ {
+ DPRINT("Found link\n");
-NTSTATUS CmiObjectCreate(PVOID ObjectBody,
- PVOID Parent,
- PWSTR RemainingPath,
- struct _OBJECT_ATTRIBUTES* ObjectAttributes)
-{
- PKEY_OBJECT pKey=ObjectBody;
- pKey->ParentKey = Parent;
- if (RemainingPath)
- {
- if(RemainingPath[0]== L'\\')
- {
- pKey->Name = (PCHAR) (&RemainingPath[1]);
- pKey->NameSize = wcslen(RemainingPath)-1;
- }
- else
- {
- pKey->Name = (PCHAR) RemainingPath;
- pKey->NameSize = wcslen(RemainingPath);
- }
- }
- else
- pKey->NameSize = 0;
+ RtlInitUnicodeString(&LinkPath, NULL);
+ Status = CmiGetLinkTarget(FoundObject->RegistryHive,
+ FoundObject->KeyCell,
+ &LinkPath);
+ if (NT_SUCCESS(Status))
+ {
+ DPRINT("LinkPath '%wZ'\n", &LinkPath);
+
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ ObDereferenceObject(FoundObject);
+
+ /* build new FullPath for reparsing */
+ TargetPath.MaximumLength = LinkPath.MaximumLength;
+ if (EndPtr != NULL)
+ {
+ TargetPath.MaximumLength += (wcslen(EndPtr) * sizeof(WCHAR));
+ }
+ TargetPath.Length = TargetPath.MaximumLength - sizeof(WCHAR);
+ TargetPath.Buffer = ExAllocatePool(NonPagedPool,
+ TargetPath.MaximumLength);
+ wcscpy(TargetPath.Buffer, LinkPath.Buffer);
+ if (EndPtr != NULL)
+ {
+ wcscat(TargetPath.Buffer, EndPtr);
+ }
+
+ RtlFreeUnicodeString(FullPath);
+ RtlFreeUnicodeString(&LinkPath);
+ FullPath->Length = TargetPath.Length;
+ FullPath->MaximumLength = TargetPath.MaximumLength;
+ FullPath->Buffer = TargetPath.Buffer;
+
+ DPRINT("FullPath '%wZ'\n", FullPath);
+
+ /* reinitialize Path for reparsing */
+ *Path = FullPath->Buffer;
+
+ *NextObject = NULL;
+
+ RtlFreeUnicodeString(&KeyName);
+ return(STATUS_REPARSE);
+ }
+ }
+ }
- return STATUS_SUCCESS;
+ RemoveEntryList(&FoundObject->ListEntry);
+ InsertHeadList(&CmiKeyObjectListHead, &FoundObject->ListEntry);
+ FoundObject->TimeStamp = CmiTimer;
+
+ ExReleaseResourceLite(&CmiRegistryLock);
+ KeLeaveCriticalRegion();
+
+ DPRINT("CmiObjectParse: %s\n", FoundObject->Name);
+
+ *Path = EndPtr;
+
+ VERIFY_KEY_OBJECT(FoundObject);
+
+ *NextObject = FoundObject;
+
+ RtlFreeUnicodeString(&KeyName);
+
+ return(STATUS_SUCCESS);
}
-void
-CmiObjectDelete(PVOID DeletedObject)
+VOID STDCALL
+CmiObjectDelete(PVOID DeletedObject)
{
- PKEY_OBJECT KeyObject;
+ PKEY_OBJECT ParentKeyObject;
+ PKEY_OBJECT KeyObject;
+
+ DPRINT("Delete key object (%p)\n", DeletedObject);
-DPRINT("delete object key\n");
KeyObject = (PKEY_OBJECT) DeletedObject;
- if(!NT_SUCCESS(CmiRemoveKeyFromList(KeyObject)))
- {
- DPRINT1("Key not found in parent list ???\n");
- }
+ 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)
{
-DPRINT1("delete really key\n");
- CmiDestroyBlock(KeyObject->RegistryFile,
- KeyObject->KeyBlock,
- KeyObject->BlockOffset);
+ DPRINT("delete really key\n");
+
+ CmiRemoveSubKey(KeyObject->RegistryHive,
+ ParentKeyObject,
+ KeyObject);
+
+ KeQuerySystemTime (&ParentKeyObject->KeyCell->LastWriteTime);
+ CmiMarkBlockDirty (ParentKeyObject->RegistryHive,
+ ParentKeyObject->KeyCellOffset);
+
+ if (!IsNoFileHive (KeyObject->RegistryHive) ||
+ !IsNoFileHive (ParentKeyObject->RegistryHive))
+ {
+ 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;
+}
+
+
+NTSTATUS STDCALL
+CmiObjectSecurity(PVOID ObjectBody,
+ SECURITY_OPERATION_CODE OperationCode,
+ SECURITY_INFORMATION SecurityInformation,
+ PSECURITY_DESCRIPTOR SecurityDescriptor,
+ PULONG BufferLength,
+ PSECURITY_DESCRIPTOR *OldSecurityDescriptor,
+ POOL_TYPE PoolType,
+ PGENERIC_MAPPING GenericMapping)
+{
+ DPRINT("CmiObjectSecurity() called\n");
+
+ 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;
+}
+
+
+NTSTATUS STDCALL
+CmiObjectQueryName (PVOID ObjectBody,
+ POBJECT_NAME_INFORMATION ObjectNameInfo,
+ ULONG Length,
+ PULONG ReturnLength)
+{
+ PKEY_OBJECT KeyObject;
+ NTSTATUS Status;
+
+ DPRINT ("CmiObjectQueryName() called\n");
+
+ KeyObject = (PKEY_OBJECT)ObjectBody;
+
+ if (KeyObject->ParentKey != KeyObject)
+ {
+ Status = ObQueryNameString (KeyObject->ParentKey,
+ ObjectNameInfo,
+ Length,
+ ReturnLength);
}
else
{
- CmiReleaseBlock(KeyObject->RegistryFile,
- KeyObject->KeyBlock);
+ /* KeyObject is the root key */
+ Status = ObQueryNameString (HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(KeyObject))->Directory,
+ ObjectNameInfo,
+ Length,
+ ReturnLength);
+ }
+
+ if (!NT_SUCCESS(Status) && Status != STATUS_INFO_LENGTH_MISMATCH)
+ {
+ return Status;
}
+ (*ReturnLength) += sizeof(WCHAR) + KeyObject->Name.Length;
+
+ 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"\\");
+ if (!NT_SUCCESS (Status))
+ return Status;
+
+ Status = RtlAppendUnicodeStringToString (&ObjectNameInfo->Name,
+ &KeyObject->Name);
+ if (NT_SUCCESS (Status))
+ {
+ DPRINT ("Total path: %wZ\n", &ObjectNameInfo->Name);
+ }
+
+ return Status;
}
-void
-CmiAddKeyToList(PKEY_OBJECT ParentKey,PKEY_OBJECT NewKey)
+
+VOID
+CmiAddKeyToList(PKEY_OBJECT ParentKey,
+ PKEY_OBJECT NewKey)
{
- KIRQL OldIrql;
-
- KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
+
+ DPRINT("ParentKey %.08x\n", ParentKey);
+
+
if (ParentKey->SizeOfSubKeys <= ParentKey->NumberOfSubKeys)
- {
- PKEY_OBJECT *tmpSubKeys = ExAllocatePool(PagedPool
- , (ParentKey->NumberOfSubKeys+1) * sizeof(DWORD));
- if(ParentKey->NumberOfSubKeys > 0)
- memcpy(tmpSubKeys,ParentKey->SubKeys
- ,ParentKey->NumberOfSubKeys*sizeof(DWORD));
- if(ParentKey->SubKeys) ExFreePool(ParentKey->SubKeys);
- ParentKey->SubKeys=tmpSubKeys;
- ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys+1;
- }
- /* FIXME : please maintain the list in alphabetic order */
+ {
+ PKEY_OBJECT *tmpSubKeys = ExAllocatePool(NonPagedPool,
+ (ParentKey->NumberOfSubKeys + 1) * sizeof(ULONG));
+
+ if (ParentKey->NumberOfSubKeys > 0)
+ {
+ RtlCopyMemory (tmpSubKeys,
+ ParentKey->SubKeys,
+ ParentKey->NumberOfSubKeys * sizeof(ULONG));
+ }
+
+ if (ParentKey->SubKeys)
+ ExFreePool(ParentKey->SubKeys);
+
+ ParentKey->SubKeys = tmpSubKeys;
+ ParentKey->SizeOfSubKeys = ParentKey->NumberOfSubKeys + 1;
+ }
+
+ /* FIXME: Please maintain the list in alphabetic order */
/* to allow a dichotomic search */
ParentKey->SubKeys[ParentKey->NumberOfSubKeys++] = NewKey;
+
+ DPRINT("Reference parent key: 0x%p\n", ParentKey);
+
ObReferenceObjectByPointer(ParentKey,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- UserMode);
+ STANDARD_RIGHTS_REQUIRED,
+ NULL,
+ UserMode);
NewKey->ParentKey = ParentKey;
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
}
+
NTSTATUS
-CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
+CmiRemoveKeyFromList(PKEY_OBJECT KeyToRemove)
{
- KIRQL OldIrql;
- PKEY_OBJECT ParentKey;
+ PKEY_OBJECT ParentKey;
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++)
- {
- if(ParentKey->SubKeys[Index] == KeyToRemove)
- {
- if (Index < ParentKey->NumberOfSubKeys-1)
- memmove(&ParentKey->SubKeys[Index]
- ,&ParentKey->SubKeys[Index+1]
- ,(ParentKey->NumberOfSubKeys-Index-1)*sizeof(PKEY_OBJECT));
- ParentKey->NumberOfSubKeys--;
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- ObDereferenceObject(ParentKey);
- return STATUS_SUCCESS;
+ ParentKey = KeyToRemove->ParentKey;
+ /* FIXME: If list maintained in alphabetic order, use dichotomic search */
+ for (Index = 0; Index < ParentKey->NumberOfSubKeys; Index++)
+ {
+ if (ParentKey->SubKeys[Index] == KeyToRemove)
+ {
+ if (Index < ParentKey->NumberOfSubKeys-1)
+ RtlMoveMemory(&ParentKey->SubKeys[Index],
+ &ParentKey->SubKeys[Index + 1],
+ (ParentKey->NumberOfSubKeys - Index - 1) * sizeof(PKEY_OBJECT));
+ ParentKey->NumberOfSubKeys--;
+
+ 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,
- PCHAR KeyName,
- ULONG Attributes)
+ PUNICODE_STRING KeyName,
+ ULONG Attributes,
+ PKEY_OBJECT* ReturnedObject)
{
- KIRQL OldIrql;
- PKEY_OBJECT CurKey;
- DWORD Index;
- WORD NameSize;
- NameSize=strlen(KeyName);
- KeAcquireSpinLock(&CmiKeyListLock, &OldIrql);
- /* FIXME : if list maintained in alphabetic order, use dichotomic search */
+ PKEY_OBJECT CurKey;
+ ULONG Index;
+
+ DPRINT("Scanning key list for: %wZ (Parent: %wZ)\n",
+ KeyName, &Parent->Name);
+
+ /* FIXME: if list maintained in alphabetic order, use dichotomic search */
for (Index=0; Index < Parent->NumberOfSubKeys; Index++)
+ {
+ CurKey = Parent->SubKeys[Index];
+ if (Attributes & OBJ_CASE_INSENSITIVE)
+ {
+ if ((KeyName->Length == CurKey->Name.Length)
+ && (_wcsicmp(KeyName->Buffer, CurKey->Name.Buffer) == 0))
+ {
+ break;
+ }
+ }
+ else
+ {
+ if ((KeyName->Length == CurKey->Name.Length)
+ && (wcscmp(KeyName->Buffer, CurKey->Name.Buffer) == 0))
+ {
+ break;
+ }
+ }
+ }
+
+ if (Index < Parent->NumberOfSubKeys)
+ {
+ if (CurKey->Flags & KO_MARKED_FOR_DELETE)
+ {
+ *ReturnedObject = NULL;
+ return STATUS_UNSUCCESSFUL;
+ }
+ ObReferenceObject(CurKey);
+ *ReturnedObject = CurKey;
+ }
+ else
{
- CurKey=Parent->SubKeys[Index];
- if (Attributes & OBJ_CASE_INSENSITIVE)
+ *ReturnedObject = NULL;
+ }
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+CmiGetLinkTarget(PREGISTRY_HIVE RegistryHive,
+ PKEY_CELL KeyCell,
+ PUNICODE_STRING TargetPath)
+{
+ UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"SymbolicLinkValue");
+ PVALUE_CELL ValueCell;
+ PDATA_CELL DataCell;
+ NTSTATUS Status;
+
+ DPRINT("CmiGetLinkTarget() called\n");
+
+ /* Get Value block of interest */
+ Status = CmiScanKeyForValue(RegistryHive,
+ KeyCell,
+ &LinkName,
+ &ValueCell,
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- if( NameSize == CurKey->NameSize
- && !_strnicmp(KeyName,CurKey->Name,NameSize))
- {
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- return CurKey;
- }
+ DPRINT1("CmiScanKeyForValue() failed (Status %lx)\n", Status);
+ return(Status);
}
- else
+
+ if (ValueCell->DataType != REG_LINK)
{
- if( NameSize == CurKey->NameSize
- && !strncmp(KeyName,CurKey->Name,NameSize))
- {
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
- return CurKey;
- }
+ DPRINT1("Type != REG_LINK\n!");
+ return(STATUS_UNSUCCESSFUL);
}
- }
- KeReleaseSpinLock(&CmiKeyListLock, OldIrql);
-
- return NULL;
+
+ if (TargetPath->Buffer == NULL && TargetPath->MaximumLength == 0)
+ {
+ TargetPath->Length = 0;
+ TargetPath->MaximumLength = ValueCell->DataSize + sizeof(WCHAR);
+ TargetPath->Buffer = ExAllocatePool(NonPagedPool,
+ TargetPath->MaximumLength);
+ }
+
+ TargetPath->Length = min(TargetPath->MaximumLength - sizeof(WCHAR),
+ (ULONG) ValueCell->DataSize);
+
+ if (ValueCell->DataSize > 0)
+ {
+ DataCell = CmiGetCell (RegistryHive, ValueCell->DataOffset, NULL);
+ RtlCopyMemory(TargetPath->Buffer,
+ DataCell->Data,
+ TargetPath->Length);
+ TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
+ }
+ else
+ {
+ RtlCopyMemory(TargetPath->Buffer,
+ &ValueCell->DataOffset,
+ TargetPath->Length);
+ TargetPath->Buffer[TargetPath->Length / sizeof(WCHAR)] = 0;
+ }
+
+ DPRINT("TargetPath '%wZ'\n", TargetPath);
+
+ return(STATUS_SUCCESS);
}
+
+/* EOF */