[NTOSKRNL:CC] Implement CcPinFileData

Implemented CcPinFileData
Note: Future had to be refactored to be more functional in styling
This commit is contained in:
Dibyamartanda Samanta 2024-08-06 14:50:17 +02:00 committed by CodingWorkshop Signing Team
parent 4370544c97
commit ddda3559c6
Signed by: CodingWorkshop Signing Team
GPG Key ID: 6DC88369C82795D2

View File

@ -185,7 +185,286 @@ CcPinFileData(
_Out_ PVOID* Buffer, _Out_ PVOID* Buffer,
_Out_ LARGE_INTEGER* BeyondLastByte) _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<PVOID>(reinterpret_cast<ULONG_PTR>(Bcb->BaseAddress) + (FileOffset->LowPart - Bcb->FileOffset.LowPart));
Result = true;
goto finish;
}
else
{
*Buffer = reinterpret_cast<PVOID>(reinterpret_cast<ULONG_PTR>(*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<PVOID>(reinterpret_cast<ULONG_PTR>(Bcb->BaseAddress) + (FileOffset->LowPart - Bcb->FileOffset.LowPart));
Result = true;
goto finish;
}
*Buffer = reinterpret_cast<PVOID>(reinterpret_cast<ULONG_PTR>(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<PVOID>(reinterpret_cast<ULONG_PTR>(*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<PVOID>(
reinterpret_cast<ULONG_PTR>(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 BOOLEAN