CmRestoreKey

__int64 __fastcall CmRestoreKey(_QWORD *a1, __int64 a2, int a3, char a4){
  char v4; 
  __int64 v8; 
  UINT64 v9; 
  UINT64 v10; 
  int Hive; 
  char v12; 
  int HiveVolatile; 
  unsigned int v14; 
  __int64 v15; 
  unsigned int v16; 
  __int64 v17; 
  unsigned int v18; 
  unsigned int v19; 
  unsigned int v20; 
  size_t v21; 
  const VOID *v22; 
  _WORD *v23; 
  __int64 v24; 
  void(__fastcall *v25)(UINT64, _HV_GET_CELL_CONTEXT *); 
  char v26; 
  INT64 v27; 
  INT64 v28; 
  __int64 v29; 
  int v30; 
  __int64 v31; 
  unsigned int v32; 
  bool v33; 
  unsigned int v34; 
  __int64 v35; 
  __int64 v36; 
  int *v37; 
  __int64 v38; 
  unsigned int v39; 
  void(__fastcall *v40)(UINT64, int *); 
  _WORD *v41; 
  unsigned int v42; 
  int *v43; 
  _WORD *v44; 
  UINT8 v45; 
  __int64 v46; 
  unsigned int v47; 
  __int64 v48; 
  _DWORD *v49; 
  _DWORD *v50; 
  __int64 v51; 
  unsigned int v52; 
  __int64 v53; 
  __int64 v54; 
  __int64 v55; 
  __int64 v56; 
  int v57; 
  int v58; 
  __int64 v59; 
  unsigned int v60; 
  VOID **CellAddress; 
  CHAR CellAddressContext; 
  _HV_GET_CELL_CONTEXT *CellAddressContexta; 
  INT64 a7; 
  UINT64 Flags; 
  char v68; 
  unsigned int CellIndex; 
  unsigned int CellIndex_4; 
  int v71; 
  __int64 v72; 
  unsigned int v73; 
  int v74[2]; 
  int v75[2]; 
  PVOID P; 
  VOID *v77; 
  int v78[2]; 
  INT64 v79[2]; 
  unsigned int NodeCell; 
  unsigned int NodeCell_4; 
  _HV_GET_CELL_CONTEXT v82; 
  unsigned int v83; 
  unsigned int v84; 
  int v85[2]; 
  int v86[2]; 
  INT64 a2a[2]; 
  _LIST_ENTRY DeferredPostAsync; 
  _WORD *v89; 
  INT64 a6[5]; 
  INT64 a12[54]; 

  v73 = a3;
  v4 = 0;
  v89 = 0i64;
  v86[1] = 0;
  v77 = 0i64;
  v86[0] = -1;
  v82.Cell = -1;
  v74[0] = -1;
  v75[0] = -1;
  v78[0] = -1;
  v8 = 0i64;
  *(_DWORD *)&v82.BinContext._bf_0 = 0;
  v74[1] = 0;
  v75[1] = 0;
  P = 0i64;
  v78[1] = 0;
  memset(a6, 0, 32);
  DeferredPostAsync = 0i64;
  memset(a12, 0i64, sizeof(a12));
  v71 = 0;
  *(_OWORD *)a2a = 0i64;
  *(_OWORD *)v79 = 0i64;
  CmpInitializeDelayDerefContext(a2a);
  v9 = a1[1];
  v10 = *(_QWORD *)(v9 + 32);
  if( (*(_DWORD *)(v10 + 160) & 0x100000) != 0 )
  {
    Hive = -1073741790;
    goto LABEL_119;
  }
  CmpTraceHiveRestoreStart((PVOID)a2, (unsigned int)a3);
  if( (a3 & 0xFFFFFFFD) != 0 && (a3 & 2) != 0 || a1[7] || a1[8] )
  {
    Hive = -1073741811;
    goto LABEL_119;
  }
  v12 = 1;
  if( (v73 & 1) != 0 )
  {
    HiveVolatile = CmpLoadHiveVolatile((_CM_KEY_BODY *)a1, (PVOID)a2);
LABEL_8:
    Hive = HiveVolatile;
    goto LABEL_119;
  }
  if( (v73 & 2) != 0 )
  {
    HiveVolatile = CmpRefreshHive((__int64)a1);
    goto LABEL_8;
  }
  DeferredPostAsync.Blink = &DeferredPostAsync;
  a6[0] = a2;
  DeferredPostAsync.Flink = &DeferredPostAsync;
  LODWORD(Flags) = 17825793;
  memset(&a6[1], 0, 24);
  Hive = CmpCreateHive((INT64)&P, 2ui64, 0x8000ui64, 0i64, 0i64, (INT64)a6, 0i64, Flags, 0i64, 0i64, 0i64, (INT64)a12);
  if( Hive < 0 )
    goto LABEL_119;
  CmpLockRegistryFreezeAware(0);
  v4 = 1;
  CmpLockKcbShared((_CM_KEY_CONTROL_BLOCK *)v9);
  v14 = *(_DWORD *)(v9 + 40);
  CellIndex = v14;
  if( *(_WORD *)(v9 + 66) )
  {
    CmpLogUnsupportedOperation(17);
    Hive = -1073741822;
LABEL_117:
    CmpUnlockKcb((_CM_KEY_CONTROL_BLOCK *)v9);
    goto LABEL_119;
  }
  if( CmpIsKeyDeletedForKeyBody((CM_KEY_BODY *)a1, 0i64) )
  {
    Hive = -1073741535;
    goto LABEL_117;
  }
  if( *(_BYTE *)(v9 + 65) == 1 || v10 == *(_QWORD *)&CmpMasterHive )
  {
    Hive = -1073741790;
    goto LABEL_117;
  }
  if( *(_BYTE *)(v10 + 2936) == 1 )
  {
    Hive = -1073741431;
    goto LABEL_117;
  }
  HvLockHiveFlusherShared(v10);
  v68 = 1;
  v15 = (*(__int64(__fastcall **)(UINT64, _QWORD, int *))(v10 + 8))(v10, v14, v74);
  v72 = v15;
  v8 = v15;
  if( !v15
    || ((*(_BYTE *)(v15 + 2) & 4) == 0 ? (v16 = *(_DWORD *)(v15 + 16)) : (v16 = -1),
        LODWORD(a7) = v14 >> 31,
        NodeCell = v16,
        v17 = *((_QWORD *)P + 8),
        v83 = v14 >> 31,
        v18 = CmpCopyKeyPartial((UINT64)P, *(unsigned int *)(v17 + 36), v10, v16, 6, CellAddressContext, a7),
        NodeCell_4 = v18,
        v18 == -1) )
  {
    Hive = -1073741670;
    goto LABEL_115;
  }
  v19 = HvReallocateCell((PVOID)v10, (PVOID)v18, (unsigned int)*(unsigned __int16 *)(v8 + 72) + 76, 1u, &v77, &v82);
  CellIndex_4 = v19;
  v20 = v19;
  if( v19 == -1 )
  {
    Hive = -1073741670;
    goto LABEL_112;
  }
  v21 = *(unsigned __int16 *)(v8 + 72);
  v22 = (const VOID *)(v8 + 76);
  v23 = v77;
  NodeCell_4 = v19;
  memmove((char *)v77 + 76, v22, v21);
  v24 = v72;
  v23[36] = *(_WORD *)(v72 + 72);
  if( (*(_BYTE *)(v24 + 2) & 0x20) != 0 )
    v23[1] |= 0x20u;
  else
    *((_WORD *)v77 + 1) &= ~0x20u;
  LODWORD(CellAddressContexta) = 0;
  if( !CmpCopySyncTree(
          (UINT64)P,
          *(unsigned int *)(*((_QWORD *)P + 8) + 36i64),
          v10,
          v20,
          2,
          (INT64)CellAddressContexta) )
  {
    v8 = v72;
    Hive = -1073741670;
LABEL_112:
    v60 = NodeCell_4;
    if( CmpDeleteTree(v10, NodeCell_4) )
      CmpFreeKeyByCell(v10, v60, 0);
    v12 = v68;
    if( !v68 )
    {
LABEL_116:
      if( !v12 )
        goto LABEL_119;
      goto LABEL_117;
    }
LABEL_115:
    HvUnlockHiveFlusherShared(v10);
    goto LABEL_116;
  }
  HvUnlockHiveFlusherShared(v10);
  v68 = 0;
  CmpUnlockKcb((_CM_KEY_CONTROL_BLOCK *)v9);
  CmpUnlockRegistry();
  (*(void(__fastcall **)(UINT64, int *))(v10 + 16))(v10, v74);
  v25 = *(void(__fastcall **)(UINT64, _HV_GET_CELL_CONTEXT *))(v10 + 16);
  v72 = 0i64;
  v8 = 0i64;
  v25(v10, &v82);
  v77 = 0i64;
  CmpLockRegistryFreezeAware(1u);
  while( 1 )
  {
    v26 = 0;
    if( (*(&CmpDummyThreadEvent + 1056) & 1) != 0 )
    {
LABEL_110:
      Hive = -1073741431;
      goto LABEL_111;
    }
    if( CmpIsKeyDeletedForKeyBody((CM_KEY_BODY *)a1, 0i64) )
      goto LABEL_60;
    if( CellIndex != *(_DWORD *)(v9 + 40) )
    {
      Hive = -1073741444;
      goto LABEL_111;
    }
    if( (*(_DWORD *)(v9 + 8) & 0x40000) != 0 )
    {
      Hive = -1073740763;
      goto LABEL_111;
    }
    if( *(_BYTE *)(v10 + 2936) == 1 )
      goto LABEL_110;
    if( NodeCell != -1 )
    {
      Hive = CmpCheckKeyAccess((_HHIVE *)v10, NodeCell, a4, 4ui64);
      if( Hive < 0 )
        goto LABEL_111;
    }
    Hive = CmpCheckKeyAccess((_HHIVE *)v10, CellIndex, a4, 0x10000ui64);
    if( Hive < 0 )
      goto LABEL_111;
    Hive = CmpTryAcquireKcbIXLocks(v9, 1, v27, (UINT64 *)v79);
    if( Hive == -1073741267 )
    {
      CmpLogTransactionAbortedForRollbackPacket(v9, 7, (unsigned int *)v79, v29);
      CmpUnlockRegistry();
      Hive = CmpAbortRollbackPacket((INT64)v79);
      if( Hive >= 0 )
        goto LABEL_45;
      CmpLockRegistryFreezeAware(1u);
LABEL_111:
      v4 = 1;
      goto LABEL_112;
    }
    if( Hive < 0 )
      goto LABEL_111;
    LOBYTE(v28) = a4;
    LODWORD(CellAddress) = 2;
    Hive = CmpDoAccessCheckOnSubtree(v10, CellIndex, v28, 0x10000i64, (INT64)CellAddress);
    if( Hive < 0 )
      goto LABEL_111;
    if( (v73 & 8) == 0 )
      break;
    Hive = CmpPrepareToInvalidateAllHigherLayerKcbs(v9, 0, (__int64)v79);
    if( Hive == -1073741267 )
    {
      v26 = 1;
    }
    else if( Hive < 0 )
    {
      goto LABEL_111;
    }
    v30 = CmpPrepareForSubtreeInvalidation(v9, (__int64)v79);
    Hive = v30;
    if( v30 != -1073741267 )
    {
      if( v30 < 0 )
        goto LABEL_111;
      if( !v26 )
      {
        CmpInvalidateAllHigherLayerKcbs(v9, 0, 1i64, (INT64)a2a);
        CmpInvalidateSubtree(v9, 1i64, (INT64)a2a, 0i64);
        CmpDrainDelayDerefContext((UINT64 **)a2a);
        goto LABEL_62;
      }
    }
    CmpLogTransactionAbortedForRollbackPacket(v9, 7, (unsigned int *)v79, v31);
    CmpUnlockRegistry();
    v4 = 0;
    Hive = CmpAbortRollbackPacket((INT64)v79);
    if( Hive < 0 )
    {
      CmpLockRegistryFreezeAware(1u);
      goto LABEL_112;
    }
LABEL_45:
    CmpCleanupRollbackPacket((INT64)v79);
    *(_OWORD *)v79 = 0i64;
    CmpRetryBackOff(&v71);
    CmpLockRegistryFreezeAware(1u);
  }
  CmpEnumerateAllHigherLayerKcbs(
    v9,
    (unsigned int(__fastcall *)(void *, __int64))CmpCleanUpHigherLayerKcbCachesPreCallback,
    (unsigned int(__fastcall *)(void *, __int64, __int64))CmpCleanUpHigherLayerKcbCachesPostCallback,
    0i64,
    0i64,
    1,
    1);
  if( CmpDoesKeyHaveOpenSubkeys(v9) || *(_QWORD *)v9 != 1i64 )
  {
LABEL_60:
    Hive = -1073741535;
    goto LABEL_111;
  }
LABEL_62:
  v32 = CellIndex_4;
  if( !HvMarkCellDirty((PVOID)v10, (PVOID)CellIndex_4, 0) )
  {
    Hive = -1073741443;
    goto LABEL_111;
  }
  v77 = (VOID *)(*(__int64(__fastcall **)(UINT64, _QWORD, _HV_GET_CELL_CONTEXT *))(v10 + 8))(v10, CellIndex, &v82);
  if( !v77 )
  {
LABEL_65:
    Hive = -1073741670;
    goto LABEL_111;
  }
  v33 = (*((_BYTE *)v77 + 2) & 4) == 0;
  v34 = *((_DWORD *)v77 + 4);
  v73 = v34;
  if( v33 )
  {
    v8 = 0i64;
    if( !HvMarkCellDirty((PVOID)v10, (PVOID)v34, 0) )
    {
      Hive = -1073741443;
      goto LABEL_111;
    }
    v38 = (*(__int64(__fastcall **)(UINT64, _QWORD, int *))(v10 + 8))(v10, v34, v75);
    if( !v38 )
      goto LABEL_65;
    v39 = *(_DWORD *)(v38 + 4i64 * v83 + 28);
    v40 = *(void(__fastcall **)(UINT64, int *))(v10 + 16);
    v84 = v39;
    v40(v10, v75);
    v41 = (_WORD *)(*(__int64(__fastcall **)(UINT64, _QWORD, int *))(v10 + 8))(v10, v39, v86);
    v89 = v41;
    if( !v41 )
    {
LABEL_68:
      Hive = -1073741670;
      v8 = 0i64;
      goto LABEL_111;
    }
    if( *v41 == 26994 )
    {
      v42 = (unsigned __int16)v41[1];
      v43 = (int *)(v41 + 2);
    }
    else
    {
      v42 = 1;
      v43 = (int *)&v84;
    }
    v71 = 0;
    if( v42 )
    {
      while( 1 )
      {
        v44 = (_WORD *)(*(__int64(__fastcall **)(UINT64, _QWORD, int *))(v10 + 8))(v10, (unsigned int)*v43, v78);
        if( !v44 )
          break;
        v45 = HvMarkCellDirty((PVOID)v10, (PVOID)(unsigned int)*v43, 0);
        v46 = 0i64;
        if( !v45 )
        {
          (*(void(__fastcall **)(UINT64, int *, _QWORD))(v10 + 16))(v10, v78, 0i64);
          v8 = v72;
          Hive = -1073741443;
          goto LABEL_111;
        }
        v47 = (unsigned __int16)v44[1];
        v48 = 0i64;
        if( ((*v44 - 26220) & 0xFDFF) != 0 )
        {
          if( v44[1] )
          {
            v46 = CellIndex;
            v49 = v44 + 2;
            while( *v49 != CellIndex )
            {
              v48 = (unsigned int)(v48 + 1);
              ++v49;
              if( (unsigned int)v48 >= v47 )
                goto LABEL_92;
            }
            v32 = CellIndex_4;
            *(_DWORD *)&v44[2 * v48 + 2] = CellIndex_4;
LABEL_104:
            (*(void(__fastcall **)(UINT64, int *))(v10 + 16))(v10, v78);
            goto LABEL_94;
          }
        }
        else if( v44[1] )
        {
          v46 = CellIndex;
          v50 = v44 + 2;
          while( *v50 != CellIndex )
          {
            v48 = (unsigned int)(v48 + 1);
            v50 += 2;
            if( (unsigned int)v48 >= v47 )
              goto LABEL_92;
          }
          v32 = CellIndex_4;
          *(_DWORD *)&v44[4 * v48 + 2] = CellIndex_4;
          goto LABEL_104;
        }
LABEL_92:
        (*(void(__fastcall **)(UINT64, int *, __int64))(v10 + 16))(v10, v78, v46);
        ++v43;
        if( ++v71 >= v42 )
          goto LABEL_93;
      }
      Hive = -1073741670;
      v8 = 0i64;
      goto LABEL_111;
    }
LABEL_93:
    v32 = CellIndex_4;
LABEL_94:
    v51 = (*(__int64(__fastcall **)(UINT64, _QWORD, int *))(v10 + 8))(v10, v73, v75);
    v52 = *(unsigned __int16 *)((*(__int64(__fastcall **)(UINT64, _QWORD, int *))(v10 + 8))(v10, v32, v74) + 74);
    if( *(_DWORD *)(v51 + 56) < v52 )
      *(_DWORD *)(v51 + 56) = v52;
    (*(void(__fastcall **)(UINT64, int *))(v10 + 16))(v10, v74);
    v37 = v75;
  }
  else
  {
    v35 = (*(__int64(__fastcall **)(_QWORD, _QWORD, int *))(*(_QWORD *)&CmpMasterHive + 8i64))(
            *(_QWORD *)&CmpMasterHive,
            v34,
            v75);
    if( !v35 )
      goto LABEL_68;
    *(_DWORD *)(v35 + 28) = CellIndex_4;
    (*(void(__fastcall **)(_QWORD, int *))(*(_QWORD *)&CmpMasterHive + 16i64))(*(_QWORD *)&CmpMasterHive, v75);
    v36 = (*(__int64(__fastcall **)(UINT64, _QWORD, int *))(v10 + 8))(v10, CellIndex_4, v74);
    v8 = v36;
    if( !v36 )
    {
LABEL_70:
      Hive = -1073741670;
      goto LABEL_111;
    }
    *(_DWORD *)(v36 + 16) = v34;
    v37 = v74;
    *(_DWORD *)(*(_QWORD *)(v10 + 64) + 36i64) = CellIndex_4;
  }
  (*(void(__fastcall **)(UINT64, int *))(v10 + 16))(v10, v37);
  *(_DWORD *)(v9 + 40) = v32;
  CmpCleanUpKcbCachedSymlink(v9, (INT64)a2a);
  v53 = *(_QWORD *)(v9 + 32);
  v85[0] = -1;
  v54 = *(unsigned int *)(v9 + 40);
  v85[1] = 0;
  v55 = (*(__int64(__fastcall **)(__int64, __int64, int *))(v53 + 8))(v53, v54, v85);
  v8 = 0i64;
  v56 = v55;
  if( !v55 )
    goto LABEL_70;
  v57 = *(_DWORD *)(v55 + 40);
  v58 = *(_DWORD *)(v55 + 36);
  *(_DWORD *)(v9 + 100) = v57;
  *(_DWORD *)(v9 + 96) = v58;
  *(_WORD *)(v9 + 186) = *(_WORD *)(v56 + 2);
  CmpAssignSecurityToKcb(v9, *(unsigned int *)(v56 + 44), 0i64, 0, 0);
  CmpCleanUpSubKeyInfo(v9, 1);
  ++*(_QWORD *)(v9 + 304);
  *(_QWORD *)(v9 + 168) = *(_QWORD *)(v56 + 4);
  *(_WORD *)(v9 + 176) = *(_WORD *)(v56 + 52);
  *(_WORD *)(v9 + 178) = *(_WORD *)(v56 + 60);
  *(_DWORD *)(v9 + 180) = *(_DWORD *)(v56 + 64);
  *(_DWORD *)(v9 + 184) ^= (*(_DWORD *)(v9 + 184) ^ *(unsigned __int16 *)(v56 + 54)) & 0xF;
  *(_DWORD *)(v9 + 184) ^= ((unsigned __int8)*(_DWORD *)(v9 + 184) ^ (unsigned __int8)*(_WORD *)(v56 + 54)) & 0xF0;
  v59 = *(_QWORD *)(v9 + 32);
  *(_BYTE *)(v9 + 185) = *(_BYTE *)(v56 + 55);
  (*(void(__fastcall **)(__int64, int *))(v59 + 16))(v59, v85);
  *(_WORD *)(v9 + 8) = 64;
  if( CmpDeleteTree(v10, CellIndex) )
    CmpFreeKeyByCell(v10, CellIndex, 0);
  CmpReportNotify(v9, 0i64, 1i64, (_LOOKASIDE_LIST_EX *)&DeferredPostAsync);
  if( !CmpProfileLoaded )
  {
    CmpGlobalQuotaAllowed = CmpGlobalQuota;
    CmpProfileLoaded = 1;
  }
  CmpDrainDelayDerefContext((UINT64 **)a2a);
  CmpUnlockRegistry();
  v4 = 0;
  CmpDestroyHive(P);
  P = 0i64;
  CmpSignalDeferredPosts(&DeferredPostAsync);
LABEL_119:
  CmpDrainDelayDerefContext((UINT64 **)a2a);
  if( v4 )
    CmpUnlockRegistry();
  if( P )
  {
    CmpDestroyHive(P);
    P = 0i64;
  }
  if( v89 )
    (*(void(__fastcall **)(UINT64, int *))(v10 + 16))(v10, v86);
  if( v8 )
    (*(void(__fastcall **)(UINT64, int *))(v10 + 16))(v10, v74);
  if( v77 )
    (*(void(__fastcall **)(UINT64, _HV_GET_CELL_CONTEXT *))(v10 + 16))(v10, &v82);
  CmpCleanupRollbackPacket((INT64)v79);
  CmpTraceHiveRestoreStop((unsigned int)Hive);
  return(unsigned int)Hive;
}

Referenced by:

NtRestoreKey