/*
 * PROJECT: Alcyone System Kernel
 * LICENSE: BSD Clause 3
 * PURPOSE: Cache Controller:: Pin Support 
 * NT KERNEL: 5.11.9360
 * COPYRIGHT:  2023-2029 Dibymartanda Samanta <>
 */ 

#include <ntoskrnl.h>
#define NTDEBUG
#include <debug.h>
#include "ccinternal.hpp"


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<ULONG*>(reinterpret_cast<ULONG_PTR>(FirstBcb) & ~1UL) -  *reinterpret_cast<ULONG*>((reinterpret_cast<ULONG_PTR>(FirstBcb) & ~1UL) + sizeof(ULONG))) >> PAGE_SHIFT) * sizeof(PVOID);

    /*Allocate memory for the OBCB*/
    POBCB NewObcb = reinterpret_cast<POBCB>(ExAllocatePoolWithTag(NonPagedPool,AllocationSize,'cObC'));

    if (NewObcb == nullptr)
    {
        return nullptr;
    }

    /* Initialize the OBCB */ 
    RtlZeroMemory(NewObcb, AllocationSize);

    NewObcb->NodeByteSize = static_cast<USHORT>(AllocationSize);
    NewObcb->NodeTypeCode = 762;
    NewObcb->ByteLength = Length;
    NewObcb->FileOffset = *FileOffset;
    NewObcb->Bcbs[0] = Bcb;

    return NewObcb;
}

VOID 
VECTORCALL 
CcMapDataForOverwrite(
    PFILE_OBJECT FileObject,
    PLARGE_INTEGER FileOffset,
    ULONG Length,
    PVOID *Bcb,
    PVOID *Buffer)
{
    NTSTATUS status = STATUS_SUCCESS;
    PETHREAD currentThread = nullptr;
    PSHARED_CACHE_MAP sharedCacheMap = nullptr;
    ULONG pageCount = {0};
    PVOID outBcb = nullptr;
    PVOID localBuffer = nullptr;
    ULONG savedState = {0};
    ULONG readClusterSize = {0};

  
    pageCount = CalculatePageCount(Length,FileOffset);
    currentThread = (PETHREAD)KeGetCurrentThread();
    sharedCacheMap = (PSHARED_CACHE_MAP)FileObject->SectionObjectPointer->SharedCacheMap;

    if ((sharedCacheMap->Flags & 0x20000) == 0)
    {
        SpinLockGuard lockGuard(LockQueueMasterLock);
        sharedCacheMap->Flags |= 0x20000;
      
    }

    savedState = currentThread->ForwardClusterOnly + 2 * currentThread->ReadClusterSize;
    readClusterSize = currentThread->ReadClusterSize;

    CcMapDataCommon(FileObject, FileOffset, Length, TRUE, &outBcb, &localBuffer);
  

    auto SystemCacheAddress = *localBuffer;
    ULONG remainingPages = pageCount;

    while (remainingPages)
    {
        currentThread->ForwardClusterOnly = 1;
        if (--remainingPages > readClusterSize)
        {
            currentThread->ReadClusterSize = (remainingPages > 0xF) ? 15 : remainingPages;
        }

        if (!MmCheckCachedPageState(SystemCacheAddress,true))
        {
            MmCheckCachedPageState(SystemCacheAddress,false);
        }

         SystemCacheAddress += 4096;
    }
    /* Restore to the saved state*/
    currentThread->ForwardClusterOnly = savedState & 1;
    currentThread->ReadClusterSize = savedState >> 1;
    *Bcb = outBcb;
    *Buffer = localBuffer;

}

