mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 22:05:49 +00:00
- Last part of Alex's work on CM before he left ReactOS development. It was unfinished, so I had to insert a few hacks and comment out some code to make it working in trunk.
- Implement subkey creation code (for NtCreateKey and CmiConnectHive) based on the new Cm branch code (just as all the other routines were changed previously). - Also support creating hash leaves, used in XP hives, since all the new code was already able to read them. svn path=/trunk/; revision=28292
This commit is contained in:
parent
edaf84b215
commit
8dae7ddffe
5 changed files with 766 additions and 79 deletions
|
@ -294,6 +294,21 @@ CmiConnectHive(POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|||
NTSTATUS
|
||||
CmiInitHives(BOOLEAN SetupBoot);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpDoCreate(
|
||||
IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Cell,
|
||||
IN PACCESS_STATE AccessState,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN PUNICODE_STRING Class,
|
||||
IN ULONG CreateOptions,
|
||||
IN PKEY_OBJECT Parent,
|
||||
IN PVOID OriginatingHive OPTIONAL,
|
||||
OUT PVOID *Object
|
||||
);
|
||||
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpFindValueByName(
|
||||
|
|
|
@ -138,7 +138,6 @@ NtCreateKey(OUT PHANDLE KeyHandle,
|
|||
OUT PULONG Disposition)
|
||||
{
|
||||
UNICODE_STRING RemainingPath = {0};
|
||||
BOOLEAN FreeRemainingPath = TRUE;
|
||||
ULONG LocalDisposition;
|
||||
PKEY_OBJECT KeyObject;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
@ -303,53 +302,27 @@ NtCreateKey(OUT PHANDLE KeyHandle,
|
|||
|
||||
DPRINT("RemainingPath %S ParentObject 0x%p\n", RemainingPath.Buffer, Object);
|
||||
|
||||
Status = ObCreateObject(PreviousMode,
|
||||
CmpKeyObjectType,
|
||||
NULL,
|
||||
PreviousMode,
|
||||
NULL,
|
||||
sizeof(KEY_OBJECT),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&KeyObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("ObCreateObject() failed!\n");
|
||||
PostCreateKeyInfo.Object = NULL;
|
||||
PostCreateKeyInfo.Status = Status;
|
||||
CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
|
||||
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
KeyObject->ParentKey = Object;
|
||||
KeyObject->RegistryHive = KeyObject->ParentKey->RegistryHive;
|
||||
KeyObject->Flags = 0;
|
||||
KeyObject->SubKeyCounts = 0;
|
||||
KeyObject->SizeOfSubKeys = 0;
|
||||
KeyObject->SubKeys = NULL;
|
||||
|
||||
/* Acquire hive lock */
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE);
|
||||
|
||||
InsertTailList(&CmiKeyObjectListHead, &KeyObject->ListEntry);
|
||||
|
||||
/* add key to subkeys of parent if needed */
|
||||
Status = CmiAddSubKey(KeyObject->RegistryHive,
|
||||
KeyObject->ParentKey,
|
||||
KeyObject,
|
||||
&RemainingPath,
|
||||
TitleIndex,
|
||||
&CapturedClass,
|
||||
CreateOptions);
|
||||
/* Create the key */
|
||||
Status = CmpDoCreate(&((PKEY_OBJECT)Object)->RegistryHive->Hive,
|
||||
((PKEY_OBJECT)Object)->KeyCellOffset,
|
||||
NULL,
|
||||
&RemainingPath,
|
||||
KernelMode,
|
||||
Class,
|
||||
CreateOptions,
|
||||
(PKEY_OBJECT)Object,
|
||||
NULL,
|
||||
(PVOID*)&KeyObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CmiAddSubKey() failed (Status %lx)\n", Status);
|
||||
/* Release hive lock */
|
||||
ExReleaseResourceLite(&CmpRegistryLock);
|
||||
KeLeaveCriticalRegion();
|
||||
ObDereferenceObject(KeyObject);
|
||||
|
||||
PostCreateKeyInfo.Object = NULL;
|
||||
PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
|
||||
|
@ -359,15 +332,8 @@ NtCreateKey(OUT PHANDLE KeyHandle,
|
|||
goto Cleanup;
|
||||
}
|
||||
|
||||
if (Start == RemainingPath.Buffer)
|
||||
{
|
||||
KeyObject->Name = RemainingPath;
|
||||
FreeRemainingPath = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
RtlCreateUnicodeString(&KeyObject->Name, Start);
|
||||
}
|
||||
InsertTailList(&CmiKeyObjectListHead, &KeyObject->ListEntry);
|
||||
RtlCreateUnicodeString(&KeyObject->Name, Start);
|
||||
|
||||
KeyObject->KeyCell->Parent = KeyObject->ParentKey->KeyCellOffset;
|
||||
KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset;
|
||||
|
@ -437,7 +403,7 @@ Cleanup:
|
|||
PreviousMode);
|
||||
}
|
||||
if (ObjectName.Buffer) ObpFreeObjectNameBuffer(&ObjectName);
|
||||
if (FreeRemainingPath) RtlFreeUnicodeString(&RemainingPath);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
if (Object != NULL) ObDereferenceObject(Object);
|
||||
|
||||
return Status;
|
||||
|
|
|
@ -263,39 +263,19 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
|
|||
DPRINT("RemainingPath %wZ ParentKey %p\n",
|
||||
&RemainingPath, ParentKey);
|
||||
|
||||
Status = ObCreateObject(KernelMode,
|
||||
CmpKeyObjectType,
|
||||
NULL,
|
||||
KernelMode,
|
||||
NULL,
|
||||
sizeof(KEY_OBJECT),
|
||||
0,
|
||||
0,
|
||||
(PVOID*)&NewKey);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status);
|
||||
ObDereferenceObject (ParentKey);
|
||||
RtlFreeUnicodeString(&RemainingPath);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NewKey->Flags = 0;
|
||||
NewKey->SubKeyCounts = 0;
|
||||
NewKey->SubKeys = NULL;
|
||||
NewKey->SizeOfSubKeys = 0;
|
||||
InsertTailList(&CmiKeyObjectListHead, &NewKey->ListEntry);
|
||||
|
||||
DPRINT ("SubName %S\n", SubName);
|
||||
|
||||
Status = CmiAddSubKey(ParentKey->RegistryHive,
|
||||
ParentKey,
|
||||
NewKey,
|
||||
&RemainingPath,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE);
|
||||
/* Create the key */
|
||||
Status = CmpDoCreate(&ParentKey->RegistryHive->Hive,
|
||||
ParentKey->KeyCellOffset,
|
||||
NULL,
|
||||
&RemainingPath,
|
||||
KernelMode,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
ParentKey,
|
||||
NULL,
|
||||
(PVOID*)&NewKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("CmiAddSubKey() failed (Status %lx)\n", Status);
|
||||
|
|
|
@ -15,6 +15,16 @@
|
|||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
ULONG CmpMaxFastIndexPerHblock =
|
||||
(HBLOCK_SIZE - (sizeof(HBIN) +
|
||||
sizeof(HCELL) +
|
||||
FIELD_OFFSET(CM_KEY_FAST_INDEX, List))) / sizeof(CM_INDEX);
|
||||
|
||||
ULONG CmpMaxIndexPerHblock =
|
||||
(HBLOCK_SIZE - (sizeof(HBIN) +
|
||||
sizeof(HCELL) +
|
||||
FIELD_OFFSET(CM_KEY_INDEX, List))) / sizeof(HCELL_INDEX) - 1;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
LONG
|
||||
|
@ -924,6 +934,396 @@ Quickie:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
HCELL_INDEX
|
||||
NTAPI
|
||||
CmpAddToLeaf(IN PHHIVE Hive,
|
||||
IN HCELL_INDEX LeafCell,
|
||||
IN HCELL_INDEX NewKey,
|
||||
IN PUNICODE_STRING Name)
|
||||
{
|
||||
PCM_KEY_INDEX Leaf;
|
||||
PCM_KEY_FAST_INDEX FastLeaf;
|
||||
ULONG Size, OldSize, EntrySize, i, j;
|
||||
HCELL_INDEX NewCell, Child;
|
||||
LONG Result;
|
||||
|
||||
/* Mark the leaf dirty */
|
||||
HvMarkCellDirty(Hive, LeafCell);
|
||||
|
||||
/* Get the leaf cell */
|
||||
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, LeafCell);
|
||||
if (!Leaf)
|
||||
{
|
||||
/* Shouldn't happen */
|
||||
ASSERT(FALSE);
|
||||
return HCELL_NIL;
|
||||
}
|
||||
|
||||
/* Release it */
|
||||
HvReleaseCell(Hive, LeafCell);
|
||||
|
||||
/* Check if this is an index leaf */
|
||||
if (Leaf->Signature == CM_KEY_INDEX_LEAF)
|
||||
{
|
||||
/* This is an old-style leaf */
|
||||
FastLeaf = NULL;
|
||||
EntrySize = sizeof(HCELL_INDEX);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Sanity check */
|
||||
ASSERT((Leaf->Signature == CM_KEY_FAST_LEAF) ||
|
||||
(Leaf->Signature == CM_KEY_HASH_LEAF));
|
||||
|
||||
/* This is a new-style optimized fast (or hash) leaf */
|
||||
FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
|
||||
EntrySize = sizeof(CM_INDEX);
|
||||
}
|
||||
|
||||
/* Get the current size of the leaf */
|
||||
OldSize = HvGetCellSize(Hive, Leaf);
|
||||
|
||||
/* Calculate the size of the free entries */
|
||||
Size = OldSize;
|
||||
Size -= EntrySize * Leaf->Count + FIELD_OFFSET(CM_KEY_INDEX, List);
|
||||
|
||||
/* Assume we'll re-use the same leaf */
|
||||
NewCell = LeafCell;
|
||||
|
||||
/* Check if we're out of space */
|
||||
if ((Size / EntrySize) < 1)
|
||||
{
|
||||
/* Grow the leaf by 1.5x, making sure we can at least fit this entry */
|
||||
Size = OldSize + OldSize / 2;
|
||||
if (Size < (OldSize + EntrySize)) Size = OldSize + EntrySize;
|
||||
|
||||
/* Re-allocate the leaf */
|
||||
NewCell = HvReallocateCell(Hive, LeafCell, Size);
|
||||
if (NewCell == HCELL_NIL) return HCELL_NIL;
|
||||
|
||||
/* Get the leaf cell */
|
||||
Leaf = (PCM_KEY_INDEX)HvGetCell(Hive, NewCell);
|
||||
if (!Leaf)
|
||||
{
|
||||
/* This shouldn't happen */
|
||||
ASSERT(FALSE);
|
||||
return HCELL_NIL;
|
||||
}
|
||||
|
||||
/* Release the cell */
|
||||
HvReleaseCell(Hive, NewCell);
|
||||
|
||||
/* Update the fast leaf pointer if we had one */
|
||||
if (FastLeaf) FastLeaf = (PCM_KEY_FAST_INDEX)Leaf;
|
||||
}
|
||||
|
||||
/* Find the insertion point for our entry */
|
||||
i = CmpFindSubKeyInLeaf(Hive, Leaf, Name, &Child);
|
||||
if (i & 0x80000000) return HCELL_NIL;
|
||||
ASSERT(Child == HCELL_NIL);
|
||||
|
||||
/* Check if we're not last */
|
||||
if (i != Leaf->Count)
|
||||
{
|
||||
/* Find out where we should go */
|
||||
Result = CmpCompareInIndex(Hive,
|
||||
Name,
|
||||
i,
|
||||
Leaf,
|
||||
&Child);
|
||||
if (Result == 2) return HCELL_NIL;
|
||||
ASSERT(Result != 0);
|
||||
|
||||
/* Check if we come after */
|
||||
if (Result > 0)
|
||||
{
|
||||
/* We do, insert us after the key */
|
||||
ASSERT(Result == 1);
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Check if we're still not last */
|
||||
if (i != Leaf->Count)
|
||||
{
|
||||
/* Check if we had a fast leaf or not */
|
||||
if (FastLeaf)
|
||||
{
|
||||
/* Copy the fast indexes */
|
||||
RtlMoveMemory(&FastLeaf->List[i + 1],
|
||||
&FastLeaf->List[i],
|
||||
(FastLeaf->Count - i) * sizeof(CM_INDEX));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy the indexes themselves */
|
||||
RtlMoveMemory(&Leaf->List[i + 1],
|
||||
&Leaf->List[i],
|
||||
(Leaf->Count - i) * sizeof(HCELL_INDEX));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if this is a new-style leaf */
|
||||
if (FastLeaf)
|
||||
{
|
||||
/* Set our cell */
|
||||
FastLeaf->List[i].Cell = NewKey;
|
||||
|
||||
/* Check if this is a hash leaf */
|
||||
if( FastLeaf->Signature == CM_KEY_HASH_LEAF )
|
||||
{
|
||||
/* Set our hash key */
|
||||
FastLeaf->List[i].HashKey = CmpComputeHashKey(0, Name, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* First, clear the name */
|
||||
FastLeaf->List[i].NameHint[0] = 0;
|
||||
FastLeaf->List[i].NameHint[1] = 0;
|
||||
FastLeaf->List[i].NameHint[2] = 0;
|
||||
FastLeaf->List[i].NameHint[3] = 0;
|
||||
|
||||
/* Now, figure out if we can fit */
|
||||
if (Name->Length / sizeof(WCHAR) < 4)
|
||||
{
|
||||
/* We can fit, use our length */
|
||||
j = Name->Length / sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We can't, use a maximum of 4 */
|
||||
j = 4;
|
||||
}
|
||||
|
||||
/* Now fill out the name hint */
|
||||
do
|
||||
{
|
||||
/* Look for invalid characters and break out if we found one */
|
||||
if ((USHORT)Name->Buffer[j - 1] > (UCHAR)-1) break;
|
||||
|
||||
/* Otherwise, copy the a character */
|
||||
FastLeaf->List[i].NameHint[j - 1] = (UCHAR)Name->Buffer[j - 1];
|
||||
} while (--j > 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is an old-style leaf, just set our index directly */
|
||||
Leaf->List[i] = NewKey;
|
||||
}
|
||||
|
||||
/* Update the leaf count and return the new cell */
|
||||
Leaf->Count += 1;
|
||||
return NewCell;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmpAddSubKey(IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Parent,
|
||||
IN HCELL_INDEX Child)
|
||||
{
|
||||
PCM_KEY_NODE KeyNode;
|
||||
PCM_KEY_INDEX Index;
|
||||
UNICODE_STRING Name;
|
||||
HCELL_INDEX IndexCell = HCELL_NIL, CellToRelease = HCELL_NIL, LeafCell;
|
||||
PHCELL_INDEX RootPointer = NULL;
|
||||
ULONG Type;
|
||||
BOOLEAN IsCompressed;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Get the key node */
|
||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Child);
|
||||
if (!KeyNode)
|
||||
{
|
||||
/* Shouldn't happen */
|
||||
ASSERT(FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check if the name is compressed */
|
||||
if (KeyNode->Flags & KEY_COMP_NAME)
|
||||
{
|
||||
/* Remember for later */
|
||||
IsCompressed = TRUE;
|
||||
|
||||
/* Create the compressed name and allocate it */
|
||||
Name.Length = CmpCompressedNameSize(KeyNode->Name, KeyNode->NameLength);
|
||||
Name.MaximumLength = Name.Length;
|
||||
Name.Buffer = Hive->Allocate(Name.Length, TRUE);
|
||||
if (!Name.Buffer)
|
||||
{
|
||||
/* Release the cell and fail */
|
||||
HvReleaseCell(Hive, Child);
|
||||
ASSERT(FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Copy the compressed name */
|
||||
CmpCopyCompressedName(Name.Buffer,
|
||||
Name.MaximumLength,
|
||||
KeyNode->Name,
|
||||
KeyNode->NameLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Remember for later */
|
||||
IsCompressed = FALSE;
|
||||
|
||||
/* Build the unicode string */
|
||||
Name.Length = KeyNode->NameLength;
|
||||
Name.MaximumLength = KeyNode->NameLength;
|
||||
Name.Buffer = &KeyNode->Name[0];
|
||||
}
|
||||
|
||||
/* Release the cell */
|
||||
HvReleaseCell(Hive, Child);
|
||||
|
||||
/* Get the parent node */
|
||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Parent);
|
||||
if (!KeyNode)
|
||||
{
|
||||
/* Not handled */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Find out the type of the cell, and check if this is the first subkey */
|
||||
Type = HvGetCellType(Child);
|
||||
if (!KeyNode->SubKeyCounts[Type])
|
||||
{
|
||||
/* Allocate a fast leaf */
|
||||
IndexCell = HvAllocateCell(Hive, sizeof(CM_KEY_FAST_INDEX), Type);
|
||||
if (IndexCell == HCELL_NIL)
|
||||
{
|
||||
/* Not handled */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Get the leaf cell */
|
||||
Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
|
||||
if (!Index)
|
||||
{
|
||||
/* Shouldn't happen */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Now check what kind of hive we're dealing with */
|
||||
if (Hive->Version >= 5)
|
||||
{
|
||||
/* XP Hive: Use hash leaf */
|
||||
Index->Signature = CM_KEY_HASH_LEAF;
|
||||
}
|
||||
else if (Hive->Version >= 3)
|
||||
{
|
||||
/* Windows 2000 and ReactOS: Use fast leaf */
|
||||
Index->Signature = CM_KEY_FAST_LEAF;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NT 4: Use index leaf */
|
||||
Index->Signature = CM_KEY_INDEX_LEAF;
|
||||
}
|
||||
|
||||
/* Setup the index list */
|
||||
Index->Count = 0;
|
||||
KeyNode->SubKeyLists[Type] = IndexCell;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We already have an index, get it */
|
||||
Index = (PCM_KEY_INDEX)HvGetCell(Hive, KeyNode->SubKeyLists[Type]);
|
||||
if (!Index)
|
||||
{
|
||||
/* Not handled */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Remember to release the cell later */
|
||||
CellToRelease = KeyNode->SubKeyLists[Type];
|
||||
|
||||
/* Check if this is a fast leaf that's gotten too full */
|
||||
if ((Index->Signature == CM_KEY_FAST_LEAF) &&
|
||||
(Index->Count >= CmpMaxFastIndexPerHblock))
|
||||
{
|
||||
/* Not handled yet */
|
||||
DPRINT1("Fast->Slow Leaf Conversion not yet implemented!\n");
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
else if (((Index->Signature == CM_KEY_INDEX_LEAF) ||
|
||||
(Index->Signature == CM_KEY_HASH_LEAF)) &&
|
||||
(Index->Count >= CmpMaxIndexPerHblock))
|
||||
{
|
||||
/* This is an old/hashed leaf that's gotten too large, root it */
|
||||
IndexCell = HvAllocateCell(Hive,
|
||||
sizeof(CM_KEY_INDEX) +
|
||||
sizeof(HCELL_INDEX),
|
||||
Type);
|
||||
if (IndexCell == HCELL_NIL)
|
||||
{
|
||||
/* Not handled */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Get the index cell */
|
||||
Index = (PCM_KEY_INDEX)HvGetCell(Hive, IndexCell);
|
||||
if (!Index)
|
||||
{
|
||||
/* Shouldn't happen */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Mark the index as a root, and set the index cell */
|
||||
Index->Signature = CM_KEY_INDEX_ROOT;
|
||||
Index->Count = 1;
|
||||
Index->List[0] = KeyNode->SubKeyLists[Type];
|
||||
KeyNode->SubKeyLists[Type] = IndexCell;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we can choose the leaf cell */
|
||||
LeafCell = KeyNode->SubKeyLists[Type];
|
||||
|
||||
/* Check if we turned the index into a root */
|
||||
if (Index->Signature == CM_KEY_INDEX_ROOT)
|
||||
{
|
||||
/* Not handled yet */
|
||||
DPRINT1("Leaf->Root Index Conversion not yet implemented!\n");
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Add our leaf cell */
|
||||
LeafCell = CmpAddToLeaf(Hive, LeafCell, Child, &Name);
|
||||
if (LeafCell == HCELL_NIL)
|
||||
{
|
||||
/* Not handled */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Update the key counts */
|
||||
KeyNode->SubKeyCounts[Type]++;
|
||||
|
||||
/* Check if caller wants us to return the leaf */
|
||||
if (RootPointer)
|
||||
{
|
||||
/* Return it */
|
||||
*RootPointer = LeafCell;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, mark it as the list index for the cell */
|
||||
KeyNode->SubKeyLists[Type] = LeafCell;
|
||||
}
|
||||
|
||||
/* If the name was compressed, free our copy */
|
||||
if (IsCompressed) Hive->Free(Name.Buffer);
|
||||
|
||||
/* Release all our cells */
|
||||
if (IndexCell != HCELL_NIL) HvReleaseCell(Hive, IndexCell);
|
||||
if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease);
|
||||
HvReleaseCell(Hive, Parent);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CmpRemoveSubKey(IN PHHIVE Hive,
|
||||
|
|
|
@ -73,3 +73,329 @@ CmpGetNextName(IN OUT PUNICODE_STRING RemainingName,
|
|||
*LastName = !RemainingName->Length;
|
||||
return NameValid;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpDoCreateChild(IN PHHIVE Hive,
|
||||
IN HCELL_INDEX ParentCell,
|
||||
IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
|
||||
IN PACCESS_STATE AccessState,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN PUNICODE_STRING Class,
|
||||
IN PKEY_OBJECT Parent,
|
||||
IN ULONG CreateOptions,
|
||||
OUT PHCELL_INDEX KeyCell,
|
||||
OUT PVOID *Object)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PKEY_OBJECT KeyBody;
|
||||
HCELL_INDEX ClassCell = HCELL_NIL;
|
||||
PCM_KEY_NODE KeyNode;
|
||||
PCELL_DATA CellData;
|
||||
ULONG StorageType;
|
||||
LARGE_INTEGER SystemTime;
|
||||
BOOLEAN Hack = FALSE;
|
||||
|
||||
/* ReactOS Hack */
|
||||
if (Name->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
|
||||
{
|
||||
/* Skip initial path separator */
|
||||
Name->Buffer++;
|
||||
Name->Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
Name->MaximumLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
Hack = TRUE;
|
||||
}
|
||||
|
||||
/* Get the storage type */
|
||||
StorageType = HvStable;
|
||||
if (CreateOptions & REG_OPTION_VOLATILE) StorageType = HvVolatile;
|
||||
|
||||
/* Allocate the child */
|
||||
*KeyCell = HvAllocateCell(Hive,
|
||||
FIELD_OFFSET(CM_KEY_NODE, Name) +
|
||||
CmpNameSize(Hive, Name),
|
||||
StorageType);
|
||||
if (*KeyCell == HCELL_NIL)
|
||||
{
|
||||
/* Fail */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Get the key node */
|
||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, *KeyCell);
|
||||
if (!KeyNode)
|
||||
{
|
||||
/* Fail, this should never happen */
|
||||
ASSERT(FALSE);
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Release the cell */
|
||||
HvReleaseCell(Hive, *KeyCell);
|
||||
|
||||
/* Check if we have a class name */
|
||||
if (Class->Length > 0)
|
||||
{
|
||||
/* Allocate a class cell */
|
||||
ClassCell = HvAllocateCell(Hive, Class->Length, StorageType);
|
||||
if (ClassCell == HCELL_NIL)
|
||||
{
|
||||
/* Fail */
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Quickie;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate the Cm Object */
|
||||
Status = ObCreateObject(AccessMode,
|
||||
CmpKeyObjectType,
|
||||
NULL,
|
||||
AccessMode,
|
||||
NULL,
|
||||
sizeof(KEY_OBJECT),
|
||||
0,
|
||||
0,
|
||||
Object);
|
||||
if (!NT_SUCCESS(Status)) goto Quickie;
|
||||
KeyBody = (PKEY_OBJECT)(*Object);
|
||||
|
||||
/* Check if we had a class */
|
||||
if (Class->Length > 0)
|
||||
{
|
||||
/* Get the class cell */
|
||||
CellData = HvGetCell(Hive, ClassCell);
|
||||
if (!CellData)
|
||||
{
|
||||
/* Fail, this should never happen */
|
||||
ASSERT(FALSE);
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
ObDereferenceObject(*Object);
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Release the cell */
|
||||
HvReleaseCell(Hive, ClassCell);
|
||||
|
||||
/* Copy the class data */
|
||||
RtlCopyMemory(&CellData->u.KeyString[0],
|
||||
Class->Buffer,
|
||||
Class->Length);
|
||||
}
|
||||
|
||||
/* Fill out the key node */
|
||||
KeyNode->Signature = CM_KEY_NODE_SIGNATURE;
|
||||
KeyNode->Flags = CreateOptions;
|
||||
KeQuerySystemTime(&SystemTime);
|
||||
KeyNode->LastWriteTime = SystemTime;
|
||||
KeyNode->Spare = 0;
|
||||
KeyNode->Parent = ParentCell;
|
||||
KeyNode->SubKeyCounts[HvStable] = 0;
|
||||
KeyNode->SubKeyCounts[HvVolatile] = 0;
|
||||
KeyNode->SubKeyLists[HvStable] = HCELL_NIL;
|
||||
KeyNode->SubKeyLists[HvVolatile] = HCELL_NIL;
|
||||
KeyNode->ValueList.Count = 0;
|
||||
KeyNode->ValueList.List = HCELL_NIL;
|
||||
KeyNode->Security = HCELL_NIL;
|
||||
KeyNode->Class = ClassCell;
|
||||
KeyNode->ClassLength = Class->Length;
|
||||
KeyNode->MaxValueDataLen = 0;
|
||||
KeyNode->MaxNameLen = 0;
|
||||
KeyNode->MaxValueNameLen = 0;
|
||||
KeyNode->MaxClassLen = 0;
|
||||
KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, Name);
|
||||
if (KeyNode->NameLength < Name->Length) KeyNode->Flags |= KEY_COMP_NAME;
|
||||
|
||||
/* Now fill out the Cm object */
|
||||
KeyBody->KeyCell = KeyNode;
|
||||
KeyBody->KeyCellOffset = *KeyCell;
|
||||
KeyBody->Flags = 0;
|
||||
KeyBody->SubKeyCounts = 0;
|
||||
KeyBody->SubKeys = NULL;
|
||||
KeyBody->SizeOfSubKeys = 0;
|
||||
KeyBody->ParentKey = Parent;
|
||||
KeyBody->RegistryHive = KeyBody->ParentKey->RegistryHive;
|
||||
InsertTailList(&CmiKeyObjectListHead, &KeyBody->ListEntry);
|
||||
|
||||
Quickie:
|
||||
/* Check if we got here because of failure */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Free any cells we might've allocated */
|
||||
if (Class->Length > 0) HvFreeCell(Hive, ClassCell);
|
||||
HvFreeCell(Hive, *KeyCell);
|
||||
}
|
||||
|
||||
/* Check if we applied ReactOS hack */
|
||||
if (Hack)
|
||||
{
|
||||
/* Restore name */
|
||||
Name->Buffer--;
|
||||
Name->Length += sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
Name->MaximumLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpDoCreate(IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Cell,
|
||||
IN PACCESS_STATE AccessState,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN PUNICODE_STRING Class OPTIONAL,
|
||||
IN ULONG CreateOptions,
|
||||
IN PKEY_OBJECT Parent,
|
||||
IN PCMHIVE OriginatingHive OPTIONAL,
|
||||
OUT PVOID *Object)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PCELL_DATA CellData;
|
||||
HCELL_INDEX KeyCell;
|
||||
ULONG ParentType;
|
||||
PKEY_OBJECT KeyBody;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
||||
LARGE_INTEGER TimeStamp;
|
||||
PCM_KEY_NODE KeyNode;
|
||||
UNICODE_STRING LocalClass = {0};
|
||||
if (!Class) Class = &LocalClass;
|
||||
|
||||
/* Acquire the flusher lock */
|
||||
//ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock);
|
||||
|
||||
/* Check if the parent is being deleted */
|
||||
#define KO_MARKED_FOR_DELETE 0x00000001
|
||||
if (Parent->Flags & KO_MARKED_FOR_DELETE)
|
||||
{
|
||||
/* It has, quit */
|
||||
ASSERT(FALSE);
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* Get the parent node */
|
||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
|
||||
if (!KeyNode)
|
||||
{
|
||||
/* Fail */
|
||||
ASSERT(FALSE);
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* Make sure nobody added us yet */
|
||||
if (CmpFindSubKeyByName(Hive, KeyNode, Name) != HCELL_NIL)
|
||||
{
|
||||
/* Fail */
|
||||
ASSERT(FALSE);
|
||||
Status = STATUS_REPARSE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(Cell == Parent->KeyCellOffset);
|
||||
|
||||
/* Get the parent type */
|
||||
ParentType = HvGetCellType(Cell);
|
||||
if ((ParentType == HvVolatile) && !(CreateOptions & REG_OPTION_VOLATILE))
|
||||
{
|
||||
/* Children of volatile parents must also be volatile */
|
||||
ASSERT(FALSE);
|
||||
Status = STATUS_CHILD_MUST_BE_VOLATILE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* Don't allow children under symlinks */
|
||||
if (Parent->Flags & KEY_SYM_LINK)
|
||||
{
|
||||
/* Fail */
|
||||
ASSERT(FALSE);
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* Make the cell dirty for now */
|
||||
HvMarkCellDirty(Hive, Cell);
|
||||
|
||||
/* Do the actual create operation */
|
||||
Status = CmpDoCreateChild(Hive,
|
||||
Cell,
|
||||
SecurityDescriptor,
|
||||
AccessState,
|
||||
Name,
|
||||
AccessMode,
|
||||
Class,
|
||||
Parent,
|
||||
CreateOptions,
|
||||
&KeyCell,
|
||||
Object);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Get the key body */
|
||||
KeyBody = (PKEY_OBJECT)(*Object);
|
||||
|
||||
/* Now add the subkey */
|
||||
if (!CmpAddSubKey(Hive, Cell, KeyCell))
|
||||
{
|
||||
/* Failure! We don't handle this yet! */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Get the key node */
|
||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
|
||||
if (!KeyNode)
|
||||
{
|
||||
/* Fail, this shouldn't happen */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Sanity checks */
|
||||
ASSERT(KeyBody->ParentKey->KeyCellOffset == Cell);
|
||||
ASSERT(&KeyBody->ParentKey->RegistryHive->Hive == Hive);
|
||||
ASSERT(KeyBody->ParentKey == Parent);
|
||||
|
||||
/* Update the timestamp */
|
||||
KeQuerySystemTime(&TimeStamp);
|
||||
KeyNode->LastWriteTime = TimeStamp;
|
||||
|
||||
/* Check if we need to update name maximum */
|
||||
if (KeyNode->MaxNameLen < Name->Length)
|
||||
{
|
||||
/* Do it */
|
||||
KeyNode->MaxNameLen = Name->Length;
|
||||
}
|
||||
|
||||
/* Check if we need toupdate class length maximum */
|
||||
if (KeyNode->MaxClassLen < Class->Length)
|
||||
{
|
||||
/* Update it */
|
||||
KeyNode->MaxClassLen = Class->Length;
|
||||
}
|
||||
|
||||
/* Check if we're creating a symbolic link */
|
||||
if (CreateOptions & REG_OPTION_CREATE_LINK)
|
||||
{
|
||||
/* Get the cell data */
|
||||
CellData = HvGetCell(Hive, KeyCell);
|
||||
if (!CellData)
|
||||
{
|
||||
/* This shouldn't happen */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
/* Update the flags */
|
||||
CellData->u.KeyNode.Flags |= KEY_SYM_LINK;
|
||||
HvReleaseCell(Hive, KeyCell);
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
/* Release the flusher lock and return status */
|
||||
//ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
|
||||
return Status;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue