CmpCreateKeyControlBlock

INT64 __fastcall CmpCreateKeyControlBlock(
        _CMHIVE *Hive,
        UINT64 Cell,
        _CM_KEY_CONTROL_BLOCK *ParentKcb,
        _CM_KEY_CONTROL_BLOCK *NextLayerKcb,
        UINT64 ControlFlags,
        _UNICODE_STRING *KeyName,
        _CM_COMPONENT_HASH ComponentHash,
        _CM_PATH_HASH PathHash,
        _CM_KEY_CONTROL_BLOCK **ResultKcb){
  ULONG_PTR v9; 
  int v11; 
  int v12; 
  unsigned int Hash; 
  _UNICODE_STRING *v15; 
  _CM_KEY_CONTROL_BLOCK *KcbInHashEntryByName; 
  _CM_KEY_CONTROL_BLOCK *v17; 
  PSLIST_ENTRY KeyControlBlock; 
  UINT8 *v19; 
  UINT64 v20; 
  struct _SLIST_ENTRY *v21; 
  _QWORD *v22; 
  _CM_NAME_CONTROL_BLOCK *NameControlBlock; 
  __int64 v24; 
  INT64 v25; 
  __int64 v26; 
  int v27; 
  _BYTE *v28; 
  unsigned int v29; 
  char v30; 
  __int64 v31; 
  __int64 v32; 
  bool v33; 
  int v34; 
  unsigned int v35; 
  unsigned __int64 v36; 
  INT64 result; 
  __int64 v38; 
  int LayerLink; 
  unsigned int *v40; 
  void *v41; 
  __int64 v42[2]; 
  unsigned int v43; 
  ULONG_PTR BugCheckParameter2; 
  BugCheckParameter2 = (ULONG_PTR)NextLayerKcb;
  v42[0] = 0i64;
  v9 = (ULONG_PTR)NextLayerKcb;
  v11 = *((_DWORD *)Hive + 40);
  v12 = Cell;
  LODWORD(v42[0]) = -1;
  if( (v11 & 0x20) != 0 && *((struct _KTHREAD **)Hive + 526) != KeGetCurrentThread() )
    return 3221225524i64;
  Hash = PathHash.Hash;
  v15 = KeyName;
  KcbInHashEntryByName = (_CM_KEY_CONTROL_BLOCK *)CmpFindKcbInHashEntryByName(
                                                    (INT64)Hive,
                                                    PathHash.Hash,
                                                    (INT64)ParentKcb,
                                                    KeyName);
  v17 = KcbInHashEntryByName;
  if( KcbInHashEntryByName )
  {
    CmpReferenceKeyControlBlockLockNotHeld(KcbInHashEntryByName);
    result = 0i64;
    *ResultKcb = v17;
    return result;
  }
  if( v15->Length + 2 + (unsigned int)CmpKeyFullNameLength((INT64)ParentKcb) > 0xFFFF )
    return 3221225485i64;
  KeyControlBlock = CmpAllocateKeyControlBlock();
  v20 = (UINT64)KeyControlBlock;
  if( !KeyControlBlock )
    return 3221225626i64;
  v21 = KeyControlBlock + 1;
  v22 = &KeyControlBlock[7].Next + 1;
  v22[1] = v22;
  *v22 = v22;
  *(_QWORD *)(v20 + 136) = 0i64;
  *(_QWORD *)(v20 + 144) = 0i64;
  *(_QWORD *)(v20 + 152) = 0i64;
  *(_QWORD *)(v20 + 160) = 0i64;
  *(_QWORD *)(v20 + 48) = 0i64;
  *(_QWORD *)v20 = 1i64;
  *(_QWORD *)(v20 + 32) = Hive;
  *(_DWORD *)(v20 + 40) = v12;
  *(_DWORD *)(v20 + 16) = Hash;
  *(_QWORD *)(v20 + 216) = v20 + 208;
  *(_QWORD *)(v20 + 208) = v20 + 208;
  *(_QWORD *)(v20 + 240) = 0i64;
  *(_DWORD *)(v20 + 248) = 0;
  *(_QWORD *)(v20 + 256) = 0i64;
  *(_DWORD *)(v20 + 264) = 0;
  *(_QWORD *)(v20 + 272) = 0i64;
  *(_DWORD *)(v20 + 280) = 0;
  *(_QWORD *)(v20 + 288) = 0i64;
  *(_QWORD *)(v20 + 232) = v20 + 224;
  *(_QWORD *)(v20 + 224) = v20 + 224;
  *(_DWORD *)(v20 + 284) = -1;
  NameControlBlock = CmpGetNameControlBlock(v15, &ComponentHash, v19);
  *(_QWORD *)(v20 + 80) = NameControlBlock;
  if( !NameControlBlock )
  {
    LayerLink = -1073741670;
    goto LABEL_44;
  }
  v24 = *(unsigned int *)(v20 + 40);
  if( (_DWORD)v24 != -1 )
  {
    v25 = (*(__int64(__fastcall **)(_QWORD, __int64, __int64 *))(*(_QWORD *)(v20 + 32) + 8i64))(
            *(_QWORD *)(v20 + 32),
            v24,
            v42);
    if( CmpKeyNodeNeedsAccessBitUpdate(*(_QWORD *)(v20 + 32), v25) )
    {
      (*(void(__fastcall **)(__int64, __int64 *))(v26 + 16))(v26, v42);
      ExAcquirePushLockSharedEx(*(_QWORD *)(v20 + 32) + 72i64, 0i64);
      v25 = (*(__int64(__fastcall **)(_QWORD, _QWORD, __int64 *))(*(_QWORD *)(v20 + 32) + 8i64))(
              *(_QWORD *)(v20 + 32),
              *(unsigned int *)(v20 + 40),
              v42);
      CmpUpdateKeyNodeAccessBits(*(_QWORD *)(v20 + 32), v25, *(unsigned int *)(v20 + 40));
      v38 = *(_QWORD *)(v20 + 32);
      if( _InterlockedCompareExchange64((volatile signed __int64 *)(v38 + 72), 0i64, 17i64) != 17 )
        ExfReleasePushLockShared((INT64 *)(v38 + 72));
      KeAbPostRelease((PVOID)(v38 + 72));
    }
    *(_BYTE *)(v20 + 65) = *(_BYTE *)(v25 + 13) & 3;
    v27 = *(_DWORD *)(v25 + 36);
    *(_DWORD *)(v20 + 100) = *(_DWORD *)(v25 + 40);
    *(_DWORD *)(v20 + 96) = v27;
    *(_WORD *)(v20 + 186) = *(_WORD *)(v25 + 2);
    *(_DWORD *)(v20 + 112) = *(_DWORD *)(v25 + 20) + *(_DWORD *)(v25 + 24);
    *(_QWORD *)(v20 + 168) = *(_QWORD *)(v25 + 4);
    *(_WORD *)(v20 + 176) = *(_WORD *)(v25 + 52);
    *(_WORD *)(v20 + 178) = *(_WORD *)(v25 + 60);
    *(_DWORD *)(v20 + 180) = *(_DWORD *)(v25 + 64);
    *(_DWORD *)(v20 + 184) ^= (*(_DWORD *)(v20 + 184) ^ *(unsigned __int16 *)(v25 + 54)) & 0xF;
    *(_DWORD *)(v20 + 184) ^= ((unsigned __int8)*(_DWORD *)(v20 + 184) ^ (unsigned __int8)*(_WORD *)(v25 + 54)) & 0xF0;
    *(_BYTE *)(v20 + 185) = *(_BYTE *)(v25 + 55);
    LODWORD(v28) = KeAbPreAcquire((PVOID)(v20 + 48), 0i64, 1ui64);
    if( _interlockedbittestandset64((volatile signed __int32 *)(v20 + 48), 0i64) )
    {
      if( v28 )
        KeAbPostReleaseEx((PVOID)(v20 + 48), v28);
    }
    else
    {
      if( v28 )
        v28[26] |= 1u;
      *(_QWORD *)(v20 + 56) = KeGetCurrentThread();
    }
    v29 = *(_DWORD *)(v25 + 44);
    v43 = 0;
    v30 = 1;
    if( v29 == -1 )
    {
      *(_QWORD *)(v20 + 88) = 0i64;
LABEL_16:
      CmpUnlockKcb(v20);
      (*(void(__fastcall **)(_QWORD, __int64 *))(*(_QWORD *)(v20 + 32) + 16i64))(*(_QWORD *)(v20 + 32), v42);
      v9 = BugCheckParameter2;
      goto LABEL_17;
    }
    v31 = *(_QWORD *)(v20 + 32);
    ExAcquirePushLockSharedEx(v31 + 1776, 0i64);
    if( CmpFindSecurityCellCacheIndex(v31, v29, &v43) )
    {
      v32 = *(_QWORD *)(*(_QWORD *)(v31 + 1880) + 16i64 * v43 + 8);
    }
    else
    {
      v30 = 0;
      v32 = 0i64;
    }
    *(_QWORD *)(v20 + 88) = v32;
    ExReleasePushLockEx(v31 + 1776, 0i64);
    if( v30 )
      goto LABEL_16;
    CmpUnlockKcb(v20);
    LayerLink = -1073741670;
    (*((void(__fastcall **)(_CMHIVE *, __int64 *))Hive + 2))(Hive, v42);
LABEL_44:
    v40 = *(unsigned int **)(v20 + 80);
    if( v40 )
      CmpDereferenceNameControlBlockWithLock(v40);
    if( *(_QWORD *)(v20 + 72) )
      CmpDereferenceKeyControlBlockUnsafe((volatile INT64 *)ParentKcb);
    v41 = *(void **)(v20 + 192);
    if( v41 )
      ExFreePoolWithTag(v41, 0);
    *(_DWORD *)(v20 + 8) |= 0x80000u;
    CmpFreeKeyControlBlock((_CM_KEY_CONTROL_BLOCK *)v20);
    return(unsigned int)LayerLink;
  }
  if( ((ParentKcb->LayerSemantics - 1) & 0xFD) == 0 )
    *(_BYTE *)(v20 + 65) = 1;
  if( (ControlFlags & 1) != 0 )
    *(_WORD *)(v20 + 186) |= 4u;
LABEL_17:
  if( ParentKcb )
  {
    CmpReferenceKeyControlBlockUnsafe((volatile INT64 *)ParentKcb);
    v33 = (*(_DWORD *)(v20 + 184) & 0x40000) == 0;
    *(_QWORD *)(v20 + 72) = ParentKcb;
    v34 = *((_DWORD *)ParentKcb + 2);
    if( v33 )
      v35 = *(_DWORD *)(v20 + 8) ^ (*(_DWORD *)(v20 + 8) ^ (v34 + 0x200000)) & 0x7FE00000;
    else
      v35 = *(_DWORD *)(v20 + 8) ^ (*(_DWORD *)(v20 + 8) ^ v34) & 0x7FE00000;
  }
  else
  {
    v35 = *(_DWORD *)(v20 + 8) & 0x801FFFFF | 0x200000;
  }
  *(_DWORD *)(v20 + 8) = v35;
  if( v9 )
  {
    CmpLockKcbExclusive(v9);
    CmpTryToLockKcbExclusive(v20);
    LayerLink = CmpCreateLayerLink(v9);
    CmpUnlockKcb(v20);
    CmpUnlockKcb(v9);
    if( LayerLink < 0 )
      goto LABEL_44;
  }
  v36 = *(_QWORD *)(*(_QWORD *)(v20 + 32) + 1640i64)
      + 24
      * ((unsigned int)(*(_DWORD *)(*(_QWORD *)(v20 + 32) + 1648i64) - 1) & ((unsigned int)(101027
                                                                                          * (LODWORD(v21->Next) ^ (LODWORD(v21->Next) >> 9))) ^ ((unsigned __int64)(unsigned int)(101027 * (LODWORD(v21->Next) ^ (LODWORD(v21->Next) >> 9))) >> 9)));
  *(_QWORD *)(v20 + 24) = *(_QWORD *)(v36 + 16);
  *(_QWORD *)(v36 + 16) = v21;
  if( *((_BYTE *)Hive + 2936) == 1 )
    *(_WORD *)(v20 + 8) |= 0x20u;
  if( *(BOOLEAN **)((char *)&NlsMbCodePageTag + 7) )
    CmpEtwDumpKcb((_CM_KEY_CONTROL_BLOCK *)v20, 0x16u);
  *ResultKcb = (_CM_KEY_CONTROL_BLOCK *)v20;
  return 0i64;
}

Referenced by:

CmRenameKey
CmpCreateRegistryRoot
CmpDoParseKey
CmpWalkOneLevel