VOID
NTAPI
CcSetDirtyPinnedData(
    IN POBCB BcbVoid,
    IN PLARGE_INTEGER Lsn OPTIONAL)
{
    PSHARED_CACHE_MAP SharedCacheMap;
    PCC_BCB Bcb;
    PCC_BCB* BcbArray;
    PFAST_MUTEX Mutex;
    KIRQL OldIrql;
    ULONG PagesToWrite;
    PETHREAD CurrentThread;

    
    if (BcbVoid->NodeTypeCode == 762)
    {
        BcbArray = reinterpret_cast<PCC_BCB>(BcbVoid->Bcbs);
    }

    SharedCacheMap = (*BcbArray)->SharedCacheMap;

    /* Handle logging if necessary */
     auto VolumeLogHandleContext = &SharedCacheMap->VolumeCacheMap->LogHandleContext;
     if ( (SharedCacheMap->Flags & 0x1000000) != 0 && LogHandleContext.LastLWTimeStamp.QuadPart = -1 )
     {
         KeQuerySystemTime(&LogHandleContext.LastLWTimeStamp)
     }

    if (!(SharedCacheMap->Flags & 0x200))
    {
        CcSetDirtyInMask(SharedCacheMap, &BcbVoid->FileOffset, BcbVoid->PagesToWrite, NULL);
        return;
    }

    Bcb = *BcbArray;
    while (Bcb)
    {
        if ((ULONG_PTR)Bcb & 1)
        {
            KeBugCheckEx(CACHE_MANAGER, 0xE94, 0xC0000420, 0, 0);
        }

        SharedCacheMap = Bcb->SharedCacheMap;
        Mutex = &SharedCacheMap->BcbLock;

        /* Acquire the BCB lock */
        KeAcquireInStackQueuedSpinLock(&SharedCacheMap->BcbSpinLock, &LockHandle);
        
		KeAcquireQueuedSpinLockAtDpcLevel((ULONG_PTR)&KeGetPcr()->Prcb->LockQueue[5]);

        if (!Bcb->Dirty)
        {
            PagesToWrite = Bcb->PagesToWrite >> PAGE_SHIFT;
            Bcb->Dirty = TRUE;

            if (Lsn)
            {
                Bcb->OldestLsn = *Lsn;
                Bcb->NewestLsn = *Lsn;
            }

            /* Update dirty page statistics */
            if (!SharedCacheMap->DirtyPages && !(SharedCacheMap->Flags & PRIVATE_CACHE_MAP_FLAGS_WRITE_THROUGH))
            {
                CcScheduleLazyWriteScan(FALSE, FALSE);
                CcInsertIntoDirtySharedCacheMapList(SharedCacheMap);
            }
            CcChargeDirtyPages(SharedCacheMap, 0, 0, PagesToWrite);

            /* Handle process disk counters if necessary */
            if (SharedCacheMap->Flags & PRIVATE_CACHE_MAP_FLAGS_TRACK_DIRTY_PAGES)
            {
                PsUpdateDiskCounters(PsGetCurrentThread()->ThreadsProcess, 0, PagesToWrite << PAGE_SHIFT, 0, 1, 0);
            }
        }
		   KeReleaseQueuedSpinLockFromDpcLevel((ULONG_PTR)&Prcb->LockQueue[5]);

        /* Update LSN information */
        if (Lsn)
        {
            if (!Bcb->MostRecentlyDirtiedPage || Lsn->QuadPart < Bcb->MostRecentlyDirtiedPage)
            {
                Bcb->OldestLsn = *Lsn;
            }
            if (!Bcb->NewestLsn.QuadPart || Lsn->QuadPart > Bcb->NewestLsn.QuadPart)
            {
                Bcb->NewestLsn = *Lsn;
            }
            if (Lsn->QuadPart > SharedCacheMap->LargestLSN.QuadPart)
            {
                SharedCacheMap->LargestLSN = *Lsn;
            }
        }

        /* Update ValidDataGoal if necessary */
        if (Bcb->ResumeWritePage > SharedCacheMap->ValidDataGoal.QuadPart)
        {
            SharedCacheMap->ValidDataGoal.QuadPart = Bcb->ResumeWritePage;
        }

        /* Release the BCB lock */
        
        KeReleaseInStackQueuedSpinLock(&LockHandle);

        /* Move to the next BCB */
        BcbArray++;
        Bcb = *BcbArray;
    }
}


