[NTOSKRNL/CONFIG]

- Flusher lock fixes: wrong kind of lock,total mess (and the wrong kind of lock). Properly fixed throughout cmapi.c, but still missing in many other places.
- Add support for detecting loading of an already loaded hive.
- Start adding calls to CmpReportNotify to support registry callbacks.
- Do work needed to flush notifications for a deleted node (but CmpFlushNotify not yet implemented).
- Add support for adding each newly loaded hive to the HiveList key in the registry (but CmpAddHiveToFileList not yet implemented).
- Add some ViewLock acquire/releases where needed.
- Load the key in a faster way (Ob vs Zw)
- Add checks everywhere for HvMarkCellDirty success. In future (when log/backup file is enabled), it can return FALSE (e.g. when we are out of space).
- Change logic in CmpDoFlushAll to only flush a hive if it won't shrink (in the future, flushing may lead to hive shrinkage for efficiency).
- Add SEH2 protection to all CmApis that may deal with user-mode data.
- Add HvTrackCellRef/HvReleaseCellRef for tracking cell references in scenarios where we might need many GetCell/ReleaseCell calls. For now stubbed to only work with up to 4 static references.
- Properly unlock/free in some failure paths in some of the CM APIs.
- Add some missing HvReleaseCell in paths where it was missing.
- Try to fix hack in enumerate key.
- Fix wrong usage of KeQuerySystemTime. It was called twice to save it in 2 different places. Instead, there should be only one call, and then duplicate the value across.
- Fix logic in CmpSetValueExistingData/Key.

Tested with winetests and .NET framework 1.1 installation which fully completes.

