diff --git a/NTOSKRNL/CC/ccpinsupport.cpp b/NTOSKRNL/CC/ccpinsupport.cpp index 5fd237b..9108f6b 100644 --- a/NTOSKRNL/CC/ccpinsupport.cpp +++ b/NTOSKRNL/CC/ccpinsupport.cpp @@ -14,8 +14,52 @@ extern "C" +/* Move Typedef later to cctypes in sdk */ +/* NOTE: This structure have reconstructed analyzing CcAllocateObcb, might be icomplete to one in Windows NT Kernel*/ +/* We just need API Compatibility, so it doesn't matter */ +typedef struct _OBCB +{ + short NodeTypeCode; + short NodeByteSize; + ULONG ByteLength; + LARGE_INTEGER FileOffset; + struct PCC_BCB Bcbs[1]; + long __PADDING__[1]; +} OBCB, *POBCB; /*Internal Function*/ +POBCB +NTAPI +CcAllocateObcb( + _In_ PLARGE_INTEGER FileOffset, + _In_ ULONG Length, + _In_ PCC_BCB Bcb) +{ + + + /*Calculate the size needed for the OBCB*/ + SIZE_T AllocationSize = sizeof(OBCB) + ((Length + PAGE_SIZE - 1 + FileOffset->LowPart - *reinterpret_cast(reinterpret_cast(FirstBcb) & ~1UL) - *reinterpret_cast((reinterpret_cast(FirstBcb) & ~1UL) + sizeof(ULONG))) >> PAGE_SHIFT) * sizeof(PVOID); + + /*Allocate memory for the OBCB*/ + POBCB NewObcb = reinterpret_cast(ExAllocatePoolWithTag(NonPagedPool,AllocationSize,'cObC')); + + if (NewObcb == nullptr) + { + return nullptr; + } + + /* Initialize the OBCB */ + RtlZeroMemory(NewObcb, AllocationSize); + + NewObcb->NodeByteSize = static_cast(AllocationSize); + NewObcb->NodeTypeCode = 762; + NewObcb->ByteLength = Length; + NewObcb->FileOffset = *FileOffset; + NewObcb->Bcbs[0] = Bcb; + + return NewObcb; +} + BOOLEAN NTAPI @@ -183,48 +227,44 @@ CcUnpinFileDataEx( } -BOOLEAN -VECTORCALL -CcPinFileData( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER FileOffset, - IN ULONG Length, - IN BOOLEAN IsReadOnly, - IN BOOLEAN IsWriteOnly, - IN ULONG Flags, - OUT PCC_BCB *Bcb, - OUT PVOID *BaseAddress, - OUT PLARGE_INTEGER BeyondLastByte) -{ - // Unimplemented -} + BOOLEAN NTAPI CcMapData( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER FileOffset, - IN ULONG Length, - IN ULONG Flags, - OUT PVOID *Bcb, - OUT PVOID *Buffer) + _In_ In PFILE_OBJECT FileObject, + _In_ PLARGE_INTEGER FileOffset, + _In_ ULONG Length, + _In_ ULONG Flags, + _Out_ PVOID *Bcb, + _Out_ PVOID *Buffer) { - //Unimplemented + PVOID LocalBuffer = nullptr; + /* Call CcMapDataCommon to perform the actual mapping */ + if (!CcMapDataCommon(FileObject,FileOffset,Length,Flags,Bcb,&LocalBuffer)) + { + return false; + } + /* Check if we need to read the data */ + if (!(Flags & MAP_NO_READ)) + { + /* Read the data */ + if (!CcMapAndRead(Length, 0, true, LocalBuffer)) + { + return false; + } + } + /* Set Bcb to point after the LocalBuffer */ + *Bcb = reinterpret_cast(reinterpret_cast(LocalBuffer) + sizeof(PVOID)); + /* Set the output Buffer */ + *Buffer = LocalBuffer; + + return true; + } -BOOLEAN -FASTCALL -CcMapDataCommon( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER FileOffset, - IN ULONG Length, - IN ULONG Flags, - OUT PVOID *Bcb, - OUT PVOID *Buffer) -{ - //Unimplemented -} + BOOLEAN NTAPI @@ -254,15 +294,74 @@ CcPinRead( BOOLEAN NTAPI CcPreparePinWrite( - IN PFILE_OBJECT FileObject, - IN PLARGE_INTEGER FileOffset, - IN ULONG Length, - IN BOOLEAN Zero, - IN ULONG Flags, - OUT PVOID *Bcb, - OUT PVOID *Buffer) + _In_ PFILE_OBJECT FileObject, + _In_ PLARGE_INTEGER FileOffset, + _In_ ULONG Length, + _In_ BOOLEAN Zero, + _In_ ULONG Flags, + _Out_ PVOID *Bcb, + _Out_ PVOID *Buffer) { - //Unimplemented + LARGE_INTEGER LocalFileOffset = *FileOffset; + LARGE_INTEGER BeyondLastByte ={0}; + ULONG RemainingLength = Length; + POBCB localbcb = nullptr; + PCC_BCB *localbcbPtr = nullptr; + PVOID LocalBuffer = nullptr; + BOOLEAN Result = false; + + + + + if (Flags & PIN_WAIT) + { + return CcMapDataForOverwrite(FileObject, FileOffset, Length, Bcb, Buffer); + } + + /*Pinning Loop*/ + while(true) + { + if (localbcb) + { + if (localbcbPtr == reinterpret_cast(&localbcb)) + { + localbcb = CcAllocateObcb(&LocalFileOffset, RemainingLength, localbcb); + localbcbPtr = localbcb->Bcbs; + *Buffer = LocalBuffer; + } + RemainingLength += LocalFileOffset.QuadPart - BeyondLastByte.QuadPart; + LocalFileOffset.QuadPart = BeyondLastByte.QuadPart; + localbcbPtr++; + } + + if (!CcPinFileData(FileObject, &LocalFileOffset,RemainingLength,false,false,Flags,localbcbPtr,&LocalBuffer, &BeyondLastByte)) + { + /* Pinning failed */ + if (localbcb) + { + CcUnpinData(localbcb); + } + return false; + } + if(BeyondLastByte.QuadPart < LocalFileOffset.QuadPart + RemainingLength) + break; + + } + + if (localbcbPtr == reinterpret_cast(&localbcb)) + { + *Buffer = LocalBuffer; + } + + if (Zero) + { + RtlZeroMemory(*Buffer, Length); + } + + CcSetDirtyPinnedData(localbcb, nullptr); + *Bcb = localbcb; + + return true; } VOID @@ -295,7 +394,7 @@ CcUnpinData( PCC_BCB Bcb = reinterpret_cast(BcbPtr); BOOLEAN WRITE_FLAG = NULL; -if (reinterpret_cast((Bcb & 1)) +if (reinterpret_cast((Bcb) & 1)) { WRITE_FLAG = TRUE; Bcb = reinterpret_cast(reinterpret_cast(Bcb) & ~(1)); @@ -329,7 +428,7 @@ CcUnpinDataForThread(IN PVOID BcbPtr, PCC_BCB Bcb = BcbPtr; BOOLEAN WRITE_FLAG = NULL; -if (reinterpret_cast((Bcb & 1)) +if (reinterpret_cast((Bcb) & 1)) { WRITE_FLAG = TRUE; Bcb = reinterpret_cast(reinterpret_cast(Bcb) & ~(1));