BOOLEAN
NTAPI
CcPinFileData(
    _In_ PFILE_OBJECT FileObject,
    _In_ PLARGE_INTEGER FileOffset,
    _In_ ULONG Length,
    _In_ BOOLEAN IsNoWrite,
    _In_ BOOLEAN Flags,
    _In_ ULONG PinFlags,
    _Out_ PCC_BCB* Bcb,
    _Out_ PVOID* Buffer,
    _Out_ LARGE_INTEGER* BeyondLastByte)
{
 
    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 
NTAPI
CcMapDataCommon(
    _In_ PFILE_OBJECT FileObject,
    _In_ PLARGE_INTEGER FileOffset,
    _In_ ULONG Length,
    _In_ ULONG Flags,
    _Out_ PVOID *Bcb,
    _Out_ PVOID *Buffer
)
  {
  if (Flags & FILE_PIN_SEQUENTIAL_READ)
        InterlockedIncrement(&CcSequentialReadCount);
    else
        InterlockedIncrement(&CcRandomReadCount);

    KeGetCurrentThread()->WaitIrql = PASSIVE_LEVEL;

    if (Flags & FILE_PIN_SEQUENTIAL_READ)
    {
        *Buffer = CcGetVirtualAddress(SharedMap, *FileOffset, (PVACB *)&Bcb, &ReceivedLength);
        return TRUE;
    }
    else
    {
        LARGE_INTEGER BeyondLastByte;
        if (CcPinFileData(FileObject, FileOffset, Length, TRUE, 0, Flags, Bcb, Buffer, &BeyondLastByte))
        {
            return TRUE;
        }
        else
        {
            InterlockedIncrement(&CCFailedPinReadCount);
            return FALSE;
        }
    }

   }
}

