diff --git a/NTOSKRNL/CC/ccutil.cpp b/NTOSKRNL/CC/ccutil.cpp index 13f5a6e..8fc2edf 100644 --- a/NTOSKRNL/CC/ccutil.cpp +++ b/NTOSKRNL/CC/ccutil.cpp @@ -100,28 +100,160 @@ CcFindBitmapRangeToDirty( VOID NTAPI CcSetDirtyInMask( - _In_ PSHARED_CACHE_MAP SharedMap, + _In_ PSHARED_CACHE_MAP SharedCacheMap, _In_ PLARGE_INTEGER FileOffset, _In_ ULONG Length) { - NT_DBGBREAK("UNIMPLEMENTED\n"); + KLOCK_QUEUE_HANDLE LockHandle = {0}; + LARGE_INTEGER EndOffset = {0}; + ULONGLONG StartPage ={0}; + ULONGLONG EndPage = {0}; + ULONG CurrentPage = {0}; + PMBCB Mbcb = nullptr; + PBITMAP_RANGE BitmapRange = nullptr; + PULONG Bitmap = nullptr; + PULONG VacbLevel = nullptr; + ULONG BitMask = {0}; + + + + // Calculate start and end pages + StartPage = FileOffset->QuadPart >> PAGE_SHIFT; + EndOffset.QuadPart = FileOffset->QuadPart + Length; + EndPage = (EndOffset.QuadPart - 1) >> PAGE_SHIFT; + + for(;;) + { + if (SharedCacheMap->SectionSize.QuadPart > VACB_MAPPING_GRANULARITY) + { + if (!CcPrefillVacbLevelZone(1, &LockHandle, 0, 0, 0)) + return; + VacbLevel = CcAllocateVacbLevel(0); + KeLowerIrql(LockHandle.OldIrql); + } + + KeAcquireInStackQueuedSpinLock(&SharedCacheMap->BcbSpinLock, &LockHandle); + + Mbcb = SharedCacheMap->Mbcb; + if (Mbcb == nullptr) + { + Mbcb = CcAllocateInitializeBcb(); + if (Mbcb == nullptr) + goto ReleaseAndExit; + + Mbcb->NodeTypeCode = CACHE_NTC_BCB; + InitializeListHead(&Mbcb->BitmapRanges); + InsertHeadList(&Mbcb->BitmapRanges, &Mbcb->BitmapRange1.Links); + Mbcb->BitmapRange1.FirstDirtyPage = (ULONG)-1; + Mbcb->BitmapRange1.Bitmap = (PULONG)&Mbcb->BitmapRange2; + SharedCacheMap->Mbcb = Mbcb; + } + + if (EndPage < 512 || Mbcb->NodeTypeCode == 0x02F9) + { + BitmapRange = CcFindBitmapRangeToDirty(Mbcb, StartPage, &Bitmap); + if (BitmapRange == nullptr) + break; + + if (StartPage < BitmapRange->BasePage + BitmapRange->FirstDirtyPage) + BitmapRange->FirstDirtyPage = StartPage - BitmapRange->BasePage; + if (EndPage > BitmapRange->BasePage + BitmapRange->LastDirtyPage) + BitmapRange->LastDirtyPage = EndPage - BitmapRange->BasePage; + + if (SharedCacheMap->DirtyPages == 0) + { + CcScheduleLazyWriteScan(FALSE); + RemoveEntryList(&SharedCacheMap->SharedCacheMapLinks); + InsertTailList(&CcDirtySharedCacheMapList, &SharedCacheMap->SharedCacheMapLinks); + Mbcb->ResumeWritePage = StartPage; + } + + Bitmap = &BitmapRange->Bitmap[(StartPage - BitmapRange->BasePage) >> 5]; + BitMask = 1 << (StartPage & 0x1F); + + for (CurrentPage = StartPage; CurrentPage <= EndPage; CurrentPage++) + { + if ((*Bitmap & BitMask) == 0) + { + CcTotalDirtyPages++; + Mbcb->DirtyPages++; + BitmapRange->DirtyPages++; + SharedCacheMap->DirtyPages++; + *Bitmap |= BitMask; + } + BitMask <<= 1; + if (BitMask == 0) + { + Bitmap++; + BitMask = 1; + } + } + } + else + { + // Handle large files (>2MB) + if (Mbcb->BitmapRange1.DirtyPages) + { + RtlCopyMemory(VacbLevel, Mbcb->BitmapRange1.Bitmap, (2 * sizeof(BITMAP_RANGE))); + RtlZeroMemory(Mbcb->BitmapRange1.Bitmap, (2 * sizeof(BITMAP_RANGE))); + } + Mbcb->BitmapRange1.Bitmap = VacbLevel; + + // Initialize BitmapRange2 + InsertTailList(&Mbcb->BitmapRanges, &Mbcb->BitmapRange2.Links); + Mbcb->BitmapRange2.BasePage = (ULONGLONG)-1; + Mbcb->BitmapRange2.FirstDirtyPage = (ULONG)-1; + + // Initialize BitmapRange3 + InsertTailList(&Mbcb->BitmapRanges, &Mbcb->BitmapRange3.Links); + Mbcb->BitmapRange3.BasePage = (ULONGLONG)-1; + Mbcb->BitmapRange3.FirstDirtyPage = (ULONG)-1; + + VacbLevel = nullptr; + Mbcb->NodeTypeCode = 0x02F9; + + KeReleaseInStackQueuedSpinLock(&LockHandle); + continue; + } + + // Update ValidDataGoal if necessary + if (EndOffset.QuadPart > SharedCacheMap->ValidDataGoal.QuadPart) + { + SharedCacheMap->ValidDataGoal = EndOffset; + } + + break; + } + +ReleaseAndExit: + if (VacbLevel != nullptr) + { + *VacbLevel = (ULONG)CcVacbLevelFreeList; + CcVacbLevelEntries++; + CcVacbLevelFreeList = VacbLevel; + } + KeReleaseInStackQueuedSpinLock(&LockHandle); } BOOLEAN NTAPI CcMapAndCopy( - _In_ PSHARED_CACHE_MAP SharedMap, + _In_ PSHARED_CACHE_MAP SharedCacheMap, _In_ PVOID Buffer, _In_ PLARGE_INTEGER FileOffset, _In_ ULONG Length, - _In_ ULONG CopyFlags, + _In_ ULONG Flags, _In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER ValidDataLength, _In_ BOOLEAN Wait) -{ - NT_DBGBREAK("UNIMPLEMENTED\n"); +{ + NT_DBGBREAK("UNIMPLEMENTED\n"); } + + + + /* EXTERNAL API FUNCTIONS */ BOOLEAN @@ -132,22 +264,22 @@ CcCanIWrite( _In_ BOOLEAN Wait, _In_ UCHAR Retrying) { - PFSRTL_COMMON_FCB_HEADER FsContext; - PSHARED_CACHE_MAP SharedCacheMap; - DEFERRED_WRITE DeferredWrite; - KEVENT Event; - ULONG WriteSize; - ULONG Pages; - KIRQL OldIrql; - BOOLEAN IsSmallThreshold = FALSE; + PFSRTL_COMMON_FCB_HEADER FsContext = nullptr; + PSHARED_CACHE_MAP SharedCacheMap = nullptr; + DEFERRED_WRITE DeferredWrite = {0}; + KEVENT Event = {0}; + ULONG WriteSize = {0}; + ULONG Pages = {0}; + KIRQL OldIrql = {0}; + BOOLEAN IsSmallThreshold = false; /* Quick checks for immediate return */ if (FileObject->Flags & FO_WRITE_THROUGH) - return TRUE; + return true; if (IoIsFileOriginRemote(FileObject) && Retrying < 0xFD) - return TRUE; + return true; /* Calculate size and pages */ WriteSize = min(BytesToWrite, 0x40000); @@ -172,7 +304,7 @@ CcCanIWrite( { if (SharedCacheMap->DirtyPageThreshold < (SharedCacheMap->DirtyPages + Pages)) { - IsSmallThreshold = TRUE; + IsSmallThreshold = true; } } } @@ -192,7 +324,7 @@ CcCanIWrite( MmAvailablePages > MmThrottleBottom && !IsSmallThreshold)) { - return TRUE; + return true; } } @@ -207,7 +339,7 @@ CcCanIWrite( KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); } - KeInitializeEvent(&Event, NotificationEvent, FALSE); + KeInitializeEvent(&Event, NotificationEvent, false); DeferredWrite.NodeTypeCode = NODE_TYPE_DEFERRED_WRITE; DeferredWrite.NodeByteSize = sizeof(DEFERRED_WRITE); @@ -238,7 +370,7 @@ CcCanIWrite( } while (KeWaitForSingleObject(&Event, Executive, KernelMode, - FALSE, + false, &CcIdleDelay) != STATUS_SUCCESS); return TRUE;