[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_ 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
|
||||
|
Loading…
Reference in New Issue
Block a user