VOID
NTAPI
CcUnpinFileDataEx(
    _In_ PCC_BCB Bcb,
    _In_ BOOLEAN& WriteStatus,
    _In_ ULONG& UnPinType)
{
	PSHARED_CACHE_MAP SharedCacheMap = nullptr;
    KIRQL OldIrql = {0};
    ULONG NumberOfPages = {0};
	BOOLEAN ReadOnly = false;


    /* If it is not BCB Ptr,it must be VACB Pointer, free it*/
    if (Bcb->NodeTypeCode != BCB_NODE_TYPE_CODE)
    {   
        PVACB Vacb = reinterpret_cast<PVACB>(Bcb);
       
        CcFreeVirtualAddress(Vacb);

        return;
    }

    SharedCacheMap = Bcb->SharedCacheMap;
    /* Is it only Unpinning if so is their no write performed by Cache Controller */
    if (!(SharedCacheMap->Flags & SHARED_CACHE_MAP_MODIFIED_NO_WRITE) || UnPinType == UnPin)
        ReadOnly = TRUE;

    OldIrql = KeAcquireSpinLockRaiseToDpc(&SharedCacheMap->BcbSpinLock);
    /* Just reduce pin count if BCB is not set to be cleaned else perform cleaning of BCB*/
    if (UnPinType < CLEAN_BCB_PIN)
    {
        ASSERT(Bcb->PinCount > 0);
        Bcb->PinCount--;
    }
    else
    {
        if (UnPinType != CLEAN_BCB_PIN)
            KeBugCheckEx(UNEXPECTED_VALUE, UnPinType, (ULONG_PTR)Bcb, 0, 0);

        if (Bcb->IsBCBDirty)
        {
            NumberOfPages = (Bcb->Length / PAGE_SIZE);

            Bcb->IsBCBDirty = FALSE;
            Bcb->NewestDirtiedPage = 0;
            Bcb->NewestLsn.QuadPart = 0;

            CcDeductIsBCBDirtyPages(SharedCacheMap, NumberOfPages);
            /*Adjust page count */
            if (CcPagesYetToWrite <= NumberOfPages)
                CcPagesYetToWrite = 0;
            else
                CcPagesYetToWrite -= NumberOfPages;

            if (!SharedCacheMap->IsBCBDirtyPages && SharedCacheMap->OpenCount)
                CcInsertIntoCleanSharedCacheMapList(SharedCacheMap);
        }
    }

    if (Bcb->PinCount)
    {   /* If not read only BCB, release resources,their no point being pinned at that case */
        if (!ReadOnly)
            ExReleaseResourceLite(&Bcb->BcbResource);

        KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
    }
	/*if BCB is dirty, free the virtual adress*/
    else if (Bcb->IsBCBDirty)
    {
        if (Bcb->BaseAddress)
        {
            CcFreeVirtualAddress(Bcb->Vacb);

            Bcb->BaseAddress = NULL;
            Bcb->Vacb = NULL;
        }

        if (!ReadOnly)
            ExReleaseResourceLite(&Bcb->BcbResource);

        KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);
    }
    else
    {
        KeAcquireSpinLockAtDpcLevel(&SharedCacheMap->VacbSpinLock);

        RemoveEntryList(&Bcb->Link);

        if (SharedCacheMap->SectionSize.QuadPart > CACHE_OVERALL_SIZE &&
            (SharedCacheMap->Flags & SHARED_CACHE_MAP_MODIFIED_NO_WRITE))
        {
            CcAdjustVacbLevelLockCount(SharedCacheMap, &Bcb->FileOffset.QuadPart, -1); 
        }

        KeReleaseSpinLockFromDpcLevel(&SharedCacheMap->VacbSpinLock);

        if (Bcb->BaseAddress)
            CcFreeVirtualAddress(Bcb->Vacb); 

        if (!ReadOnly)
            ExReleaseResourceLite(&Bcb->BcbResource);

        KeReleaseSpinLock(&SharedCacheMap->BcbSpinLock, OldIrql);

        CcDeallocateBcb(Bcb);
    }
    
}




BOOLEAN
NTAPI
CcMapData(
    _In_ In PFILE_OBJECT FileObject,
    _In_ PLARGE_INTEGER FileOffset,
    _In_ ULONG Length,
    _In_ ULONG Flags,
    _Out_ PVOID *Bcb,
    _Out_ PVOID *Buffer)
{
    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<PVOID>(reinterpret_cast<ULONG_PTR>(LocalBuffer) + sizeof(PVOID));
    /* Set the output Buffer */
    *Buffer = LocalBuffer;

    return true;

}



