MiPrepareToHotPatchImage

NTSTATUS __stdcall MiPrepareToHotPatchImage(INT64 a1, UINT64 *a2, UINT64 a3){
  INT64 v3; 
  unsigned __int8 v6; 
  _RTL_BITMAP *Pool; 
  _RTL_BITMAP *v8; 
  NTSTATUS v9; 
  unsigned int *v10; 
  _RTL_BITMAP *v11; 
  int *v12; 
  UINT64 *v13; 
  int v14; 
  __int64 v15; 
  unsigned int v16; 
  unsigned int v17; 
  unsigned int v18; 
  VOID *v19; 
  const VOID *v20; 
  _RTL_BITMAP *v21; 
  _RTL_BITMAP *v22; 
  INT64 v23; 
  UINT64 i; 
  int v25; 
  unsigned int NextForwardRunClear; 
  unsigned int v27; 
  int v28; 
  __int64 v29; 
  int BitMapHeader; 
  INT64 v32; 
  INT64 v33; 
  int v34[2]; 
  int *v35; 
  __int128 v36; 
  INT64 v37; 
  INT64 v38[19]; 
  INT64 v40; 
  unsigned __int8 v41; 

  v40 = a3;
  v3 = a3;
  v36 = 0i64;
  memset(v38, 0i64, 0x60u);
  if( v3 )
  {
    v6 = 0;
  }
  else
  {
    v3 = (INT64)v38;
    v40 = (INT64)v38;
    v6 = 1;
  }
  v41 = v6;
  Pool = (_RTL_BITMAP *)MiAllocatePool(
                          256i64,
                          8 * ((unsigned int)((*(_DWORD *)(a1 + 32) & 0x3F000) != 0) + 2 + (*(_DWORD *)(a1 + 32) >> 18)),
                          0x20206D4Dui64);
  v8 = Pool;
  *(_QWORD *)(a1 + 48) = Pool;
  if( Pool )
  {
    Pool->SizeOfBitMap = *(_DWORD *)(a1 + 32) >> 12;
    Pool->Buffer = &Pool[1].SizeOfBitMap;
    v8 = *(_RTL_BITMAP **)(a1 + 48);
  }
  if( !v8 )
    return -1073741670;
  RtlSetAllBits(v8);
  v10 = (unsigned int *)(v3 + 32);
  v37 = v3 + 32;
  *(_DWORD *)(a1 + 36) = 8 * *(_DWORD *)(v3 + 32);
  if( !a2 )
  {
    v11 = (_RTL_BITMAP *)MiAllocatePool(64i64, 8 * (((*v10 & 0x3F) != 0) + 2 + (*v10 >> 6)), 0x20206D4Dui64);
    *(_QWORD *)(a1 + 40) = v11;
    if( v11 )
    {
      v11->SizeOfBitMap = *v10;
      v11->Buffer = &v11[1].SizeOfBitMap;
      v11 = *(_RTL_BITMAP **)(a1 + 40);
    }
    if( !v11 )
      return -1073741670;
    RtlClearAllBits(v11);
    MiProcessHotPatchUndoTable(a1, v3);
    v12 = 0i64;
    v13 = a2;
    goto LABEL_34;
  }
  v35 = (int *)((char *)a2 + *((unsigned int *)RtlFindHotPatchBase(a2) + 6));
  v34[0] = 0;
  v9 = RtlCountRequiredHotPatchAddressTableEntries(
         *(_QWORD *)(a1 + 8),
         *(_DWORD *)(a1 + 32),
         *(_DWORD *)(a1 + 32) + v14,
         a2,
         v35,
         v6,
         BitMapHeader,
         v32,
         v34);
  v34[1] = v9;
  if( v9 < 0 )
    return v9;
  v16 = *v10;
  if( v34[0] )
  {
    v17 = v16 + v34[0];
    *(_DWORD *)(a1 + 36) = 8 * (v16 + v34[0]);
    v15 = ((8 * v17) >> 12) + (((8 * v17) & 0xFFF) != 0);
    LODWORD(v40) = v15;
    v18 = *(_DWORD *)(v3 + 36);
    if( (unsigned int)v15 > v18 )
    {
      if( 8 * v17 + *(_DWORD *)(a1 + 32) > ((*(unsigned int *)(*(_QWORD *)a1 + 28i64) | ((unsigned __int64)*(unsigned __int8 *)(*(_QWORD *)a1 + 33i64) << 32))
                                           - (*(unsigned int *)(*(_QWORD *)a1 + 24i64) | ((unsigned __int64)*(unsigned __int8 *)(*(_QWORD *)a1 + 32i64) << 32))
                                           + 1) << 12 )
        return -1073741671;
      v9 = MiCommitHotPatchTable(*(_QWORD *)a1, *(_QWORD *)(a1 + 24) + (v18 << 12), (unsigned int)v15 - v18);
      if( v9 < 0 )
        return v9;
      *(_DWORD *)(v3 + 36) = v40;
    }
  }
  else
  {
    v17 = *v10;
  }
  if( !v6 )
  {
    if( v17 > *v10 )
    {
      v19 = MiAllocatePool(256i64, 6 * v17, 0x48555048ui64);
      v40 = (INT64)v19;
      if( !v19 )
        return v9;
      v20 = *(const VOID **)(v3 + 40);
      if( v20 )
      {
        memmove(v19, v20, 6 * *v10);
        ExFreePoolWithTag(*(PVOID *)(v3 + 40), 0);
        v19 = (VOID *)v40;
      }
      *(_QWORD *)(v3 + 40) = v19;
    }
    v21 = (_RTL_BITMAP *)MiAllocatePool(64i64, 8 * ((v17 >> 6) + ((v17 & 0x3F) != 0) + 2), 0x20206D4Dui64);
    v22 = v21;
    *(_QWORD *)(a1 + 40) = v21;
    if( v21 )
    {
      v21->SizeOfBitMap = v17;
      v21->Buffer = &v21[1].SizeOfBitMap;
      v22 = *(_RTL_BITMAP **)(a1 + 40);
    }
    if( !v22 )
      return -1073741670;
    RtlClearAllBits(v22);
    MiProcessHotPatchUndoTable(a1, v3);
  }
  if( !*(_DWORD *)(a1 + 36)
    || (v9 = MiPrepareImagePagesForHotPatch(
               (INT64 *)a1,
               *(_QWORD *)(a1 + 24),
               (*(_DWORD *)(a1 + 36) >> 12) + (unsigned int)((*(_DWORD *)(a1 + 36) & 0xFFF) != 0)),
        v9 >= 0) )
  {
    *(_QWORD *)&v36 = a1;
    *((_QWORD *)&v36 + 1) = v6;
    v12 = v35;
    v13 = a2;
    RtlEnumerateHotPatchPatches(a2, (unsigned int *)v35, v15, &v36);
LABEL_34:
    if( !v6 )
    {
      if( !RtlCheckCurrentPatchesApplied(*(_QWORD *)(a1 + 8), *(_QWORD *)(a1 + 24), *(UINT64 **)(v3 + 40), *v10) )
        return -1073740628;
      LOBYTE(v40) = 0;
      RtlHotPatchSynchronizationRequired(
        *(_QWORD *)(a1 + 8),
        (INT64)v13,
        (INT64)v12,
        v23,
        *(_QWORD *)(a1 + 24),
        *(_QWORD *)(v3 + 40),
        *(PRTL_BITMAP *)(a1 + 40),
        v32,
        v33,
        (INT64)&v40);
      RtlClearAllBits(*(PRTL_BITMAP *)(a1 + 40));
      if( (_BYTE)v40 )
        *(_DWORD *)(a1 + 136) |= 1u;
    }
    LODWORD(v40) = 0;
    for( i = 0i64; ; i = v27 + v25 )
    {
      NextForwardRunClear = RtlFindNextForwardRunClear(*(_QWORD *)(a1 + 48), i, (UINT64 *)&v40);
      v27 = NextForwardRunClear;
      if( !NextForwardRunClear )
        break;
      v25 = v40;
      v9 = MiPrepareImagePagesForHotPatch(
             (INT64 *)a1,
             *(_QWORD *)(a1 + 8) + (unsigned int)((_DWORD)v40 << 12),
             NextForwardRunClear);
      if( v9 < 0 )
        return v9;
      LODWORD(v40) = v27 + v25;
    }
    MiMapHotPatchImageInSystemSpace();
    v9 = v28;
    if( v28 >= 0 )
    {
      v29 = *(_QWORD *)(*(_QWORD *)(a1 + 64) + 24i64);
      *(_QWORD *)(a1 + 72) = v29;
      *(_QWORD *)(a1 + 80) = v29 + *(unsigned int *)(a1 + 32);
      return 0;
    }
  }
  return v9;
}

Referenced by:

MiPerformImageHotPatch