svn path=/trunk/; revision=46702
This commit is contained in:
Aleksey Bragin
2010-04-03 20:22:32 +00:00
parent eb82a3b915
commit 71d61c9c59
8 changed files with 1187 additions and 736 deletions
+37
View File
@@ -198,6 +198,22 @@ typedef struct _CMHIVE
#endif
typedef struct _HV_HIVE_CELL_PAIR
{
PHHIVE Hive;
HCELL_INDEX Cell;
} HV_HIVE_CELL_PAIR, *PHV_HIVE_CELL_PAIR;
#define STATIC_CELL_PAIR_COUNT 4
typedef struct _HV_TRACK_CELL_REF
{
USHORT Count;
USHORT Max;
PHV_HIVE_CELL_PAIR CellArray;
HV_HIVE_CELL_PAIR StaticArray[STATIC_CELL_PAIR_COUNT];
USHORT StaticCount;
} HV_TRACK_CELL_REF, *PHV_TRACK_CELL_REF;
extern ULONG CmlibTraceLevel;
/*
@@ -272,6 +288,12 @@ HvIsCellDirty(
IN HCELL_INDEX Cell
);
BOOLEAN
CMAPI
HvHiveWillShrink(
IN PHHIVE RegistryHive
);
BOOLEAN CMAPI
HvSyncHive(
PHHIVE RegistryHive);
@@ -288,6 +310,21 @@ CmCreateRootNode(
VOID CMAPI
CmPrepareHive(
PHHIVE RegistryHive);
BOOLEAN
CMAPI
HvTrackCellRef(
PHV_TRACK_CELL_REF CellRef,
PHHIVE Hive,
HCELL_INDEX Cell
);
VOID
CMAPI
HvReleaseFreeCellRefArray(
PHV_TRACK_CELL_REF CellRef
);
/*
* Private functions.
+54 -1
View File
@@ -113,7 +113,7 @@ HvMarkCellDirty(
__FUNCTION__, RegistryHive, CellIndex, HoldingLock);
if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != Stable)
return FALSE;
return TRUE;
CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
CellLastBlock = ((CellIndex + HV_BLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
@@ -525,3 +525,56 @@ HvFreeCell(
if (CellType == Stable)
HvMarkCellDirty(RegistryHive, CellIndex, FALSE);
}
BOOLEAN
CMAPI
HvTrackCellRef(PHV_TRACK_CELL_REF CellRef,
PHHIVE Hive,
HCELL_INDEX Cell)
{
/* Sanity checks */
ASSERT(CellRef);
ASSERT(Hive );
ASSERT(Cell != HCELL_NIL);
/* Less than 4? */
if (CellRef->StaticCount < STATIC_CELL_PAIR_COUNT)
{
/* Add reference */
CellRef->StaticArray[CellRef->StaticCount].Hive = Hive;
CellRef->StaticArray[CellRef->StaticCount].Cell = Cell;
CellRef->StaticCount++;
return TRUE;
}
/* FIXME: TODO */
DPRINT1("ERROR: Too many references\n");
while (TRUE);
return FALSE;
}
VOID
CMAPI
HvReleaseFreeCellRefArray(PHV_TRACK_CELL_REF CellRef)
{
ULONG i;
ASSERT(CellRef);
/* Any references? */
if (CellRef->StaticCount > 0)
{
/* Sanity check */
ASSERT(CellRef->StaticCount <= STATIC_CELL_PAIR_COUNT);
/* Loop them */
for (i = 0; i < CellRef->StaticCount;i++)
{
/* Release them */
HvReleaseCell(CellRef->StaticArray[i].Hive,
CellRef->StaticArray[i].Cell);
}
/* Free again */
CellRef->StaticCount = 0;
}
}
+8
View File
@@ -265,6 +265,14 @@ HvSyncHive(
return TRUE;
}
BOOLEAN
CMAPI
HvHiveWillShrink(IN PHHIVE RegistryHive)
{
/* No shrinking yet */
return FALSE;
}
BOOLEAN CMAPI
HvWriteHive(
PHHIVE RegistryHive)
File diff suppressed because it is too large Load Diff
+7
View File
@@ -14,4 +14,11 @@
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
CmpAddToHiveFileList(IN PCMHIVE Hive)
{
return STATUS_SUCCESS;
}
/* EOF */
+1 -7
View File
@@ -119,12 +119,10 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
if (!Hive->ViewLock) return STATUS_INSUFFICIENT_RESOURCES;
/* Allocate the flush lock */
#if 0
Hive->FlusherLock = ExAllocatePoolWithTag(NonPagedPool,
sizeof(ERESOURCE),
TAG_CM);
if (!Hive->FlusherLock) return STATUS_INSUFFICIENT_RESOURCES;
#endif
/* Setup the handles */
Hive->FileHandles[HFILE_TYPE_PRIMARY] = Primary;
@@ -136,7 +134,7 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
Hive->ViewLockOwner = NULL;
/* Initialize the flush lock */
ExInitializePushLock((PULONG_PTR)&Hive->FlusherLock);
ExInitializeResourceLite(Hive->FlusherLock);
/* Setup hive locks */
ExInitializePushLock((PULONG_PTR)&Hive->HiveLock);
@@ -193,9 +191,7 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
{
/* Clear allocations and fail */
ExFreePool(Hive->ViewLock);
#if 0
ExFreePool(Hive->FlusherLock);
#endif
ExFreePool(Hive);
return Status;
}
@@ -211,9 +207,7 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
{
/* Free all alocations */
ExFreePool(Hive->ViewLock);
#if 0
ExFreePool(Hive->FlusherLock);
#endif
ExFreePool(Hive);
return STATUS_REGISTRY_CORRUPT;
}
+59
View File
@@ -1135,3 +1135,62 @@ DelistKeyBodyFromKCB(IN PCM_KEY_BODY KeyBody,
/* Unlock it it if we did a manual lock */
if (!LockHeld) CmpReleaseKcbLock(KeyBody->KeyControlBlock);
}
VOID
NTAPI
CmpFlushNotifiesOnKeyBodyList(IN PCM_KEY_CONTROL_BLOCK Kcb,
IN BOOLEAN LockHeld)
{
PLIST_ENTRY NextEntry, ListHead;
PCM_KEY_BODY KeyBody;
/* Sanity check */
LockHeld ? CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() : CmpIsKcbLockedExclusive(Kcb);
while (TRUE)
{
/* Is the list empty? */
ListHead = &Kcb->KeyBodyListHead;
if (!IsListEmpty(ListHead))
{
/* Loop the list */
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the key body */
KeyBody = CONTAINING_RECORD(NextEntry, CM_KEY_BODY, KeyBodyList);
ASSERT(KeyBody->Type == '20yk');
/* Check for notifications */
if (KeyBody->NotifyBlock)
{
/* Is the lock held? */
if (LockHeld)
{
/* Flush it */
CmpFlushNotify(KeyBody, LockHeld);
ASSERT(KeyBody->NotifyBlock == NULL);
continue;
}
/* Lock isn't held, so we need to take a reference */
if (ObReferenceObjectSafe(KeyBody))
{
/* Now we can flush */
CmpFlushNotify(KeyBody, LockHeld);
ASSERT(KeyBody->NotifyBlock == NULL);
/* Release the reference we took */
ObDereferenceObjectDeferDelete(KeyBody);
continue;
}
}
/* Try the next entry */
NextEntry = NextEntry->Flink;
}
}
/* List has been parsed, exit */
break;
}
}
-19
View File
@@ -414,15 +414,6 @@ CmpDoCreate(IN PHHIVE Hive,
LARGE_INTEGER TimeStamp;
PCM_KEY_NODE KeyNode;
/* Sanity check */
#if 0
ASSERT((CmpIsKcbLockedExclusive(ParentKcb) == TRUE) ||
(CmpTestRegistryLockExclusive() == TRUE));
#endif
/* Acquire the flusher lock */
ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock);
/* Check if the parent is being deleted */
if (ParentKcb->Delete)
{
@@ -555,7 +546,6 @@ CmpDoCreate(IN PHHIVE Hive,
Exit:
/* Release the flusher lock and return status */
ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
return Status;
}
@@ -747,9 +737,6 @@ CmpCreateLinkNode(IN PHHIVE Hive,
LARGE_INTEGER TimeStamp;
PCM_KEY_NODE KeyNode;
PCM_KEY_CONTROL_BLOCK Kcb = ParentKcb;
#if 0
CMP_ASSERT_REGISTRY_LOCK();
#endif
/* Link nodes only allowed on the master */
if (Hive != &CmiVolatileHive->Hive)
@@ -759,10 +746,6 @@ CmpCreateLinkNode(IN PHHIVE Hive,
return STATUS_ACCESS_DENIED;
}
/* Acquire the flusher locks */
ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock);
ExAcquirePushLockShared((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock);
/* Check if the parent is being deleted */
if (ParentKcb->Delete)
{
@@ -964,8 +947,6 @@ CmpCreateLinkNode(IN PHHIVE Hive,
Exit:
/* Release the flusher locks and return status */
ExReleasePushLock((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock);
ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
return Status;
}