/* * PROJECT: Alcyone System Kernel * LICENSE: BSD Clause 3 * PURPOSE: Cache Controllerm, Cache Utility Handler. * NT KERNEL: 5.11.9360 * COPYRIGHT: 2023-2029 Dibymartanda Samanta <> */ class BitmapRangeManager { private: static constexpr LONGLONG CalculateBasePage(LONGLONG InputPage) { return (InputPage & ~(0x1000 - 1)); } public: static PBITMAP_RANGE FindBitmapRangeToDirty(PMBCB Mbcb, LONGLONG InputPage, PULONG* pBitmap) { PBITMAP_RANGE CurrentRange = nullptr; PBITMAP_RANGE NewRange = nullptr; PLIST_ENTRY HeadList = nullptr; LONGLONG BasePage = {0}; HeadList = &Mbcb->BitmapRanges; BasePage = CalculateBasePage(InputPage); CurrentRange = CONTAINING_RECORD(Mbcb->BitmapRanges.Flink, BITMAP_RANGE, Links); while(true){ if (BasePage == CurrentRange->BasePage) return CurrentRange; if (CurrentRange->DirtyPages || NewRange) { if (BasePage > CurrentRange->BasePage) HeadList = &CurrentRange->Links; } else { NewRange = CurrentRange; } if (CurrentRange->Links.Flink == &Mbcb->BitmapRanges) break; CurrentRange = CONTAINING_RECORD(CurrentRange->Links.Flink, BITMAP_RANGE, Links); if (CurrentRange->BasePage > BasePage && NewRange) break; } if (NewRange) { RemoveEntryList(&NewRange->Links); } else { NewRange = reinterpret_cast(ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewRange), 'rBcC')); if (!NewRange) { return nullptr; } RtlZeroMemory(NewRange, sizeof(*NewRange)); } InsertHeadList(HeadList, &NewRange->Links); NewRange->BasePage = BasePage; NewRange->FirstDirtyPage = 0xFFFFFFFF; NewRange->LastDirtyPage = 0; if (!NewRange->Bitmap) { NewRange->Bitmap = *pBitmap; *pBitmap = nullptr; } return NewRange; } }; /* Internal Functions */ LONG CcCopyReadExceptionFilter( _In_ PEXCEPTION_POINTERS ExceptionInfo, _Out_ NTSTATUS* OutStatus) { NT_ASSERT(!NT_SUCCESS(*OutStatus)); return EXCEPTION_EXECUTE_HANDLER; } PBITMAP_RANGE NTAPI CcFindBitmapRangeToDirty( _In_ PMBCB Mbcb, _In_ LONGLONG InputPage, _Inout_ PULONG* PBITMAP) { return BitmapRangeManager::FindBitmapRangeToDirty(Mbcb, InputPage, pBitmap); } VOID NTAPI CcSetDirtyInMask( _In_ PSHARED_CACHE_MAP SharedMap, _In_ PLARGE_INTEGER FileOffset, _In_ ULONG Length) { NT_DBGBREAK("UNIMPLEMENTED\n"); } BOOLEAN NTAPI CcMapAndCopy( _In_ PSHARED_CACHE_MAP SharedMap, _In_ PVOID Buffer, _In_ PLARGE_INTEGER FileOffset, _In_ ULONG Length, _In_ ULONG CopyFlags, _In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER ValidDataLength, _In_ BOOLEAN Wait) { NT_DBGBREAK("UNIMPLEMENTED\n"); } /* EXTERNAL API FUNCTIONS */ BOOLEAN NTAPI CcCanIWrite( _In_ PFILE_OBJECT FileObject, _In_ ULONG BytesToWrite, _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; /* Quick checks for immediate return */ if (FileObject->Flags & FO_WRITE_THROUGH) return TRUE; if (IoIsFileOriginRemote(FileObject) && Retrying < 0xFD) return TRUE; /* Calculate size and pages */ WriteSize = min(BytesToWrite, 0x40000); Pages = ROUND_UP(WriteSize, PAGE_SIZE) / PAGE_SIZE; FsContext = FileObject->FsContext; /* Check threshold conditions */ if (Retrying >= 0xFE || (FsContext->Flags & FSRTL_FLAG_LIMIT_MODIFIED_PAGES)) { if (Retrying != 0xFF) { OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); } if (FileObject->SectionObjectPointer) { SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap; if (SharedCacheMap && SharedCacheMap->DirtyPageThreshold && SharedCacheMap->DirtyPages) { if (SharedCacheMap->DirtyPageThreshold < (SharedCacheMap->DirtyPages + Pages)) { IsSmallThreshold = TRUE; } } } if (Retrying != 0xFF) { KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); } } /* Check if we can write immediately */ if ((Retrying || IsListEmpty(&CcDeferredWrites)) && (CcDirtyPageThreshold > (CcTotalDirtyPages + Pages))) { if ((MmAvailablePages > MmThrottleTop && !IsSmallThreshold) || (MmModifiedPageListHead.Total < 1000 && MmAvailablePages > MmThrottleBottom && !IsSmallThreshold)) { return TRUE; } } if (!Wait) return FALSE; /* Initialize deferred write */ if (IsListEmpty(&CcDeferredWrites)) { OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); CcScheduleLazyWriteScan(TRUE); KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); } KeInitializeEvent(&Event, NotificationEvent, FALSE); DeferredWrite.NodeTypeCode = NODE_TYPE_DEFERRED_WRITE; DeferredWrite.NodeByteSize = sizeof(DEFERRED_WRITE); DeferredWrite.FileObject = FileObject; DeferredWrite.BytesToWrite = BytesToWrite; DeferredWrite.Event = &Event; DeferredWrite.LimitModifiedPages = (FsContext->Flags & FSRTL_FLAG_LIMIT_MODIFIED_PAGES) != 0; /* Insert into deferred writes list */ /* Insert into deferred writes list */ if (Retrying) { ExInterlockedInsertHeadList(&CcDeferredWrites, &DeferredWrite.DeferredWriteLinks, &CcDeferredWriteSpinLock); } else { ExInterlockedInsertTailList(&CcDeferredWrites, &DeferredWrite.DeferredWriteLinks, &CcDeferredWriteSpinLock); } /* Wait for the write to complete */ do { CcPostDeferredWrites(); } while (KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &CcIdleDelay) != STATUS_SUCCESS); return TRUE; } BOOLEAN NTAPI CcCopyRead( _In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER FileOffset, _In_ ULONG Length, _In_ BOOLEAN Wait, _Out_ PVOID Buffer, _Out_ IO_STATUS_BLOCK* OutIoStatus) { NT_DBGBREAK("UNIMPLEMENTED\n"); } BOOLEAN NTAPI CcCopyWrite( _In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER FileOffset, _In_ ULONG Length, _In_ BOOLEAN Wait, _In_ PVOID Buffer) { NT_DBGBREAK("UNIMPLEMENTED\n"); } VOID CcDeferWrite( _In_ PFILE_OBJECT FileObject, _In_ PCC_POST_DEFERRED_WRITE PostRoutine, _In_ PVOID Context1, _In_ PVOID Context2, _In_ ULONG BytesToWrite, _In_ BOOLEAN Retrying ) { KIRQL OldIrql; PDEFERRED_WRITE DeferredWrite = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(DEFERRED_WRITE), 'wDcC'); if (DeferredWrite != nullptr) { RtlZeroMemory(DeferredWrite, sizeof(DEFERRED_WRITE)); DeferredWrite->NodeTypeCode = NODE_TYPE_DEFERRED_WRITE; DeferredWrite->NodeByteSize = sizeof(DEFERRED_WRITE); DeferredWrite->FileObject = FileObject; DeferredWrite->BytesToWrite = BytesToWrite; DeferredWrite->PostRoutine = PostRoutine; DeferredWrite->Context1 = Context1; DeferredWrite->Context2 = Context2; if (Retrying) ExInterlockedInsertHeadList(&CcDeferredWrites, &DeferredWrite->DeferredWriteLinks, &CcDeferredWriteSpinLock); else ExInterlockedInsertTailList(&CcDeferredWrites, &DeferredWrite->DeferredWriteLinks, &CcDeferredWriteSpinLock); CcPostDeferredWrites(); OldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); CcScheduleLazyWriteScan(TRUE); KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql); } else { PostRoutine(Context1, Context2); } } VOID NTAPI CcFastCopyRead( _In_ PFILE_OBJECT FileObject, _In_ ULONG FileOffset, _In_ ULONG Length, _In_ ULONG PageCount, _Out_ PVOID Buffer, _Out_ PIO_STATUS_BLOCK IoStatus) { NT_DBGBREAK("UNIMPLEMENTED\n"); } VOID NTAPI CcFastCopyWrite( _In_ PFILE_OBJECT FileObject, _In_ ULONG FileOffset, _In_ ULONG Length, _In_ PVOID InBuffer) { NT_DBGBREAK("UNIMPLEMENTED\n"); }