mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-28 19:26:16 +00:00
[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:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -265,6 +265,14 @@ HvSyncHive(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
CMAPI
|
||||
HvHiveWillShrink(IN PHHIVE RegistryHive)
|
||||
{
|
||||
/* No shrinking yet */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN CMAPI
|
||||
HvWriteHive(
|
||||
PHHIVE RegistryHive)
|
||||
|
||||
+1021
-709
File diff suppressed because it is too large
Load Diff
@@ -14,4 +14,11 @@
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CmpAddToHiveFileList(IN PCMHIVE Hive)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user