if (Length > 0xFFFF) goto Exit;
/* Check if we need a new buffer */
- if (Length > ObjectName->MaximumLength)
+ if (Length > ObjectName->MaximumLength)
{
/* We do -- allocate one */
NewBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM);
/* Setup the key body */
KeyBody = (PCM_KEY_BODY)(*Object);
- KeyBody->Type = '20yk';
+ KeyBody->Type = CM_KEY_BODY_TYPE;
KeyBody->KeyControlBlock = NULL;
/* Check if we had a class */
KeyNode->MaxClassLen = 0;
KeyNode->NameLength = CmpCopyName(Hive, KeyNode->Name, Name);
if (KeyNode->NameLength < Name->Length) KeyNode->Flags |= KEY_COMP_NAME;
-
+
/* Create the KCB */
Kcb = CmpCreateKeyControlBlock(Hive,
*KeyCell,
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
}
-
+
/* Sanity check */
ASSERT(Kcb->RefCount == 1);
KeyBody->NotifyBlock = NULL;
KeyBody->ProcessID = PsGetCurrentProcessId();
KeyBody->KeyControlBlock = Kcb;
-
+
/* Link it with the KCB */
EnlistKeyBodyWithKCB(KeyBody, 0);
/* Get the key body and fill it out */
KeyBody = (PCM_KEY_BODY)(*Object);
KeyBody->KeyControlBlock = Kcb;
- KeyBody->Type = '20yk';
+ KeyBody->Type = CM_KEY_BODY_TYPE;
KeyBody->ProcessID = PsGetCurrentProcessId();
KeyBody->NotifyBlock = NULL;
DPRINT1("Invalid link node attempt\n");
return STATUS_ACCESS_DENIED;
}
-
+
/* Check if the parent is being deleted */
if (ParentKcb->Delete)
{
Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto Exit;
}
-
+
/* Allocate a link node */
LinkCell = HvAllocateCell(Hive,
FIELD_OFFSET(CM_KEY_NODE, Name) +
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
-
+
/* Get the key cell */
KeyCell = Context->ChildHive.KeyCell;
if (KeyCell != HCELL_NIL)
{
/* Hive exists! */
ChildCell = KeyCell;
-
+
/* Get the node data */
KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, ChildCell);
if (!KeyNode)
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
-
+
/* Fill out the data */
KeyNode->Parent = LinkCell;
KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
-
+
/* Now open the key cell */
KeyNode = (PCM_KEY_NODE)HvGetCell(Context->ChildHive.KeyHive, KeyCell);
if (!KeyNode)
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
-
+
/* Open the parent */
Status = CmpDoOpen(Context->ChildHive.KeyHive,
KeyCell,
Context->ChildHive.KeyHive->BaseBlock->RootCell = ChildCell;
}
}
-
+
/* Check if open or create suceeded */
if (NT_SUCCESS(Status))
{
/* Mark the cell dirty */
HvMarkCellDirty(Context->ChildHive.KeyHive, ChildCell, FALSE);
-
+
/* Get the key node */
KeyNode = HvGetCell(Context->ChildHive.KeyHive, ChildCell);
if (!KeyNode)
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
-
+
/* Release it */
HvReleaseCell(Context->ChildHive.KeyHive, ChildCell);
-
+
/* Set the parent and flags */
KeyNode->Parent = LinkCell;
KeyNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
-
+
/* Get the link node */
KeyNode = HvGetCell(Hive, LinkCell);
if (!KeyNode)
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
-
+
/* Set it up */
KeyNode->Signature = CM_LINK_NODE_SIGNATURE;
KeyNode->Flags = KEY_HIVE_EXIT | KEY_NO_DELETE;
if (KeyNode->NameLength < Name.Length) KeyNode->Flags |= KEY_COMP_NAME;
KeQuerySystemTime(&TimeStamp);
KeyNode->LastWriteTime = TimeStamp;
-
+
/* Clear out the rest */
KeyNode->SubKeyCounts[Stable] = 0;
KeyNode->SubKeyCounts[Volatile] = 0;
KeyNode->ValueList.Count = 0;
KeyNode->ValueList.List = HCELL_NIL;
KeyNode->ClassLength = 0;
-
+
/* Reference the root node */
KeyNode->ChildHiveReference.KeyHive = Context->ChildHive.KeyHive;
KeyNode->ChildHiveReference.KeyCell = ChildCell;
HvReleaseCell(Hive, LinkCell);
-
+
/* Get the parent node */
KeyNode = HvGetCell(Hive, Cell);
if (!KeyNode)
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Exit;
}
-
+
/* Now add the subkey */
if (!CmpAddSubKey(Hive, Cell, LinkCell))
{
/* Failure! We don't handle this yet! */
ASSERT(FALSE);
}
-
+
/* Get the key body */
KeyBody = (PCM_KEY_BODY)*Object;
ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell);
ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive);
ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
-
+
/* Update the timestamp */
KeQuerySystemTime(&TimeStamp);
KeyNode->LastWriteTime = TimeStamp;
KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
-
+
/* Check if we need to update name maximum */
if (KeyNode->MaxNameLen < Name.Length)
{
KeyNode->MaxNameLen = Name.Length;
KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name.Length;
}
-
+
/* Check if we need toupdate class length maximum */
if (KeyNode->MaxClassLen < Context->Class.Length)
{
/* Update it */
KeyNode->MaxClassLen = Context->Class.Length;
}
-
+
/* Release the cell */
HvReleaseCell(Hive, Cell);
}
/* Release the link cell */
HvReleaseCell(Hive, LinkCell);
}
-
+
Exit:
/* Release the flusher locks and return status */
return Status;
ASSERT(*ReleaseHive != NULL);
HvReleaseCell((*ReleaseHive), *ReleaseCell);
}
-
+
/* Get the link references */
*Hive = (*KeyNode)->ChildHiveReference.KeyHive;
*Cell = (*KeyNode)->ChildHiveReference.KeyCell;
-
+
/* Get the new node */
*KeyNode = (PCM_KEY_NODE)HvGetCell((*Hive), *Cell);
if (*KeyNode)
/* Calculate hash values */
*TotalRemainingSubkeys = 0xBAADF00D;
-
+
/* Lock the registry */
CmpLockRegistry();
-
+
/* Return hive and cell data */
*Hive = (*Kcb)->KeyHive;
*Cell = (*Kcb)->KeyCell;
/* Fail if this isn't a key object */
if (ObjectType != CmpKeyObjectType) return STATUS_OBJECT_TYPE_MISMATCH;
-
+
/* Copy the remaining name */
Current = *RemainingName;
/* It isn't, so no context */
ParseContext = NULL;
}
-
+
/* Grab the KCB */
Kcb = ((PCM_KEY_BODY)ParseObject)->KeyControlBlock;
+ /* Sanity check */
+ ASSERT(Kcb != NULL);
+
+ /* Fail if the key was marked as deleted */
+ if (Kcb->Delete)
+ return STATUS_KEY_DELETED;
+
/* Lookup in the cache */
Status = CmpBuildHashStackAndLookupCache(ParseObject,
&Kcb,
&TotalSubkeys,
NULL,
&LockedKcbs);
-
+
/* This is now the parent */
ParentKcb = Kcb;
-
+
+ /* Sanity check */
+ ASSERT(ParentKcb != NULL);
+
/* Check if everything was found cached */
if (!TotalRemainingSubkeys) ASSERTMSG("Caching not implemented", FALSE);
goto Quickie;
}
Current.MaximumLength += NextName.MaximumLength;
-
+
/* Parse the symlink */
if (CmpGetSymbolicLink(Hive,
CompleteName,
/* We're done */
goto Quickie;
}
-
+
/* Get the key node */
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
if (!Node)
Cell = NextCell;
Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
if (!Node) ASSERT(FALSE);
-
+
/* Check if this was the last key */
if (Last)
{
&CellToRelease);
if (!Node) ASSERT(FALSE);
}
-
+
/* Do the open */
Status = CmpDoOpen(Hive,
Cell,
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
}
-
+
/* We are done */
break;
}
-
+
/* Is this an exit node */
if (Node->Flags & KEY_HIVE_EXIT)
{
0,
&NextName);
if (!Kcb) ASSERT(FALSE);
-
+
/* Dereference the parent and set the new one */
CmpDereferenceKeyControlBlock(ParentKcb);
ParentKcb = Kcb;
ParentKcb,
Object);
}
-
+
/* Check for reparse (in this case, someone beat us) */
if (Status == STATUS_REPARSE) break;
{
/* Save the next name */
Current.Buffer = NextName.Buffer;
-
+
/* Validate the current name string length */
if (Current.Length + NextName.Length > MAXUSHORT)
{
break;
}
Current.Length += NextName.Length;
-
+
/* Validate the current name string maximum length */
if (Current.MaximumLength + NextName.MaximumLength > MAXUSHORT)
{
break;
}
Current.MaximumLength += NextName.MaximumLength;
-
+
/* Parse the symlink */
if (CmpGetSymbolicLink(Hive,
CompleteName,
{
/* Nothing to do */
}
-
+
/* We're done */
break;
}
/* Dereference the parent if it exists */
Quickie:
if (ParentKcb) CmpDereferenceKeyControlBlock(ParentKcb);
-
+
/* Unlock the registry */
CmpUnlockRegistry();
return Status;