[NTOS]: Improve a bit CmpDeepCopyKeyInternal():

- Normally getting the SrcNode and DestNode must succeed (checked with assert);
- Set the DestNode Flags member, in particular when this is the new root node of the saved registry hive;
- Copy the key class cell (OK), and the key security cell (currently done in a hackish way; proper way: call the CmpAssignSecurity* function);
- Add more clean-up on failure;
- Warn in code about the fact that CmpDeepCopyKeyInternal is recursive, and will easily exhaust kernel stack. This function will need to be reworked later...
CORE-10793 CORE-10796

svn path=/trunk/; revision=75171
This commit is contained in:
Hermès Bélusca-Maïto 2017-06-23 17:33:44 +00:00
parent 3dae17b0e7
commit ab30fb1d60

View file

@ -993,7 +993,7 @@ CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
goto Quickie; goto Quickie;
} }
/* Ssanity checks */ /* Sanity checks */
ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List)); ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List));
ASSERT(HvIsCellDirty(Hive, ChildCell)); ASSERT(HvIsCellDirty(Hive, ChildCell));
@ -2376,7 +2376,6 @@ CmCountOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb,
static static
NTSTATUS NTSTATUS
NTAPI
CmpDeepCopyKeyInternal(IN PHHIVE SourceHive, CmpDeepCopyKeyInternal(IN PHHIVE SourceHive,
IN HCELL_INDEX SrcKeyCell, IN HCELL_INDEX SrcKeyCell,
IN PHHIVE DestinationHive, IN PHHIVE DestinationHive,
@ -2387,8 +2386,11 @@ CmpDeepCopyKeyInternal(IN PHHIVE SourceHive,
NTSTATUS Status; NTSTATUS Status;
PCM_KEY_NODE SrcNode; PCM_KEY_NODE SrcNode;
PCM_KEY_NODE DestNode = NULL; PCM_KEY_NODE DestNode = NULL;
HCELL_INDEX NewKeyCell, SubKey, NewSubKey; HCELL_INDEX NewKeyCell = HCELL_NIL;
HCELL_INDEX NewClassCell = HCELL_NIL, NewSecCell = HCELL_NIL;
HCELL_INDEX SubKey, NewSubKey;
ULONG Index, SubKeyCount; ULONG Index, SubKeyCount;
PAGED_CODE(); PAGED_CODE();
DPRINT("CmpDeepCopyKeyInternal(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X)\n", DPRINT("CmpDeepCopyKeyInternal(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X)\n",
@ -2401,6 +2403,7 @@ CmpDeepCopyKeyInternal(IN PHHIVE SourceHive,
/* Get the source cell node */ /* Get the source cell node */
SrcNode = HvGetCell(SourceHive, SrcKeyCell); SrcNode = HvGetCell(SourceHive, SrcKeyCell);
ASSERT(SrcNode);
/* Sanity check */ /* Sanity check */
ASSERT(SrcNode->Signature == CM_KEY_NODE_SIGNATURE); ASSERT(SrcNode->Signature == CM_KEY_NODE_SIGNATURE);
@ -2419,12 +2422,55 @@ CmpDeepCopyKeyInternal(IN PHHIVE SourceHive,
/* Get the destination cell node */ /* Get the destination cell node */
DestNode = HvGetCell(DestinationHive, NewKeyCell); DestNode = HvGetCell(DestinationHive, NewKeyCell);
ASSERT(DestNode);
/* Set the parent */ /* Set the parent and copy the flags */
DestNode->Parent = Parent; DestNode->Parent = Parent;
DestNode->Flags = (SrcNode->Flags & KEY_COMP_NAME); // Keep only the single permanent flag
if (Parent == HCELL_NIL)
{
/* This is the new root node */
DestNode->Flags |= KEY_HIVE_ENTRY | KEY_NO_DELETE;
}
// TODO: These should also be copied! /* Copy the class cell */
DestNode->Security = DestNode->Class = HCELL_NIL; if (SrcNode->ClassLength > 0)
{
NewClassCell = CmpCopyCell(SourceHive,
SrcNode->Class,
DestinationHive,
StorageType);
if (NewClassCell == HCELL_NIL)
{
/* Not enough storage space */
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
DestNode->Class = NewClassCell;
DestNode->ClassLength = SrcNode->ClassLength;
}
else
{
DestNode->Class = HCELL_NIL;
DestNode->ClassLength = 0;
}
/* Copy the security cell (FIXME: HACKish poor-man version) */
if (SrcNode->Security != HCELL_NIL)
{
NewSecCell = CmpCopyCell(SourceHive,
SrcNode->Security,
DestinationHive,
StorageType);
if (NewSecCell == HCELL_NIL)
{
/* Not enough storage space */
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
}
DestNode->Security = NewSecCell;
/* Copy the value list */ /* Copy the value list */
Status = CmpCopyKeyValueList(SourceHive, Status = CmpCopyKeyValueList(SourceHive,
@ -2432,7 +2478,8 @@ CmpDeepCopyKeyInternal(IN PHHIVE SourceHive,
DestinationHive, DestinationHive,
&DestNode->ValueList, &DestNode->ValueList,
StorageType); StorageType);
if (!NT_SUCCESS(Status)) goto Cleanup; if (!NT_SUCCESS(Status))
goto Cleanup;
/* Clear the invalid subkey index */ /* Clear the invalid subkey index */
DestNode->SubKeyCounts[Stable] = DestNode->SubKeyCounts[Volatile] = 0; DestNode->SubKeyCounts[Stable] = DestNode->SubKeyCounts[Volatile] = 0;
@ -2449,34 +2496,57 @@ CmpDeepCopyKeyInternal(IN PHHIVE SourceHive,
ASSERT(SubKey != HCELL_NIL); ASSERT(SubKey != HCELL_NIL);
/* Call the function recursively for the subkey */ /* Call the function recursively for the subkey */
//
// FIXME: Danger!! Kernel stack exhaustion!!
//
Status = CmpDeepCopyKeyInternal(SourceHive, Status = CmpDeepCopyKeyInternal(SourceHive,
SubKey, SubKey,
DestinationHive, DestinationHive,
NewKeyCell, NewKeyCell,
StorageType, StorageType,
&NewSubKey); &NewSubKey);
if (!NT_SUCCESS(Status)) goto Cleanup; if (!NT_SUCCESS(Status))
goto Cleanup;
/* Add the copy of the subkey to the new key */ /* Add the copy of the subkey to the new key */
if (!CmpAddSubKey(DestinationHive, if (!CmpAddSubKey(DestinationHive,
NewKeyCell, NewKeyCell,
NewSubKey)) NewSubKey))
{ {
/* Cleanup allocated cell */
HvFreeCell(DestinationHive, NewSubKey);
Status = STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup; goto Cleanup;
} }
} }
/* Set the cell index if requested and return success */ /* Set success */
if (DestKeyCell) *DestKeyCell = NewKeyCell;
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
Cleanup: Cleanup:
/* Release the cells */ /* Release the cells */
if (SrcNode) HvReleaseCell(SourceHive, SrcKeyCell);
if (DestNode) HvReleaseCell(DestinationHive, NewKeyCell); if (DestNode) HvReleaseCell(DestinationHive, NewKeyCell);
if (SrcNode) HvReleaseCell(SourceHive, SrcKeyCell);
/* Cleanup allocated cells in case of failure */
if (!NT_SUCCESS(Status))
{
if (NewSecCell != HCELL_NIL)
HvFreeCell(DestinationHive, NewSecCell);
if (NewClassCell != HCELL_NIL)
HvFreeCell(DestinationHive, NewClassCell);
if (NewKeyCell != HCELL_NIL)
HvFreeCell(DestinationHive, NewKeyCell);
NewKeyCell = HCELL_NIL;
}
/* Set the cell index if requested and return status */
if (DestKeyCell) *DestKeyCell = NewKeyCell;
return Status; return Status;
} }