ExDupHandleTable

NTSTATUS __stdcall ExDupHandleTable(
        _EPROCESS *Process,
        _HANDLE_TABLE *OldHandleTable,
        UINT64 DupHandleCount,
        VOID **DupHandleList,
        _HANDLE_TABLE **NewHandleTable){
  unsigned __int64 NextHandleNeedingPool; 
  _HANDLE_TABLE **v6; 
  unsigned int v7; 
  _HANDLE_TABLE *v8; 
  unsigned __int64 v9; 
  _HANDLE_TABLE_ENTRY *v10; 
  unsigned __int64 v11; 
  int v12; 
  _HANDLE_TABLE_ENTRY *v13; 
  _HANDLE_TABLE *v14; 
  _HANDLE_TABLE *v15; 
  _ETHREAD *CurrentThread; 
  NTSTATUS v17; 
  _EXHANDLE v18; 
  _HANDLE_TABLE_ENTRY **p_FirstFreeHandleEntry; 
  _HANDLE_TABLE_ENTRY *v20; 
  _HANDLE_TABLE_ENTRY *v21; 
  unsigned int v22; 
  _HANDLE_TABLE *v23; 
  _HANDLE_TABLE *v24; 
  _HANDLE_TABLE_ENTRY *v25; 
  unsigned int v26; 
  __int64 v27; 
  _LIST_ENTRY *v28; 
  _LIST_ENTRY *p_HandleTableList; 
  __int64 v31; 
  _HANDLE_TABLE_ENTRY *v32; 
  NTSTATUS v33; 
  UINT8 HandleTableEntrySlow; 
  unsigned int v35; 
  VOID **v36; 
  VOID *v37; 
  _HANDLE_TABLE *v38; 
  unsigned int v39; 
  _HANDLE_TABLE_ENTRY *v40; 
  unsigned __int64 v41; 
  _HANDLE_TABLE *v42; 
  char *v43; 
  _HANDLE_TABLE_ENTRY *v44; 
  _ETHREAD *v45; 
  _EPROCESS *Processa; 
  int v48; 

  Processa = Process;
  NextHandleNeedingPool = OldHandleTable->NextHandleNeedingPool;
  v6 = NewHandleTable;
  v41 = NextHandleNeedingPool;
  v7 = DupHandleCount;
  v8 = OldHandleTable;
  v9 = (unsigned int)NextHandleNeedingPool;
  *NewHandleTable = 0i64;
  if( (_DWORD)DupHandleCount )
  {
    if( (*(_BYTE *)DupHandleList & 3) == 0 )
    {
      v35 = 1;
      if( (unsigned int)DupHandleCount <= 1 )
      {
LABEL_55:
        v37 = DupHandleList[v7 - 1];
        if( (unsigned __int64)v37 < v9 )
        {
          v9 = (unsigned __int64)v37 + 4;
          goto LABEL_13;
        }
      }
      else
      {
        v36 = DupHandleList + 1;
        while( ((unsigned __int8)*v36 & 3) == 0 && *v36 > DupHandleList[v35 - 1] )
        {
          ++v35;
          ++v36;
          if( v35 >= v7 )
            goto LABEL_55;
        }
      }
    }
    return -1073741811;
  }
  if( !(_DWORD)NextHandleNeedingPool )
    goto LABEL_14;
  do
  {
    v10 = ExpLookupHandleTableEntry(v8, (_EXHANDLE)(v9 - 1024));
    v12 = 255;
    v13 = v10 + 255;
    while( (v13->VolatileLowValue & 0x40000) == 0 )
    {
      if( (v13[-1].VolatileLowValue & 0x40000) != 0 )
      {
        --v12;
        break;
      }
      if( (v13[-2].VolatileLowValue & 0x40000) != 0 )
      {
        v12 -= 2;
        break;
      }
      if( (v13[-3].VolatileLowValue & 0x40000) != 0 )
      {
        v12 -= 3;
        break;
      }
      if( (v13[-4].VolatileLowValue & 0x40000) != 0 )
      {
        v12 -= 4;
        break;
      }
      v13 -= 5;
      v12 -= 5;
      if( !v12 )
        break;
    }
    if( v12 )
      break;
    v9 = v11;
  }
  while( v11 );
LABEL_13:
  Process = Processa;
  v41 = v9;
LABEL_14:
  if( !v9 )
  {
    v38 = ExCreateHandleTable(Process, 1ui64);
    *NewHandleTable = v38;
    if( v38 )
      return 0;
    return -1073741670;
  }
  v14 = ExpAllocateHandleTable(Process, 0);
  *NewHandleTable = v14;
  v15 = v14;
  if( !v14 )
    return -1073741670;
  if( v14->NextHandleNeedingPool < v9 )
  {
    while( 1 )
    {
      HandleTableEntrySlow = ExpAllocateHandleTableEntrySlow(v15, 0i64);
      v15 = *NewHandleTable;
      if( !HandleTableEntrySlow )
        break;
      if( v15->NextHandleNeedingPool >= v9 )
        goto LABEL_17;
    }
    ExpFreeHandleTable(v15);
    *NewHandleTable = 0i64;
    return -1073741670;
  }
LABEL_17:
  LOBYTE(v15->Flags) |= 8u;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  --CurrentThread->Tcb.KernelApcDisable;
  v45 = CurrentThread;
  v42 = *NewHandleTable;
  v17 = 0;
  v39 = 0;
  v18 = 0i64;
  v48 = 0;
  p_FirstFreeHandleEntry = &(*NewHandleTable)->FreeLists[0].FirstFreeHandleEntry;
  do
  {
    v44 = ExpLookupHandleTableEntry(OldHandleTable, v18);
    v20 = ExpLookupHandleTableEntry(*v6, v18);
    v24 = *v6;
    v25 = v21 + 1;
    v40 = v20;
    v26 = 1;
    v43 = (char *)((char *)v20 - (char *)v21);
    while( v17 >= 0 )
    {
      if( v7 && DupHandleList[v22] != (VOID *)(*(_QWORD *)&v18 + 4 * v26) )
        goto LABEL_24;
      if( (v25->VolatileLowValue & 0x40000) == 0 )
        goto LABEL_22;
      v31 = v26;
      v32 = &v21[v31];
      if( !ExLockHandleTableEntry(v23, &v21[v31]) )
      {
        v17 = v48;
LABEL_22:
        if( v7 )
        {
          v17 = -1073741811;
          v48 = -1073741811;
        }
LABEL_24:
        v27 = v26;
        *p_FirstFreeHandleEntry = &v40[v27];
        v42->FreeLists[0].LastFreeHandleEntry = &v40[v27];
        p_FirstFreeHandleEntry = &v40[v27].NextFreeHandleEntry;
        *(__int64 *)((char *)&v25->LowValue + (_QWORD)v43) = 0i64;
        goto LABEL_25;
      }
      if( (v25->VolatileLowValue & 0x40000) == 0 )
      {
        ExUnlockHandleTableEntry(OldHandleTable, v32);
        if( v7 )
        {
          v17 = -1073741811;
          v48 = -1073741811;
        }
        else
        {
          v17 = v48;
        }
        goto LABEL_24;
      }
      v33 = ExpDuplicateSingleHandle(
              Processa,
              (PVOID)(*(_QWORD *)&v18 + 4 * v26),
              OldHandleTable,
              v32,
              *NewHandleTable,
              &v40[v31],
              DupHandleList != 0i64);
      v48 = v33;
      v17 = v33;
      if( v33 < 0 )
        goto LABEL_24;
      if( v33 == 263 )
      {
        v17 = 0;
        v48 = 0;
        goto LABEL_24;
      }
      v24 = *NewHandleTable;
      ++(*NewHandleTable)->FreeLists[0].HandleCount;
      if( v7 && v39 < v7 - 1 )
        ++v39;
      if( !v24->DebugInfo )
      {
        v6 = NewHandleTable;
        goto LABEL_26;
      }
      ExpUpdateDebugInfo(v24, (_ETHREAD *)KeGetCurrentThread(), (VOID *)(*(_QWORD *)&v18 + 4 * v26), 1ui64);
LABEL_25:
      v6 = NewHandleTable;
      v24 = *NewHandleTable;
LABEL_26:
      v21 = v44;
      ++v26;
      v22 = v39;
      ++v25;
      v23 = OldHandleTable;
      if( v26 >= 0x100 )
        goto LABEL_27;
    }
    memset(&v40[v26], 0i64, 4096 - 16 * v26);
LABEL_27:
    *(_QWORD *)&v18 += 1024i64;
  }
  while( v18.Value < v41 );
  *p_FirstFreeHandleEntry = 0i64;
  if( v17 < 0 )
  {
    LOBYTE(v24->Flags) |= 4u;
    v24->HandleTableList.Blink = &v24->HandleTableList;
    v24->HandleTableList.Flink = &v24->HandleTableList;
  }
  else
  {
    v24->FreeLists[0].HighWaterMark = v24->FreeLists[0].HandleCount;
    ExAcquirePushLockExclusiveEx(&HandleTableListLock, 0i64);
    v28 = (_LIST_ENTRY *)qword_140D2DB48;
    p_HandleTableList = &(*v6)->HandleTableList;
    if( *(__int64 **)qword_140D2DB48 != &HandleTableListHead )
      __fastfail(3u);
    p_HandleTableList->Flink = (_LIST_ENTRY *)&HandleTableListHead;
    p_HandleTableList->Blink = v28;
    v28->Flink = p_HandleTableList;
    qword_140D2DB48 = (__int64)p_HandleTableList;
    if( (_InterlockedExchangeAdd64(&HandleTableListLock._bf_0, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
      ExfTryToWakePushLock(&HandleTableListLock);
    KeAbPostRelease(&HandleTableListLock);
    v17 = 0;
  }
  KeLeaveCriticalRegionThread(&v45->Tcb);
  return v17;
}

Referenced by:

ObInitProcess