mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[NTOS:CM] Implement more support for force-unloading registry hives.
CORE-13448 CORE-10705
This commit is contained in:
parent
16752875db
commit
d61c00c252
3 changed files with 64 additions and 12 deletions
|
@ -2221,7 +2221,7 @@ CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
|||
{
|
||||
if (Flags != REG_FORCE_UNLOAD)
|
||||
{
|
||||
if (CmCountOpenSubKeys(Kcb, FALSE) != 0)
|
||||
if (CmpEnumerateOpenSubKeys(Kcb, FALSE, FALSE) != 0)
|
||||
{
|
||||
/* There are open subkeys but we don't force hive unloading, fail */
|
||||
Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
|
||||
|
@ -2230,7 +2230,13 @@ CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
|||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("CmUnloadKey: Force unloading is UNIMPLEMENTED, expect dangling KCBs problems!\n");
|
||||
DPRINT1("CmUnloadKey: Force unloading is HALF-IMPLEMENTED, expect dangling KCBs problems!\n");
|
||||
if (CmpEnumerateOpenSubKeys(Kcb, TRUE, TRUE) != 0)
|
||||
{
|
||||
/* There are open subkeys that we cannot force to unload, fail */
|
||||
Hive->HiveFlags &= ~HIVE_IS_UNLOADING;
|
||||
return STATUS_CANNOT_DELETE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2247,6 +2253,10 @@ CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* Flush any notifications if we force hive unloading */
|
||||
if (Flags == REG_FORCE_UNLOAD)
|
||||
CmpFlushNotifiesOnKeyBodyList(Kcb, TRUE); // Lock is already held
|
||||
|
||||
/* Clean up information we have on the subkey */
|
||||
CmpCleanUpSubKeyInfo(Kcb->ParentKcb);
|
||||
|
||||
|
@ -2272,6 +2282,10 @@ CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
|||
/* Remove the hive from the hive file list */
|
||||
CmpRemoveFromHiveFileList(CmHive);
|
||||
|
||||
/**
|
||||
** NOTE:
|
||||
** The following code is mostly equivalent to what we "call" CmpDestroyHive()
|
||||
**/
|
||||
/* Destroy the security descriptor cache */
|
||||
CmpDestroySecurityCache(CmHive);
|
||||
|
||||
|
@ -2296,8 +2310,10 @@ CmUnloadKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
|
|||
|
||||
ULONG
|
||||
NTAPI
|
||||
CmCountOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb,
|
||||
IN BOOLEAN RemoveEmptyCacheEntries)
|
||||
CmpEnumerateOpenSubKeys(
|
||||
IN PCM_KEY_CONTROL_BLOCK RootKcb,
|
||||
IN BOOLEAN RemoveEmptyCacheEntries,
|
||||
IN BOOLEAN DereferenceOpenedEntries)
|
||||
{
|
||||
PCM_KEY_HASH Entry;
|
||||
PCM_KEY_CONTROL_BLOCK CachedKcb;
|
||||
|
@ -2306,9 +2322,9 @@ CmCountOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb,
|
|||
ULONG i, j;
|
||||
ULONG SubKeys = 0;
|
||||
|
||||
DPRINT("CmCountOpenSubKeys() called\n");
|
||||
DPRINT("CmpEnumerateOpenSubKeys() called\n");
|
||||
|
||||
/* The root key is the only referenced key. There are no refereced sub keys. */
|
||||
/* The root key is the only referenced key. There are no referenced sub keys. */
|
||||
if (RootKcb->RefCount == 1)
|
||||
{
|
||||
DPRINT("Open sub keys: 0\n");
|
||||
|
@ -2347,10 +2363,43 @@ CmCountOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb,
|
|||
|
||||
if (CachedKcb->RefCount > 0)
|
||||
{
|
||||
DPRINT1("Found a sub key pointing to '%.*s', RefCount = %u\n",
|
||||
CachedKcb->NameBlock->NameLength, CachedKcb->NameBlock->Name,
|
||||
CachedKcb->RefCount);
|
||||
|
||||
/* If we dereference opened KCBs, don't touch read-only keys */
|
||||
if (DereferenceOpenedEntries &&
|
||||
!(CachedKcb->ExtFlags & CM_KCB_READ_ONLY_KEY))
|
||||
{
|
||||
/* Registry needs to be locked down */
|
||||
CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK();
|
||||
|
||||
/* Flush any notifications */
|
||||
CmpFlushNotifiesOnKeyBodyList(CachedKcb, TRUE); // Lock is already held
|
||||
|
||||
/* Clean up information we have on the subkey */
|
||||
CmpCleanUpSubKeyInfo(CachedKcb->ParentKcb);
|
||||
|
||||
/* Get and cache the next cache entry */
|
||||
// Entry = Entry->NextHash;
|
||||
Entry = CachedKcb->NextHash;
|
||||
|
||||
/* Set the KCB in delete mode and remove it */
|
||||
CachedKcb->Delete = TRUE;
|
||||
CmpRemoveKeyControlBlock(CachedKcb);
|
||||
|
||||
/* Clear the cell */
|
||||
CachedKcb->KeyCell = HCELL_NIL;
|
||||
|
||||
/* Restart with the next cache entry */
|
||||
continue;
|
||||
}
|
||||
/* Else, the key cannot be dereferenced, and we count it as in use */
|
||||
|
||||
/* Count the current hash entry if it is in use */
|
||||
SubKeys++;
|
||||
}
|
||||
else if ((CachedKcb->RefCount == 0) && (RemoveEmptyCacheEntries != FALSE))
|
||||
else if ((CachedKcb->RefCount == 0) && RemoveEmptyCacheEntries)
|
||||
{
|
||||
/* Remove the current key from the delayed close list */
|
||||
CmpRemoveFromDelayedClose(CachedKcb);
|
||||
|
@ -2370,7 +2419,9 @@ CmCountOpenSubKeys(IN PCM_KEY_CONTROL_BLOCK RootKcb,
|
|||
}
|
||||
}
|
||||
|
||||
DPRINT("Open sub keys: %u\n", SubKeys);
|
||||
if (SubKeys > 0)
|
||||
DPRINT1("Open sub keys: %u\n", SubKeys);
|
||||
|
||||
return SubKeys;
|
||||
}
|
||||
|
||||
|
|
|
@ -1542,8 +1542,8 @@ NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey,
|
|||
}
|
||||
|
||||
/* Call the internal API */
|
||||
*HandleCount = CmCountOpenSubKeys(KeyBody->KeyControlBlock,
|
||||
FALSE);
|
||||
*HandleCount = CmpEnumerateOpenSubKeys(KeyBody->KeyControlBlock,
|
||||
FALSE, FALSE);
|
||||
|
||||
/* Unlock the registry */
|
||||
CmpUnlockRegistry();
|
||||
|
|
|
@ -1357,9 +1357,10 @@ CmUnloadKey(
|
|||
|
||||
ULONG
|
||||
NTAPI
|
||||
CmCountOpenSubKeys(
|
||||
CmpEnumerateOpenSubKeys(
|
||||
IN PCM_KEY_CONTROL_BLOCK RootKcb,
|
||||
IN BOOLEAN RemoveEmptyCacheEntries
|
||||
IN BOOLEAN RemoveEmptyCacheEntries,
|
||||
IN BOOLEAN DereferenceOpenedEntries
|
||||
);
|
||||
|
||||
HCELL_INDEX
|
||||
|
|
Loading…
Reference in a new issue