BOOLEAN
NTAPI
CcPinMappedData(
    IN PFILE_OBJECT FileObject,
    IN PLARGE_INTEGER FileOffset,
    IN ULONG Length,
    IN ULONG Flags,
    IN OUT PCC_BCB Bcb)
{
    PSHARED_CACHE_MAP SharedCacheMap = nullptr;
    LARGE_INTEGER LocalFileOffset = {0};
    LARGE_INTEGER BeyondLastByte ={0};
    PVOID Buffer = nullptr;
    POBCB localbcb = nullptr;
    PCC_BCB *localbcbptr = nullptr;
    PCC_BCB *Bcbs = nullptr;
    bool Result = false;


    LocalFileOffset = *FileOffset;

   if (!(reinterpret_cast<PULONG>(Bcb) & 1))
    return true;

    *Bcb = reinterpret_cast<PVOID>(reinterpret_cast<ULONG_PTR>(*Bcb) - 1);

    SharedCacheMap = reinterpret_cast<PSHARED_CACHE_MAP>(FileObject->SectionObjectPointer->SharedCacheMap);
    InterlockedIncrement(&SharedCacheMap->PinCount);

     if (ExAcquireSharedStarveExclusive(&((PCC_BCB)*Bcb)->BcbResource, ((Flags & 1) == 1)))
	 {
            Result = true;
	  }
    else
    {
        LARGE_INTEGER localoffset = LocalFileOffset;
        ULONG RemainingLength = Length;

        while (true)
        {
            if (localbcb)
            {
                if (localbcbptr == reinterpret_cast<PCC_BCB*>(&localbcb))
                {
                    localbcb = CcAllocateObcb(FileOffset, Length, reinterpret_cast<PCC_BCB>(localbcb));
                    Bcbs = localbcb->Bcbs;
                    localbcbptr = localbcb->Bcbs;
                }
                RemainingLength += localoffset.LowPart - BeyondLastByte.LowPart;
                localoffset = BeyondLastByte;
                LocalFileOffset = BeyondLastByte;
                localbcbptr = ++Bcbs;
            }

            if (!CcPinFileData(FileObject,&LocalFileOffset,RemainingLength,!(SharedCacheMap->Flags & 0x200),false,Flags,localbcbptr,&Buffer,&BeyondLastByte))
            {
                Result = false;
                break;
            }

            if ((BeyondLastByte.QuadPart - localoffset.QuadPart) >= RemainingLength)
            {
                CcFreeVirtualAddress(reinterpret_cast<PVACB>(*Bcb));
                *Bcb = localbcb;
                Result = true;
                break;
            }
        }
    }

    if (!Result)
    {
        *Bcb = reinterpret_cast<PVOID>(reinterpret_cast<ULONG_PTR>(*Bcb) + 1);
        if (localbcb)
        {
            CcUnpinData(localbcb);
        }
    }

    return Result;
}

BOOLEAN
NTAPI
CcPinRead(
    IN PFILE_OBJECT FileObject,
    IN PLARGE_INTEGER FileOffset,
    IN ULONG Length,
    IN ULONG Flags,
    OUT PVOID *Bcb,
    OUT PVOID *Buffer)
{
    PSHARED_CACHE_MAP SharedCacheMap = nullptr;
    LARGE_INTEGER LocalFileOffset ={0};
    LARGE_INTEGER BeyondLastByte ={0};
    PVOID LocalBuffer = nullptr;
    POBCB localbcb = nullptr;
    PCC_BCB *localBcbPtr = nullptr;
    bool Result = false;
    ULONG RemainingLength = Length;

    

    LocalFileOffset = *FileOffset;

    if (Flags & 1) // 1 Signifies Pin is waiting 
        CcPinReadWait++;
    else
        CcPinReadNoWait++;

   
    SharedCacheMap = reinterpret_cast<PSHARED_CACHE_MAP>(FileObject->SectionObjectPointer->SharedCacheMap);
   /* Main Pinning Loop*/
    while (true)
    {
        if (localbcb)
        {
            if (localBcbPtr == reinterpret_cast<PCC_BCB*>(&localbcb))
            {
                localbcb = CcAllocateObcb(FileOffset, RemainingLength, reinterpret_cast<PCC_BCB>(localbcb));
                localBcbPtr = localbcb->Bcbs;
                *Buffer = LocalBuffer;
            }
            RemainingLength += LocalFileOffset.LowPart - BeyondLastByte.LowPart;
            LocalFileOffset = BeyondLastByte;
            ++localBcbPtr;
        }

        if (!CcPinFileData(FileObject,&LocalFileOffset,RemainingLength,(SharedCacheMap->Flags & 0x200) == 0,false,Flags,localBcbPtr,&LocalBuffer,&BeyondLastByte))
        {
            Result = false;
            break;
        }

        if (BeyondLastByte.QuadPart - LocalFileOffset.QuadPart >= RemainingLength)
        {
            *Bcb = localbcb;
            if (localBcbPtr == reinterpret_cast<PCC_BCB*>(&localbcb))
            {
                *Buffer = LocalBuffer;
            }
            Result = true;
            break;
        }
    }

    

    if (!Result && localbcb)
    {
        CcUnpinData(localbcb);
    }

    return Result;
}

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)
{
    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<PCC_BCB>(&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<PCC_BCB*>(&localbcb))
    {
        *Buffer = LocalBuffer;
    }

    if (Zero)
    {
        RtlZeroMemory(*Buffer, Length);
    }

    if(localbcb != nullptr)
   {
    CcSetDirtyPinnedData(localbcb, nullptr);
    *Bcb = localbcb;
   }

    return true;
}

