goto Quickie;
}
- /* Ssanity checks */
+ /* Sanity checks */
ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List));
ASSERT(HvIsCellDirty(Hive, ChildCell));
goto Quickie;
}
- /* Check what class we got */
- switch (KeyInformationClass)
+ /* Data can be user-mode, use SEH */
+ _SEH2_TRY
{
- /* Typical information */
- case KeyFullInformation:
- case KeyBasicInformation:
- case KeyNodeInformation:
+ /* Check what class we got */
+ switch (KeyInformationClass)
+ {
+ /* Typical information */
+ case KeyFullInformation:
+ case KeyBasicInformation:
+ case KeyNodeInformation:
+ {
+ /* Get the hive and parent */
+ Hive = Kcb->KeyHive;
+ Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
+ ASSERT(Parent);
- /* Get the hive and parent */
- Hive = Kcb->KeyHive;
- Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
- ASSERT(Parent);
+ /* Track cell references */
+ if (!HvTrackCellRef(&CellReferences, Hive, Kcb->KeyCell))
+ {
+ /* Not enough memory to track references */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ /* Call the internal API */
+ Status = CmpQueryKeyData(Hive,
+ Parent,
+ KeyInformationClass,
+ KeyInformation,
+ Length,
+ ResultLength);
+ }
+ break;
+ }
- /* Track cell references */
- if (!HvTrackCellRef(&CellReferences, Hive, Kcb->KeyCell))
+ case KeyCachedInformation:
{
- /* Not enough memory to track references */
- Status = STATUS_INSUFFICIENT_RESOURCES;
+ /* Call the internal API */
+ Status = CmpQueryKeyDataFromCache(Kcb,
+ KeyInformation,
+ Length,
+ ResultLength);
+ break;
}
- else
+
+ case KeyFlagsInformation:
{
/* Call the internal API */
- Status = CmpQueryKeyData(Hive,
- Parent,
- KeyInformationClass,
- KeyInformation,
- Length,
- ResultLength);
+ Status = CmpQueryFlagsInformation(Kcb,
+ KeyInformation,
+ Length,
+ ResultLength);
+ break;
}
- break;
-
- case KeyCachedInformation:
- /* Call the internal API */
- Status = CmpQueryKeyDataFromCache(Kcb,
- KeyInformation,
- Length,
- ResultLength);
- break;
- case KeyFlagsInformation:
- /* Call the internal API */
- Status = CmpQueryFlagsInformation(Kcb,
- KeyInformation,
- Length,
- ResultLength);
- break;
-
- case KeyNameInformation:
- /* Call the internal API */
- Status = CmpQueryNameInformation(Kcb,
- KeyInformation,
- Length,
- ResultLength);
- break;
-
- /* Illegal classes */
- default:
+ case KeyNameInformation:
+ {
+ /* Call the internal API */
+ Status = CmpQueryNameInformation(Kcb,
+ KeyInformation,
+ Length,
+ ResultLength);
+ break;
+ }
- /* Print message and fail */
- DPRINT1("Unsupported class: %d!\n", KeyInformationClass);
- Status = STATUS_INVALID_INFO_CLASS;
- break;
+ /* Illegal classes */
+ default:
+ {
+ /* Print message and fail */
+ DPRINT1("Unsupported class: %d!\n", KeyInformationClass);
+ Status = STATUS_INVALID_INFO_CLASS;
+ break;
+ }
+ }
}
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Fail with exception code */
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(goto Quickie);
+ }
+ _SEH2_END;
Quickie:
/* Release references */
}
/* Open the target key */
-#if 0
- Status = ZwOpenKey(&KeyHandle, KEY_READ, TargetKey);
-#else
RtlZeroMemory(&ParseContext, sizeof(ParseContext));
ParseContext.CreateOperation = FALSE;
Status = ObOpenObjectByName(TargetKey,
KEY_READ,
&ParseContext,
&KeyHandle);
-#endif
if (!NT_SUCCESS(Status)) KeyHandle = NULL;
/* Open the hive */
}
/* Is this first profile load? */
- if (!(CmpProfileLoaded) && !(CmpWasSetupBoot))
+ if (!CmpProfileLoaded && !CmpWasSetupBoot)
{
/* User is now logged on, set quotas */
CmpProfileLoaded = TRUE;
return STATUS_INVALID_PARAMETER;
}
+ /* Mark this hive as being unloaded */
+ Hive->HiveFlags |= HIVE_IS_UNLOADING;
+
+ /* Search for any opened keys in this hive, and take an appropriate action */
+ if (Kcb->RefCount > 1)
+ {
+ if (Flags != REG_FORCE_UNLOAD)
+ {
+ if (CmCountOpenSubKeys(Kcb, FALSE) != 0)
+ {
+ /* There are open subkeys but we don't force hive unloading, fail */
+ Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
+ return STATUS_CANNOT_DELETE;
+ }
+ }
+ else
+ {
+ DPRINT1("CmUnloadKey: Force unloading is UNIMPLEMENTED, expect dangling KCBs problems!\n");
+ }
+ }
+
/* Flush the hive */
CmFlushKey(Kcb, TRUE);
{
DPRINT("CmpUnlinkHiveFromMaster() failed!\n");
- /* Remove the unloading flag */
+ /* Remove the unloading flag and return failure */
Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
-
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Destroy the view list */
CmpDestroyHiveViewList(CmHive);
- /* Free the hive storage */
- HvFree(Hive);
-
/* Delete the flusher lock */
ExDeleteResourceLite(CmHive->FlusherLock);
ExFreePoolWithTag(CmHive->FlusherLock, TAG_CMHIVE);
/* Delete the view lock */
ExFreePoolWithTag(CmHive->ViewLock, TAG_CMHIVE);
+ /* Free the hive storage */
+ HvFree(Hive);
+
/* Free the hive */
CmpFree(CmHive, TAG_CM);
static
NTSTATUS
-NTAPI
CmpDeepCopyKeyInternal(IN PHHIVE SourceHive,
IN HCELL_INDEX SrcKeyCell,
IN PHHIVE DestinationHive,
NTSTATUS Status;
PCM_KEY_NODE SrcNode;
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;
+
PAGED_CODE();
DPRINT("CmpDeepCopyKeyInternal(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X)\n",
/* Get the source cell node */
SrcNode = HvGetCell(SourceHive, SrcKeyCell);
+ ASSERT(SrcNode);
/* Sanity check */
ASSERT(SrcNode->Signature == CM_KEY_NODE_SIGNATURE);
/* Get the destination cell node */
DestNode = HvGetCell(DestinationHive, NewKeyCell);
+ ASSERT(DestNode);
- /* Set the parent */
+ /* Set the parent and copy the flags */
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!
- DestNode->Security = DestNode->Class = HCELL_NIL;
+ /* Copy the class cell */
+ 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 */
Status = CmpCopyKeyValueList(SourceHive,
DestinationHive,
&DestNode->ValueList,
StorageType);
- if (!NT_SUCCESS(Status)) goto Cleanup;
+ if (!NT_SUCCESS(Status))
+ goto Cleanup;
/* Clear the invalid subkey index */
DestNode->SubKeyCounts[Stable] = DestNode->SubKeyCounts[Volatile] = 0;
ASSERT(SubKey != HCELL_NIL);
/* Call the function recursively for the subkey */
+ //
+ // FIXME: Danger!! Kernel stack exhaustion!!
+ //
Status = CmpDeepCopyKeyInternal(SourceHive,
SubKey,
DestinationHive,
NewKeyCell,
StorageType,
&NewSubKey);
- if (!NT_SUCCESS(Status)) goto Cleanup;
+ if (!NT_SUCCESS(Status))
+ goto Cleanup;
/* Add the copy of the subkey to the new key */
if (!CmpAddSubKey(DestinationHive,
NewKeyCell,
NewSubKey))
{
+ /* Cleanup allocated cell */
+ HvFreeCell(DestinationHive, NewSubKey);
+
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
}
- /* Set the cell index if requested and return success */
- if (DestKeyCell) *DestKeyCell = NewKeyCell;
+ /* Set success */
Status = STATUS_SUCCESS;
Cleanup:
/* Release the cells */
- if (SrcNode) HvReleaseCell(SourceHive, SrcKeyCell);
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;
}