diff --git a/NTOSKRNL/CC/ccpinsupport.cpp b/NTOSKRNL/CC/ccpinsupport.cpp index 27d1c37..49072ba 100644 --- a/NTOSKRNL/CC/ccpinsupport.cpp +++ b/NTOSKRNL/CC/ccpinsupport.cpp @@ -185,7 +185,286 @@ CcPinFileData( _Out_ PVOID* Buffer, _Out_ LARGE_INTEGER* BeyondLastByte) { - // Unimplemented + + KLOCK_QUEUE_HANDLE LockHandle ={0}; + PSHARED_CACHE_MAP SharedMap = nullptr; + PVACB Vacb = nullptr; + PCC_BCB Bcb = nullptr; + LARGE_INTEGER EndFileOffset ={0}; + LARGE_INTEGER offset = {0}; + LARGE_INTEGER length = {0}; + ULONG ActivePage = {0}; + ULONG ReceivedLength ={0}; + ULONG MapFlags = {0}; + BOOLEAN IsLocked = false; + BOOLEAN IsVacbLocked = false; + BOOLEAN Result = false; + + + SharedMap = FileObject->SectionObjectPointer->SharedCacheMap; + + CcGetActiveVacb(SharedMap, &Vacb, &ActivePage, &IsVacbLocked); + + if (Vacb || SharedMap->NeedToZero) + { + CcFreeActiveVacb(SharedMap, Vacb, ActivePage, IsVacbLocked); + Vacb = nullptr; + } + + *Bcb = nullptr; + *Buffer = nullptr; + + if (PinFlags & PIN_NO_READ) + { + ReceivedLength = PAGE_SIZE - (FileOffset->LowPart & (PAGE_SIZE - 1)); + CcReferenceFileOffset(SharedMap, *FileOffset); + } + else + { + *Buffer = CcGetVirtualAddress(SharedMap, *FileOffset, &Vacb, &ReceivedLength); + } + + KeAcquireInStackQueuedSpinLock(&SharedMap->BcbSpinLock, &LockHandle); + IsLocked = true; + + _try{ + + EndFileOffset.QuadPart = (FileOffset->QuadPart + Length); + + if (CcFindBcb(SharedMap, FileOffset, &EndFileOffset, &Bcb)) + { + if (!(SharedMap->Flags & SHARE_FL_MODIFIED_NO_WRITE)) + IsNoWrite = true; + + if (Bcb->BaseAddress) + { + if (PinFlags & PIN_WAIT) + { + Bcb->PinCount++; + KeReleaseInStackQueuedSpinLock(&LockHandle); + IsLocked = false; + + if (!IsNoWrite) + { + if (PinFlags & PIN_EXCLUSIVE) + ExAcquireResourceExclusiveLite(&Bcb->BcbResource, true); + else + ExAcquireSharedStarveExclusive(&Bcb->BcbResource, true); + } + } + if (!(PinFlags & PIN_WAIT)) + { + if (!IsNoWrite && !ExAcquireSharedStarveExclusive(&Bcb->BcbResource, false)) + { + Bcb = nullptr; + Result = false; + goto finish; + } + InterlockedIncrement(&Bcb->PinCount); + KeReleaseInStackQueuedSpinLock(&LockHandle); + IsLocked = false; + Result = CcMapAndRead(SharedMap, &offset, length.LowPart, 0, false, *Buffer); + if (!Result) + goto finish; + } + + + *Buffer = reinterpret_cast(reinterpret_cast(Bcb->BaseAddress) + (FileOffset->LowPart - Bcb->FileOffset.LowPart)); + + Result = true; + goto finish; + } + else + { + *Buffer = reinterpret_cast(reinterpret_cast(*Buffer) + (Bcb->FileOffset.LowPart - FileOffset->LowPart)); + + offset.QuadPart = Bcb->FileOffset.QuadPart; + length.QuadPart = Bcb->Length; + + if (PinFlags & PIN_WAIT) + { + Bcb->PinCount++; + KeReleaseInStackQueuedSpinLock(&LockHandle); + IsLocked = false; + + if (!IsNoWrite) + { + if (PinFlags & PIN_EXCLUSIVE) + ExAcquireResourceExclusiveLite(&Bcb->BcbResource, true); + else + ExAcquireSharedStarveExclusive(&Bcb->BcbResource, true); + } + + if (PinFlags & PIN_NO_READ) + { + Result = true; + goto finish; + } + + CcMapAndRead(SharedMap, &offset, length.LowPart, 0, true, *Buffer); + + KeAcquireInStackQueuedSpinLock(&SharedMap->BcbSpinLock, &LockHandle); + if (!Bcb->BaseAddress) + { + Bcb->BaseAddress = *Buffer; + Bcb->Vacb = Vacb; + Vacb = nullptr; + } + KeReleaseInStackQueuedSpinLock(&LockHandle); + + + *Buffer = reinterpret_cast(reinterpret_cast(Bcb->BaseAddress) + (FileOffset->LowPart - Bcb->FileOffset.LowPart)); + + Result = true; + goto finish; + } + + *Buffer = reinterpret_cast(reinterpret_cast(Bcb->BaseAddress) + (FileOffset->LowPart - Bcb->FileOffset.LowPart)); + + Result = true; + goto finish; + } + } + else + { + if (PinFlags & PIN_IF_BCB) + { + Bcb = nullptr; + Result = false; + goto finish; + } + + offset.QuadPart = FileOffset->QuadPart; + length.QuadPart = (EndFileOffset.QuadPart - offset.QuadPart); + + length.LowPart += (offset.LowPart & (PAGE_SIZE - 1)); + ReceivedLength += (offset.LowPart & (PAGE_SIZE - 1)); + + if ((!IsNoWrite && !(SharedMap->Flags & SHARE_FL_PIN_ACCESS)) || Flags) + { + if (!(offset.LowPart & (PAGE_SIZE - 1)) && Length >= PAGE_SIZE) + MapFlags = 3; + else + MapFlags = 2; + + if (!(length.LowPart & (PAGE_SIZE - 1))) + MapFlags |= 4; + } + + if (!(SharedMap->Flags & SHARE_FL_MODIFIED_NO_WRITE)) + IsNoWrite = true; + + *Buffer = reinterpret_cast(reinterpret_cast(*Buffer) - (FileOffset->LowPart & (PAGE_SIZE - 1))); + + offset.LowPart &= ~(PAGE_SIZE - 1); + + length.LowPart = ROUND_TO_PAGES(length.LowPart); + + if (length.LowPart > ReceivedLength) + length.LowPart = ReceivedLength; + + Bcb = CcAllocateInitializeBcb(SharedMap, Bcb, &offset, &length); + + if (PinFlags & PIN_WAIT) + { + if (!Bcb) + { + KeReleaseInStackQueuedSpinLock(&LockHandle); + IsLocked = false; + RtlRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + + if (!IsNoWrite) + { + /* For writing need acquire Bcb */ + if (PinFlags & PIN_EXCLUSIVE) + ExAcquireResourceExclusiveLite(&Bcb->BcbResource, true); + else + ExAcquireSharedStarveExclusive(&Bcb->BcbResource, true); + } + + KeReleaseInStackQueuedSpinLock(&LockHandle); + IsLocked = false; + + if (PinFlags & PIN_NO_READ) + { + Result = true; + goto finish; + } + + CcMapAndRead(SharedMap, &offset, length.LowPart, MapFlags, true, *Buffer); + + KeAcquireInStackQueuedSpinLock(&SharedMap->BcbSpinLock, &LockHandle); + if (!Bcb->BaseAddress) + { + Bcb->BaseAddress = *Buffer; + Bcb->Vacb = Vacb; + Vacb = nullptr; + } + KeReleaseInStackQueuedSpinLock(&LockHandle); + + *Buffer = reinterpret_cast( + reinterpret_cast(Bcb->BaseAddress) + + (FileOffset->LowPart - Bcb->FileOffset.LowPart)); + + Result = true; + goto finish; + } + else + { + + if (!IsNoWrite && !ExAcquireSharedStarveExclusive(&Bcb->BcbResource, false)) + { + Bcb = nullptr; + Result = false; + goto Finish; + } + _InterlockedIncrement(&Bcb->PinCount); + KeReleaseInStackQueuedSpinLock(&LockHandle); + IsLocked = false; + Result = CcMapAndRead(SharedMap, &offset, length.LowPart, MapFlags, false, *Buffer); + if (!Result) + goto finish; + + } + } + } +finish: + + if ((PinFlags & PIN_NO_READ) && (PinFlags & PIN_EXCLUSIVE) && Bcb && Bcb->BaseAddress) + { + CcFreeVirtualAddress(Bcb->Vacb); + + Bcb->BaseAddress = nullptr; + Bcb->Vacb = nullptr; + } +__finally{ + + if (IsLocked) + KeReleaseInStackQueuedSpinLock(&LockHandle); + + if (Vacb) + CcFreeVirtualAddress(Vacb); + + if (PinFlags & PIN_NO_READ) + { + CcDereferenceFileOffset(SharedMap, *FileOffset); + + } + if (Result) + { + *Bcb = Bcb; + BeyondLastByte->QuadPart = Bcb->BeyondLastByte.QuadPart; + } + else + { + *Buffer = nullptr; + + if (Bcb) + CcUnpinFileDataEx(Bcb, IsNoWrite, 0); + } + return Result; +} } BOOLEAN