VOID
NTAPI
CcSetBcbOwnerPointer(
    IN PMBCB Bcb,
    IN PVOID OwnerPointer)
{
     if (Bcb->NodeTypeCode == 762)
    {
        /* Iterate through all bitmap ranges */
         for (auto it = ListEntryIterator::begin(&Bcb->BitmapRanges); it != ListEntryIterator::end(&Bcb->BitmapRanges); ++it)
        {   auto* Bcb = CONTAINING_RECORD(it->Blink,MBCB,BitmapRanges);
            ExSetResourceOwnerPointer(&Bcb->DirtyPages,OwnerPointer);
        }
    }
    else
    {
        /* Single bitmap range */
        ExSetResourceOwnerPointer(&Bcb->BitmapRange1.FirstDirtyPage,OwnerPointer);
    }
}


VOID
NTAPI
CcUnpinData(
    _In_ PVOID BcbPtr)
{
	PCC_BCB Bcb = reinterpret_cast<PCC_BCB>(BcbPtr);
    BOOLEAN WRITE_FLAG = NULL;
		
if (reinterpret_cast<ULONG_PTR>((Bcb) & 1))
{
    WRITE_FLAG = TRUE;
    Bcb = reinterpret_cast<PCC_BCB>(reinterpret_cast<ULONG_PTR>(Bcb) & ~(1));

    CcUnpinFileDataEx(Bcb, WRITE_FLAG, UNPIN_BCB);

    return;
}

 if (Bcb->NodeTypeCode != 762)
{
        WRITE_FLAG = FALSE;
        CcUnpinFileDataEx(Bcb, WRITE_FLAG, UNPIN_BCB);
        return;
}
 for (auto it = ListEntryIterator::begin(&Bcb->BcbLinks); it != ListEntryIterator::end(&Bcb->BcbLinks); ++it)
{
        auto* BCB_CURRENT = CONTAINING_RECORD(it->Blink, CC_BCB, BcbLinks);
        
		CcUnpinData(BCB_CURRENT);
		
}
ExFreePoolWithTag(Bcb,NULL);
}

VOID
NTAPI
CcUnpinDataForThread(IN PVOID BcbPtr,
                     IN ERESOURCE_THREAD ResourceThreadId)
{
    PCC_BCB Bcb = BcbPtr;
    BOOLEAN WRITE_FLAG = NULL;

if (reinterpret_cast<ULONG_PTR>((Bcb) & 1))
{
    WRITE_FLAG = TRUE;
    Bcb = reinterpret_cast<PCC_BCB>(reinterpret_cast<ULONG_PTR>(Bcb) & ~(1));

    CcUnpinFileDataEx(Bcb, WRITE_FLAG, );

    return;
}

if (Bcb->NodeTypeCode != 762)
{
        WRITE_FLAG = FALSE;
		ExReleaseResourceForThreadLite(&Bcb->Resource, ResourceThreadId);
        CcUnpinFileDataEx(Bcb, WRITE_FLAG, UNPIN_BCB);
        return;
}
 for (auto it = ListEntryIterator::begin(&Bcb->BcbLinks); it != ListEntryIterator::end(&Bcb->BcbLinks); ++it)
{
        auto* BCB_CURRENT = CONTAINING_RECORD(it->Blink, CC_BCB, BcbLinks);
        
		CcUnpinData(BCB_CURRENT);
		
}
ExFreePoolWithTag(Bcb,NULL);
    
}