diff --git a/NTOSKRNL/CC/ccloghandler.cpp b/NTOSKRNL/CC/ccloghandler.cpp index 975b641..5af923e 100644 --- a/NTOSKRNL/CC/ccloghandler.cpp +++ b/NTOSKRNL/CC/ccloghandler.cpp @@ -58,7 +58,8 @@ CcGetDirtyPages(IN PVOID LogHandle, FileObject = CcReferenceSharedCacheMapFileObject(SharedCacheMap); /* Acquire the BCB Lock */ - oldIrql = ExAcquireSpinLockShared (&SharedCacheMap->BcbSpinLock); + KLOCK_QUEUE_HANDLE LockHandle; + KeAcquireInStackQueuedSpinLock(&SharedCacheMap->BcbLock, &LockHandle); /* Iterate over BCB List */ for (auto it = ListEntryIterator::begin(&SharedCacheMap->BcbList); it != ListEntryIterator::end(&SharedCacheMap->BcbList); ++it) @@ -75,7 +76,7 @@ CcGetDirtyPages(IN PVOID LogHandle, Bcb->PinCount++; /*Release the BCB lock temporarily for the callback*/ - ExReleaseSpinLockShared (&SharedCacheMap->BcbSpinLock,oldIrql); + KeReleaseInStackQueuedSpinLock(&LockHandle); /*Unpin any previously pinned BCB*/ if (BcbToUnpin) @@ -99,7 +100,7 @@ CcGetDirtyPages(IN PVOID LogHandle, } // Reacquire the BCB lock - oldIrql = ExAcquireSpinLockShared (&SharedCacheMap->BcbSpinLock); + KeAcquireInStackQueuedSpinLock(&SharedCacheMap->BcbLock, &LockHandle); // Decrement the PinCount or mark for unpinning if (Bcb->PinCount > 1) { @@ -114,7 +115,7 @@ CcGetDirtyPages(IN PVOID LogHandle, } /*Release the BCB lock*/ - ExReleaseSpinLockShared (&SharedCacheMap->BcbSpinLock,oldIrql); + KeReleaseInStackQueuedSpinLock(&LockHandle); /* Dereference the shared cache map file object*/ CcDereferenceSharedCacheMapFileObject(SharedCacheMap, FileObject); @@ -143,7 +144,57 @@ NTAPI CcGetLsnForFileObject(IN PFILE_OBJECT FileObject, OUT OPTIONAL PLARGE_INTEGER OldestLsn) { - /* IMPLEMENTATION INCOMPLETE*/ + PSHARED_CACHE_MAP SharedCacheMap = nullptr; + PMBCB Bcb = nullptr; + KLOCK_QUEUE_HANDLE LockHandle; + LARGE_INTEGER OldestLsnValue = {0}; + LARGE_INTEGER Result = {0}; + BITMAP_RANGE OldRangeBasePage = {0}; + + if (OldestLsn) + { + OldestLsn->QuadPart = 0; + } + SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; + if (!SharedCacheMap || !SharedCacheMap->BcbList.Flink) { + return 0; + } + + /* Acquire the spin lock*/ + KeAcquireInStackQueuedSpinLock(&SharedCacheMap->BcbLock, &LockHandle); + for(auto it = ListEntryIterator::begin(&SharedCacheMap->BcbList); it != ListEntryIterator::end(&SharedCacheMap->BcbList); ++it) + { + Bcb = CONTAINING_RECORD(*it, _MBCB, BitmapRange1); + + if (Bcb->NodeTypeCode == NODE_TYPE_CODE_BCB && Bcb->NodeIsInZone) + { + auto MostRecentlyDirtiedPage = Bcb->MostRecentlyDirtiedPage.QuadPart; + + if (MostRecentlyDirtiedPage && (!OldestLsnValue.QuadPart || MostRecentlyDirtiedPage < OldestLsnValue.QuadPart)) + { + OldestLsnValue = MostRecentlyDirtiedPage; + } + + if(Bcb->BitmapRange1.BasePage > OldRangeBasePage.BasePage) + { + OldRangeBasePage = Bcb->BitmapRange1; + } + } + } + } + + + KeReleaseInStackQueuedSpinLock(&LockHandle); + + /* Set the OldestLsn value if requested*/ + if (OldestLsn) + { + OldestLsn->QuadPart = OldestLsnValue; + } + + Result.QuadPart = OldRangeBasePage.BasePage; + + return Result; }