[NTOSKRNL:CC] Implement CcPinFileData
Implemented CcPinFileData Note: Future had to be refactored to be more functional in styling
This commit is contained in:
parent
4370544c97
commit
ddda3559c6
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user