MiCopyOnWrite

INT64 __fastcall MiCopyOnWrite(UINT64 a1, UINT64 *rdx0, INT64 Page, INT64 a4){
  UINT64 v4; 
  char *v6; 
  unsigned int v7; 
  __int64 v8; 
  BOOL v9; 
  int SystemRegionType; 
  void *v11; 
  int v12; 
  unsigned int v13; 
  int v14; 
  int v15; 
  unsigned int v17; 
  unsigned int v18; 
  unsigned __int64 v19; 
  UINT8 v20; 
  int v21; 
  char v22; 
  int WsleProtection; 
  UINT64 v24; 
  int v25; 
  signed __int32 v26; 
  __int64 v27; 
  _MMPFN *PfnDb; 
  RTL_BALANCED_NODE *Address; 
  unsigned int v30; 
  INT64 v31; 
  unsigned __int64 *v32; 
  KSPIN_LOCK_QUEUE *v33; 
  unsigned __int64 v34; 
  _ETHREAD *CurrentThread; 
  unsigned int PagePriorityThread; 
  INT64 v37; 
  unsigned __int64 v38; 
  int v39; 
  UINT64 v40; 
  bool v41; 
  INT64 v42; 
  UINT64 v43; 
  INT64 v44; 
  _MMPTE *PxeUserLimit; 
  UINT64 v46; 
  char v47; 
  int v48; 
  _QWORD *CloneAddress; 
  volatile INT64 *v50; 
  _MMVAD **BugCheckParameter4; 
  int v52; 
  int v53; 
  UINT64 SessionVm; 
  UINT64 v56; 
  int v57; 
  int v58; 
  BOOL v59; 
  UINT64 SpinCount; 
  char v61[12]; 
  UINT64 v62; 
  UINT64 v63; 
  UINT64 v64; 
  _MMPTE *v65; 
  _MI_PARTITION *Partition; 
  INT64 v67[2]; 
  struct _KLOCK_QUEUE_HANDLE LockHandle; 
  UINT64 v69; 
  __int64 v70; 
  UINT64 a2[2]; 
  __int128 v72; 
  _MMSUPPORT_INSTANCE Vm; 
  __int128 v74; 
  __int128 v75; 
  __int128 v76; 
  __int128 v77; 
  __int128 v78; 
  __int128 v79; 
  __int128 v80; 
  __int128 v81; 
  __int128 v82; 
  __int64 v83; 
  v4 = *rdx0;
  HIWORD(Vm.PeakWorkingSetSize) = 0;
  *(_OWORD *)v67 = 0i64;
  v83 = 0i64;
  v74 = 0i64;
  v57 = a4;
  v75 = 0i64;
  v63 = (UINT64)rdx0;
  v76 = 0i64;
  v77 = 0i64;
  v78 = 0i64;
  v79 = 0i64;
  v80 = 0i64;
  v81 = 0i64;
  v82 = 0i64;
  *(_OWORD *)a2 = 0i64;
  v72 = 0i64;
  v59 = MiPteInShadowRange((UINT64)rdx0);
  v56 = v4;
  v70 = (v4 >> 12) & 0xFFFFFFFFFi64;
  v6 = (char *)MmGetPfnDb() + 48 * v70;
  *(_QWORD *)&v61[4] = 0i64;
  v7 = 0;
  v8 = *((_QWORD *)v6 + 1);
  v9 = (v4 & 0x200) == 0;
  v65 = (_MMPTE *)(v8 | 0x8000000000000000ui64);
  v62 = *((_QWORD *)KeGetCurrentThread() + 23);
  SystemRegionType = MiGetSystemRegionType(a1);
  if( SystemRegionType == 1 )
  {
    SessionVm = MiGetSessionVm();
    v13 = (v4 & 0x200) == 0;
    if( (*((_QWORD *)v6 + 5) & 0x1000000000i64) == 0 && v8 > 0 )
      v13 = v12 | v9;
    v52 = v12;
  }
  else if( SystemRegionType == 12 )
  {
    v52 = 0;
    SessionVm = (UINT64)MiGetAnyMultiplexedVm(1i64);
    v13 = (v4 & 0x200) == 0;
    if( (*((_QWORD *)v6 + 5) & 0x1000000000i64) == 0 && v8 > 0 )
      v13 = v14 | v9;
  }
  else
  {
    if( SystemRegionType == 9 || SystemRegionType == 14 )
      KeBugCheckEx(0x1Au, 0x3300ui64, a1, v4, 2ui64);
    if( SystemRegionType == 6 )
    {
      v52 = 0;
      SessionVm = (UINT64)MiGetAnyMultiplexedVm(2i64);
      v13 = v15 | v9;
      if( (*((_QWORD *)v6 + 5) & 0x1000000000i64) != 0 || v8 <= 0 )
        KeBugCheckEx(0x1Au, 0x3300ui64, a1, v4, 0i64);
    }
    else
    {
      if( SystemRegionType == 5 )
        KeBugCheckEx(0x1Au, 0x3300ui64, a1, v4, 1ui64);
      if( *(_QWORD *)(v62 + 1248) )
        return 3221226548i64;
      v52 = 1;
      v13 = (v4 & 0x200) == 0;
      SessionVm = v62 + 1664;
      if( (*((_QWORD *)v6 + 5) & 0x1000000000i64) == 0 && v8 > 0 )
        v13 = v9 | 2;
      Vm.AgeDistribution[2] = v62 + 1664;
      memset(&Vm.TrimmedPageCount, 0, 48);
      *(_QWORD *)&Vm.NextPageColor = a1;
      memset(&Vm.AgeDistribution[3], 0, 72);
      MiComputeFaultNode(&Vm, 0i64, (_CONTROL_AREA *)&v61[4], v11, BugCheckParameter4);
      v7 = v17;
    }
  }
  v18 = 0;
  Partition = *(_MI_PARTITION **)(qword_140C4E388 + 8i64 * *(unsigned __int16 *)(SessionVm + 174));
  HIDWORD(SpinCount) = *(_DWORD *)v6 & 1;
  v69 = (UINT64)MmGetPteBase() + ((a1 >> 9) & 0x7FFFFFFFF8i64);
  v19 = *(_QWORD *)v69;
  v20 = HIBYTE(v19) & 0xF | (16 * ((v19 >> 60) & 7));
  v58 = v57 & 1;
  if( (v57 & 1) != 0 || (HIBYTE(v19) & 0xF) == 10 )
  {
    v21 = v52;
  }
  else
  {
    v21 = v52;
    if( (HIBYTE(v19) & 0xF) == 9 )
    {
      v20 = (16 * ((v19 >> 60) & 7)) | 0xA;
    }
    else if( v52 != 1 && (v6[35] & 8) != 0 )
    {
      v20 = (16 * ((v19 >> 60) & 7)) | 0xA;
    }
  }
  v22 = v20 & 0xF;
  if( (v20 & 0xF) == 10 )
    goto LABEL_37;
  if( v22 == 8 && v21 != 2 )
  {
    v18 = 1;
    if( (*((_DWORD *)v6 + 4) & 0x400i64) != 0 )
      v18 = 2;
  }
  WsleProtection = MiGetWsleProtection(a1, v20);
  if( !WsleProtection )
LABEL_37:
    WsleProtection = ((unsigned __int64)MI_READ_PTE_LOCK_FREE((INT64)(v6 + 16)) >> 5) & 0x1F;
  v25 = MmMakeProtectNotWriteCopy[WsleProtection];
  v53 = v25;
  if( Page == -1 )
  {
    MiInitializePageColorBase(SessionVm, v7, (INT64)v67);
    v26 = _InterlockedExchangeAdd((volatile signed __int32 *)v67[0], 1u);
    Page = MiGetPage(Partition, v67[1] & v26 | HIDWORD(v67[1]), 0i64);
    if( Page == -1 )
      return 3221225495i64;
  }
  if( v18 )
  {
    if( v18 >= 2 )
    {
      v27 = *(_QWORD *)(qword_140C4E388 + 8 * ((*((_QWORD *)v6 + 5) >> 39) & 0x3FFi64));
      MiReturnCommit((_MI_PARTITION *)v27, 1ui64);
      if( v52 == 1 )
        _InterlockedDecrement64((volatile signed __int64 *)(v27 + 7616));
      v25 = v53;
    }
    PfnDb = MmGetPfnDb();
    MiUnlockPageTableCharges((_MMPFN *)((char *)PfnDb + 48 * (*((_QWORD *)v6 + 5) & 0xFFFFFFFFFi64)), 1u, v24);
  }
  else
  {
    PfnDb = MmGetPfnDb();
  }
  if( v25 == 24 )
  {
    Address = *(RTL_BALANCED_NODE **)&v61[4];
    LOBYTE(v25) = 1;
    LOBYTE(v53) = 1;
    if( *(_QWORD *)&v61[4] || (Address = MiLocateAddress(a1), (*(_QWORD *)&v61[4] = Address) != 0i64) )
    {
      v30 = (LODWORD(Address[2].Children[0]) >> 7) & 0x1F;
      if( v30 >> 3 == 3 && (v30 & 7) != 0 )
      {
        LOBYTE(v25) = 25;
      }
      else if( v30 >> 3 == 1 )
      {
        LOBYTE(v25) = 9;
      }
      LOBYTE(v53) = v25;
    }
  }
  v31 = (INT64)PfnDb + 48 * Page;
  *(_QWORD *)(v31 + 16) = MiSwizzleInvalidPte(32i64 * (v25 & 0x1F));
  if( v22 == 10 )
  {
    v34 = v63;
  }
  else
  {
    v32 = &qword_140C4F500;
    *(_QWORD *)&LockHandle.OldIrql = 0i64;
    if( (*(_BYTE *)(SessionVm + 184) & 7) != 2 )
      v32 = (unsigned __int64 *)(SessionVm + 256);
    LockHandle.LockQueue.Lock = v32;
    LockHandle.LockQueue.Next = 0i64;
    v33 = (KSPIN_LOCK_QUEUE *)_InterlockedExchange64((volatile __int64 *)v32, (__int64)&LockHandle);
    if( v33 )
      KxWaitForLockOwnerShip(&LockHandle.LockQueue, v33);
    ++*(_QWORD *)(SessionVm + 144);
    if( a1 < (unsigned __int64)MmGetPteBase() || a1 > (unsigned __int64)MmGetPteLimit() )
      ++*(_QWORD *)(SessionVm + 128);
    KeReleaseInStackQueuedSpinLockFromDpcLevel(&LockHandle);
    MiWriteValidPteVolatile((MMPTE *)v69, 0x80000000ui64);
    v34 = v63;
    v56 = *(_QWORD *)v63;
  }
  *(_WORD *)(v31 + 32) = 1;
  v64 = *(_QWORD *)((char *)MmGetPteBase() + ((v34 >> 9) & 0x7FFFFFFFF8i64));
  *(_QWORD *)(v31 + 40) ^= (*(_QWORD *)(v31 + 40) ^ (v64 >> 12)) & 0xFFFFFFFFFi64;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  if( (*((_DWORD *)CurrentThread + 326) & 0x100) != 0 )
    PagePriorityThread = (*((_DWORD *)CurrentThread + 326) & 0xE00u) >> 9;
  else
    PagePriorityThread = PsGetPagePriorityThread((__int64)CurrentThread);
  LODWORD(SpinCount) = 0;
  while( _interlockedbittestandset64((volatile signed __int32 *)(v31 + 24), 0x3Fui64) )
  {
    do
      KeYieldProcessorEx(&SpinCount);
    while( *(__int64 *)(v31 + 24) < 0 );
  }
  if( HIDWORD(SpinCount) )
    *(_QWORD *)v31 |= 1ui64;
  *(_BYTE *)(v31 + 34) |= 0x10u;
  if( v52 || (v6[35] & 8) == 0 || v58 )
    *(_BYTE *)(v31 + 35) &= ~8u;
  else
    *(_BYTE *)(v31 + 35) |= 8u;
  v37 = (unsigned __int8)v6[34] >> 6;
  if( *(unsigned __int8 *)(v31 + 34) >> 6 != (_DWORD)v37 )
    MiChangePageAttribute(v31, v37, 1);
  MiSetPfnTbFlushStamp((_MMPFN *)v31, 0i64, 1ui64);
  v38 = *(_QWORD *)(v31 + 24) & 0xC000000000000001ui64;
  *(_QWORD *)(v31 + 8) = v34;
  *(_QWORD *)(v31 + 24) = v38 | 1;
  *(_BYTE *)(v31 + 35) ^= (*(_BYTE *)(v31 + 35) ^ PagePriorityThread) & 7;
  *(_BYTE *)(v31 + 34) = *(_BYTE *)(v31 + 34) & 0xF8 | 6;
  if( v13 >= 4 )
    MiIdentifyPfn((_MMPFN *)v31, a2);
  _InterlockedAnd64((volatile signed __int64 *)(v31 + 24), 0x7FFFFFFFFFFFFFFFui64);
  if( v13 >= 4 )
  {
    *((_QWORD *)&v72 + 1) |= 8ui64;
    Vm.WorkingSetPrivateSize = (unsigned __int64)a2;
    Vm.MaximumWorkingSetSize = 32i64;
    LODWORD(BugCheckParameter4) = 289413890;
    EtwTraceKernelEvent(
      (EVENT_DATA_DESCRIPTOR *)&Vm.WorkingSetPrivateSize,
      1ui64,
      0x28000001ui64,
      0x282u,
      (UINT64)BugCheckParameter4);
  }
  __incgsdword(0x2E94u);
  v39 = 1;
  if( (v53 & 2) == 0 )
  {
    v39 = 9;
LABEL_88:
    v40 = a1;
    goto LABEL_89;
  }
  if( (MiFlags & 0x40000) != 0 )
    goto LABEL_88;
  v40 = a1;
  if( (MiFlags & 0x10000) == 0 )
  {
LABEL_89:
    if( v40 >= 0xFFFF800000000000ui64 )
      goto LABEL_92;
    goto LABEL_90;
  }
  if( a1 >= 0xFFFF800000000000ui64 )
  {
    v39 = 17;
    if( (v57 & 2) != 0 )
      v39 = 49;
    goto LABEL_89;
  }
LABEL_90:
  if( (*(_BYTE *)(*((_QWORD *)KeGetCurrentThread() + 23) + 992i64) & 1) != 0 )
    v39 |= 0x10u;
LABEL_92:
  MiCopyPage(Page, v70, 0i64, v39);
  if( (_DWORD)dword_140C4E568 )
  {
    v41 = PagePriorityThread < dword_140C4E56C;
    v42 = SessionVm;
    if( !v41 )
      MiLogPageAccess(SessionVm, v34);
  }
  else
  {
    v42 = SessionVm;
  }
  v43 = v56;
  if( (v13 & 1) == 0 )
  {
    if( (v56 & 0x8000000000000000ui64) != 0i64 || v52 != 1 )
      v43 = v56 | 0x42;
    v43 = v43 & 0xFFFFFFFFFFFFF5DFui64 | 0x820;
  }
  *(_QWORD *)&Vm.HardFaultCount = 20i64;
  v44 = v43 ^ (v43 ^ (Page << 12)) & 0xFFFFFFFFF000i64;
  WORD2(Vm.PeakWorkingSetSize) = 0;
  Vm.SelfmapLock = 0i64;
  *(_QWORD *)&Vm.Flags.0 = 0i64;
  v56 = v44;
  LODWORD(Vm.PeakWorkingSetSize) = v52;
  MiInsertTbFlushEntry((INT64)&Vm.PeakWorkingSetSize, a1 & 0xFFFFFFFFFFFFF000ui64, 1i64, 0i64);
  if( (v39 & 0x20) != 0 || (v44 & 0x42) == 0 )
  {
    MI_INTERLOCKED_EXCHANGE_PTE((volatile INT64 *)v34, v44);
    MiFlushTbList((__int64)&Vm.PeakWorkingSetSize);
  }
  else
  {
    PxeUserLimit = MmGetPxeUserLimit();
    *(_QWORD *)v34 = v44 & 0xFFFFFFFFFFFFFBFEui64 | 0x400;
    MiFlushTbList((__int64)&Vm.PeakWorkingSetSize);
    if( v34 >= (unsigned __int64)MmGetPml4eBase()
      && v34 <= (unsigned __int64)PxeUserLimit
      && (*(_DWORD *)(*((_QWORD *)KeGetCurrentThread() + 23) + 2172i64) & 0x1000) != 0
      && (v44 & 1) != 0 )
    {
      v44 |= 0x8000000000000000ui64;
    }
    *(_QWORD *)v34 = v44;
  }
  v46 = v62;
  if( v52 == 1 )
    _InterlockedExchangeAdd64((volatile signed __int64 *)(v62 + 1272), 1ui64);
  *(_DWORD *)v61 = 0;
  while( _interlockedbittestandset64((volatile signed __int32 *)v6 + 6, 0x3Fui64) )
  {
    do
      KeYieldProcessorEx((UINT64 *)v61);
    while( *((__int64 *)v6 + 3) < 0 );
  }
  if( !v52 && !v58 )
  {
    v47 = v6[35];
    if( (v47 & 8) != 0 )
      v6[35] = v47 & 0xF7;
  }
  MiDecrementShareCount((UINT64)v6);
  _InterlockedAnd64((volatile signed __int64 *)v6 + 3, 0x7FFFFFFFFFFFFFFFui64);
  if( (v13 & 2) != 0 )
  {
    v48 = MiDecrementCombinedPte(v42, v65);
  }
  else
  {
    if( (*(_BYTE *)(v42 + 184) & 7) != 0 )
      return 0i64;
    CloneAddress = MiLocateCloneAddress(v46, (unsigned __int64)v65);
    if( !CloneAddress )
      return 0i64;
    v48 = MiDecrementCloneBlockReference((UINT64)CloneAddress, v50, v46);
  }
  if( v48 == 3 )
    MiChargeCommit(Partition, 1ui64, 4ui64);
  return 0i64;
}

Referenced by:

MiCompleteProtoPteFault
MiCopyToUserVa
MiFaultInPagedPool
MiLockCode
MiLockDriverPageRange
MiLockPagedAddress
MiMakeDriverPagesPrivate
MiMakeProtoPrivate
MiPrepareImagePagesForHotPatch
MiProbeLeafPteAccess
MiSetProtectionOnSection
MiSplitPrivatePage
MiSplitReducedCommitClonePage
MiSystemFault
MiValidFault
MiValidVirtualizationFault
MiWalkVaRange
MmProtectPool
MmReplaceImportEntry