PspAllocateThread

NTSTATUS __stdcall PspAllocateThread(
        _EPROCESS *Process,
        _OBJECT_ATTRIBUTES *ObjectAttributes,
        INT64 PreviousMode,
        PSP_CREATE_PROCESS_CONTEXT *CreateContext,
        _CONTEXT *ThreadContext,
        _PSP_USER_BASES *UserBases,
        VOID *StartRoutine,
        VOID *a8,
        VOID *StartContext,
        PSP_CREATE_THREAD_FLAGS *CreateFlags,
        _ETHREAD **NewThread,
        PSP_STACK_ALLOCATION_STATE *StackAllocationState,
        PSP_OBJECT_CREATION_STATE *ThreadAccessState){
  char v14; 
  PSP_STACK_ALLOCATION_STATE *v17; 
  _ETHREAD *CurrentThread; 
  __int64 v19; 
  __int64 v20; 
  PSP_CREATE_PROCESS_CONTEXT v21; 
  _QWORD *v22; 
  NTSTATUS v23; 
  _KNODE *v24; 
  _GROUP_AFFINITY *v25; 
  INT64 v26; 
  size_t v27; 
  _BYTE *v28; 
  unsigned __int16 v29; 
  UINT64 v30; 
  UINT64 v31; 
  char *v33; 
  __int64 v34; 
  int v35; 
  _EX_PUSH_LOCK *v36; 
  VOID *Handle; 
  _EX_PUSH_LOCK *v38; 
  _PS_INITIAL_TEB *v39; 
  int v40; 
  __int16 v41; 
  __int16 v42; 
  __int16 v43; 
  PSP_STACK_ALLOCATION_STATE *v44; 
  _PSP_STACK_ALLOCATION_STATE *v45; 
  __int64 v46; 
  NTSTATUS v47; 
  __int64 v48; 
  char *v49; 
  _EWOW64PROCESS *v50; 
  unsigned __int64 Rip; 
  __int64 v52; 
  VOID **PoolWithTag; 
  char *ExtendedFeature; 
  _EWOW64PROCESS *WoW64Process; 
  __int64 v56; 
  PSP_STACK_ALLOCATION_STATE *v57; 
  _EWOW64PROCESS *v58; 
  int inited; 
  void *v60; 
  _HANDLE_TABLE_ENTRY_INFO *ExtraInfo; 
  _HANDLE_TABLE_ENTRY_INFO *ExtraInfoa; 
  _HANDLE_TABLE_ENTRY_INFO *ExtraInfob; 
  UINT64 ObjectBodySize; 
  UINT64 PagedPoolCharge; 
  UINT64 NonPagedPoolCharge; 
  int v67; 
  char v68; 
  __int16 v69; 
  int PreferredNode; 
  PS_INITIAL_TEB *InitialTeb; 
  VOID *ObjectPointer; 
  _TEB *Teb; 
  _PSP_STACK_ALLOCATION_STATE *v74; 
  PSP_STACK_ALLOCATION_STATE *v75; 
  UINT64 ContextLength; 
  __int64 v77; 
  __int64 v78; 
  __int64 v79; 
  _ETHREAD *Thread; 
  _EPROCESS *v81; 
  PSP_CREATE_PROCESS_CONTEXT *v82; 
  _CONTEXT *v83; 
  _EX_PUSH_LOCK *PushLock; 
  _PSP_STACK_ALLOCATION_STATE v85; 
  __int64 v86; 
  __int64 v87; 
  PSP_STACK_ALLOCATION_STATE v88; 
  int v89; 
  PSP_STACK_ALLOCATION_STATE v90; 
  int v91; 
  char *v92; 
  char *v93; 
  PSP_CREATE_THREAD_FLAGS *v94; 
  _KAPC_STATE ApcState; 
  char ProbeMode; 

  ProbeMode = PreviousMode;
  v14 = PreviousMode;
  v81 = Process;
  PushLock = (_EX_PUSH_LOCK *)ObjectAttributes;
  v82 = CreateContext;
  v83 = ThreadContext;
  v77 = (__int64)UserBases;
  v94 = CreateFlags;
  v74 = (_PSP_STACK_ALLOCATION_STATE *)NewThread;
  v17 = StackAllocationState;
  v75 = StackAllocationState;
  memset(&ApcState, 0, sizeof(ApcState));
  Teb = 0i64;
  v78 = 0i64;
  ObjectPointer = 0i64;
  *(_DWORD *)(&v85.0 + 1) = 0;
  *(_WORD *)((char *)&v85.ZeroBits + 1) = 0;
  HIBYTE(v85.ZeroBits) = 0;
  LODWORD(ContextLength) = 0;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  Thread = CurrentThread;
  PreferredNode = 0;
  if( UserBases )
    v19 = *(_QWORD *)UserBases;
  else
    v19 = 0i64;
  v79 = v19;
  InitialTeb = (PS_INITIAL_TEB *)v19;
  if( !CreateContext )
    goto LABEL_22;
  v20 = 0i64;
  v21 = CreateContext[1];
  v22 = (_QWORD *)((unsigned __int64)(CreateContext + 80) & -(__int64)((v21 & 0x1000) != 0));
  if( (v21 & 0x4000) != 0 )
    v20 = (__int64)*(&KiProcessorBlock + (unsigned int)CreateContext[63]);
  if( v20 )
  {
    if( v22 )
    {
      if( *(unsigned __int8 *)(v20 + 208) != *(_WORD *)(((unsigned __int64)(CreateContext + 80) & -(__int64)((CreateContext[1] & 0x1000) != 0))
                                                       + 8)
        || *v22 && (*v22 & *(_QWORD *)(v20 + 200)) == 0i64 )
      {
        v23 = -1073741776;
LABEL_34:
        ObfDereferenceObjectWithTag(Process, 0x72437350ui64);
        return v23;
      }
    }
    else
    {
      CreateContext[1] = v21 | 0x1000;
      *((_WORD *)CreateContext + 164) = *(unsigned __int8 *)(v20 + 208);
      *((_QWORD *)CreateContext + 40) = KeActiveProcessors.Bitmap[*(unsigned __int8 *)(v20 + 208)];
    }
    PreferredNode = *(unsigned __int16 *)(*(_QWORD *)(v20 + 192) + 146i64) + 1;
    goto LABEL_18;
  }
  if( v22 && *v22 )
  {
    v24 = KeSelectNodeForAffinity((_GROUP_AFFINITY *)((unsigned __int64)(CreateContext + 80) & -(__int64)((CreateContext[1] & 0x1000) != 0)));
    PreferredNode = v24->Affinity.Reserved[0] + 1;
    CreateContext[1] = v21 | 0x4000;
    CreateContext[63] = (unsigned __int16)KeSelectIdealProcessor(v24, v25, 0i64);
    v17 = v75;
    CurrentThread = Thread;
LABEL_18:
    v14 = ProbeMode;
  }
  if( (CreateContext[1] & 0x8000) != 0 && (Process->WoW64Process || Process != CurrentThread->Tcb.Process) )
    goto LABEL_24;
LABEL_22:
  v17[96] = 0;
  *((_BYTE *)v17 + 388) = v14;
  if( ThreadContext )
  {
    if( Process == PsInitialSystemProcess )
    {
LABEL_24:
      v23 = -1073741811;
      goto LABEL_34;
    }
    if( ObjectAttributes )
    {
      if( v14 == 1 && ((unsigned __int8)ObjectAttributes & 3) != 0 )
        ExRaiseDatatypeMisalignment();
      v17[96] = ObjectAttributes->Attributes & (v14 != 0 ? 7666 : 73714);
    }
  }
  else if( ObjectAttributes )
  {
    v17[96] = ObjectAttributes->Attributes & 0x11FF2;
  }
  v68 = PoEnergyEstimationEnabled();
  LOBYTE(v26) = -v68;
  v27 = v68 != 0 ? 2400 : 2200;
  KeQueryMaximumGroupCount(v26, v28);
  v31 = v29;
  LODWORD(v75) = 0;
  if( v29 > 1u )
  {
    LODWORD(v75) = (v68 != 0 ? 2407 : 2207) & 0xFFFFFFF8;
    v27 = (_DWORD)v75 + 8 * v29;
  }
  LODWORD(NonPagedPoolCharge) = v27;
  LODWORD(PagedPoolCharge) = 0;
  LODWORD(ObjectBodySize) = v27;
  LOBYTE(v30) = ProbeMode;
  LOBYTE(v31) = ProbeMode;
  v23 = ObCreateObjectEx(
          v31,
          (_OBJECT_TYPE *)PsThreadType,
          ObjectAttributes,
          v30,
          ExtraInfo,
          ObjectBodySize,
          PagedPoolCharge,
          NonPagedPoolCharge,
          &ObjectPointer,
          0i64);
  v67 = v23;
  if( v23 < 0 )
    goto LABEL_34;
  v33 = (char *)ObjectPointer;
  memset(ObjectPointer, 0i64, v27);
  if( v68 )
  {
    *((_QWORD *)v33 + 191) = v33 + 2200;
    _interlockedbittestandset((volatile signed __int32 *)v33, 0x15u);
    v33 = (char *)ObjectPointer;
  }
  if( KiSchedulerAssistThreadFlagEnabled )
  {
    _interlockedbittestandset((volatile signed __int32 *)v33, 0x16u);
    v33 = (char *)ObjectPointer;
  }
  v34 = (unsigned int)v75;
  if( (_DWORD)v75 )
  {
    *((_DWORD *)v33 + 324) |= 0x20000u;
    *((_QWORD *)v33 + 192) = &v33[v34];
  }
  ExInitializePushLock((PULONG_PTR)v33 + 159);
  v75 = (PSP_STACK_ALLOCATION_STATE *)(v33 + 1144);
  *((_QWORD *)v33 + 143) = Process->UniqueProcessId;
  v35 = *(_DWORD *)StartContext;
  if( (*(_DWORD *)StartContext & 4) != 0 )
  {
    *((_DWORD *)v33 + 324) |= 4u;
    v35 = *(_DWORD *)StartContext;
  }
  if( (v35 & 0x200) != 0 )
    *((_DWORD *)v33 + 29) |= 0x200000u;
  v36 = (_EX_PUSH_LOCK *)(v33 + 1280);
  PushLock = (_EX_PUSH_LOCK *)(v33 + 1280);
  *((_QWORD *)v33 + 160) = 0i64;
  *((_DWORD *)v33 + 322) = 7;
  KeInitializeSemaphore((PRKSEMAPHORE)(v33 + 1160), 0, 1);
  *((_QWORD *)v33 + 136) = v33 + 1080;
  *((_QWORD *)v33 + 135) = v33 + 1080;
  *((_QWORD *)v33 + 173) = v33 + 1376;
  *((_QWORD *)v33 + 172) = v33 + 1376;
  *((_QWORD *)v33 + 175) = v33 + 1392;
  *((_QWORD *)v33 + 174) = v33 + 1392;
  *((_QWORD *)v33 + 176) = 0i64;
  *((_QWORD *)v33 + 186) = v33 + 1480;
  *((_QWORD *)v33 + 185) = v33 + 1480;
  *((_QWORD *)v33 + 187) = 0i64;
  *((_QWORD *)v33 + 151) = v33 + 1200;
  *((_QWORD *)v33 + 150) = v33 + 1200;
  *((_QWORD *)v33 + 177) = 0i64;
  *((_QWORD *)v33 + 140) = 0i64;
  *((_QWORD *)v33 + 142) = v33 + 1128;
  *((_QWORD *)v33 + 141) = v33 + 1128;
  *((_QWORD *)v33 + 193) = -3i64;
  if( KeQuerySystemTimeUnsafe() )
  {
    KeQuerySystemTimePrecise((_LARGE_INTEGER *)v33 + 134);
  }
  else
  {
    v33 = (char *)ObjectPointer;
    *((_QWORD *)ObjectPointer + 134) = *(_QWORD *)&KUSER_SHARED_DATA.SystemTime.LowPart;
  }
  *((_QWORD *)v33 + 198) = v33 + 1576;
  *((_QWORD *)v33 + 197) = v33 + 1576;
  *((_QWORD *)v33 + 199) = 0i64;
  *((_QWORD *)v33 + 201) = v33 + 1600;
  *((_QWORD *)v33 + 200) = v33 + 1600;
  ExAcquirePushLockExclusiveEx(v36, 0i64);
  Handle = ExCreateHandleEx(PspCidTable, v33, 0i64, 0i64, 0i64);
  *((_QWORD *)v33 + 144) = Handle;
  if( !Handle )
  {
    v38 = PushLock;
    if( (_InterlockedExchangeAdd64(&PushLock->_bf_0, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
      ExfTryToWakePushLock(v38);
    KeAbPostRelease(v38);
    v23 = -1073741670;
    v67 = -1073741670;
    v33 = (char *)ObjectPointer;
    goto LABEL_121;
  }
  if( ThreadContext )
  {
    v40 = *(_DWORD *)StartContext;
    v41 = (16 * (*(_DWORD *)StartContext & 0x40)) | 8;
    if( (*(_DWORD *)StartContext & 2) == 0 )
      v41 = 16 * (v40 & 0x40);
    v42 = v41 | 0x2000;
    if( (v40 & 0x80u) == 0 )
      v42 = v41;
    v43 = v42 | 0x4000;
    if( (v40 & 0x100) == 0 )
      v43 = v42;
    v69 = v43;
    v44 = (PSP_STACK_ALLOCATION_STATE *)v74;
    if( !v74 )
    {
      if( !Process->PicoContext )
      {
        v49 = (char *)Thread->Tcb.Teb;
        Teb = (_TEB *)v49;
        *((_QWORD *)v33 + 138) = PsQueryThreadStartAddress(Thread, 1ui64);
        *((_QWORD *)v33 + 154) = Thread->Win32StartAddress;
        *((_DWORD *)v33 + 325) |= 0x10u;
        if( (Process->MitigationFlags2 & 0x4000) != 0
          && (ThreadContext->ContextFlags & 0x100040) == 1048640
          && (*(_DWORD *)((_BYTE *)&ThreadContext[1].P1Home + SLODWORD(ThreadContext[1].P3Home)) & 0x800i64) != 0 )
        {
          ExtendedFeature = RtlLocateExtendedFeature(&ThreadContext[1], 0xBu, 0i64);
          if( ExtendedFeature )
          {
            if( (*ExtendedFeature & 1) != 0 && *((_QWORD *)ExtendedFeature + 1) )
              *((_DWORD *)v33 + 29) |= 0x100000u;
          }
        }
        WoW64Process = Process->WoW64Process;
        if( WoW64Process )
        {
          v56 = 14392i64;
          if( WoW64Process->Machine != 0x8664 )
            v56 = 12288i64;
          v77 = v56;
        }
        else
        {
          v77 = 6200i64;
        }
        KiStackAttachProcess(Process, 0i64, &ApcState);
        if( MmSecureVirtualMemoryEx((unsigned __int64)v49, v77, 4, 0) )
        {
          v57 = v75;
          *((_OWORD *)v49 + 4) = *(_OWORD *)v75;
          *(_OWORD *)(v49 + 2008) = *(_OWORD *)v57;
          *((_DWORD *)v49 + 1511) = 0;
          *((_DWORD *)v49 + 1530) = 0;
          *((_WORD *)v49 + 3063) &= 0x62Cu;
          *((_WORD *)v49 + 3063) |= v69 | 0x40;
          v58 = Process->WoW64Process;
          if( v58 )
          {
            if( v58->Machine == 0x8664 )
            {
              v92 = v49 + 0x2000;
              *((_QWORD *)v49 + 1032) = *(_QWORD *)v57;
              *((_QWORD *)v49 + 1033) = *((_QWORD *)v33 + 144);
              *((_QWORD *)v49 + 1275) = *(_QWORD *)v57;
              *((_QWORD *)v49 + 1276) = *((_QWORD *)v33 + 144);
              *((_DWORD *)v49 + 3559) = 0;
              *((_DWORD *)v49 + 3578) = 0;
              *((_WORD *)v49 + 7159) &= 0x62Cu;
              *((_WORD *)v49 + 7159) |= v69 | 0x40;
            }
            else
            {
              v93 = v49 + 0x2000;
              v88 = *v57;
              *((_DWORD *)v49 + 2056) = v88;
              v89 = *((_DWORD *)v33 + 288);
              *((_DWORD *)v49 + 2057) = v89;
              v90 = *v57;
              *((_DWORD *)v49 + 2477) = v90;
              v91 = *((_DWORD *)v33 + 288);
              *((_DWORD *)v49 + 2478) = v91;
              *((_DWORD *)v49 + 3047) = 0;
              *((_DWORD *)v49 + 3057) = 0;
              *((_WORD *)v49 + 6117) &= 0x62Cu;
              *((_WORD *)v49 + 6117) |= v69 | 0x40;
            }
          }
        }
        else
        {
          v23 = -1073741503;
          v67 = -1073741503;
        }
LABEL_110:
        KiUnstackDetachProcess(&ApcState, 0i64);
        if( v23 < 0 )
          goto LABEL_121;
        goto LABEL_111;
      }
      Rip = ThreadContext->_Rip;
      *((_QWORD *)v33 + 138) = Rip;
      *((_QWORD *)v33 + 154) = Rip;
      v52 = v77;
      *((_QWORD *)v33 + 189) = *(_QWORD *)(v77 + 8);
      *((_QWORD *)v33 + 190) = *(_QWORD *)(v52 + 16);
      _interlockedbittestandset((volatile signed __int32 *)v33, 0x1Au);
      RtlGetExtendedContextLength(KUSER_SHARED_DATA.XState.EnabledFeatures != 0 ? 1048671 : 1048607, &ContextLength);
      PoolWithTag = ExAllocatePoolWithTag(1ui64, (unsigned int)ContextLength, 1666413392i64);
      v33 = (char *)ObjectPointer;
      *((_QWORD *)ObjectPointer + 195) = PoolWithTag;
      if( !PoolWithTag )
      {
        v23 = -1073741670;
        v67 = -1073741670;
        goto LABEL_121;
      }
      v49 = (char *)Teb;
LABEL_111:
      inited = KeInitThread(
                 (_KTHREAD *)v33,
                 *((_QWORD *)v33 + 138),
                 (__int64)ThreadContext,
                 (__int64)v49,
                 (__int64)Process,
                 PreferredNode);
      goto LABEL_113;
    }
    if( (Process->MitigationFlags2 & 0x4000) != 0 && (!CreateContext || (CreateContext[1] & 0x8000) == 0) )
      *((_DWORD *)v33 + 29) |= 0x100000u;
    LODWORD(ExtraInfoa) = PreferredNode;
    if( Process->WoW64Process )
    {
      v85.StackAllocationFlags = 0;
      v86 = 0x8000i64;
      v87 = 0x40000i64;
      *(_QWORD *)&v85.StackSize = 0i64;
      v23 = PspSetupUserStack(
              (ULONG_PTR)Process,
              ThreadContext,
              InitialTeb,
              (PSP_STACK_ALLOCATION_STATE *)&v85,
              (UINT64)ExtraInfoa);
      v67 = v23;
      if( v23 >= 0 )
      {
        v45 = v74;
        v74->StackAllocationFlags ^= (v85.StackAllocationFlags ^ v74->StackAllocationFlags) & 2;
        v46 = (__int64)InitialTeb;
        v47 = PspWow64SetupUserStack(Process, (INT64)v39, (INT64)InitialTeb, (CHAR *)v45);
LABEL_68:
        v23 = v47;
        v67 = v47;
LABEL_73:
        if( v23 < 0 )
          goto LABEL_121;
        v48 = v78;
        if( CreateContext && (CreateContext[1] & 0x8000) != 0 && ((unsigned int)KeFeatureBits & 0x10000000) == 0 )
          v48 = 0x100000000i64;
        v23 = MmCreateTeb(Process, v46, v75, (VOID **)v48, (__int64)&Teb);
        v67 = v23;
        if( v23 < 0 )
          goto LABEL_121;
        *((_QWORD *)v33 + 138) = ThreadContext->_Rip;
        *((_QWORD *)v33 + 154) = ThreadContext->_Rcx;
        v49 = (char *)Teb;
        if( Process->WoW64Process )
        {
          v23 = PspWow64InitThread((ULONG_PTR)Process);
          v67 = v23;
          if( v23 < 0 )
            goto LABEL_121;
        }
        if( v69 )
        {
          KiStackAttachProcess(Process, 0i64, &ApcState);
          *((_WORD *)v49 + 3063) = v69;
          v50 = Process->WoW64Process;
          if( v50 )
          {
            if( v50->Machine == 0x8664 )
            {
              v92 = v49 + 0x2000;
              *((_WORD *)v49 + 7159) = v69;
            }
            else
            {
              v93 = v49 + 0x2000;
              *((_WORD *)v49 + 6117) = v69;
            }
          }
          v23 = 0;
          v67 = 0;
          goto LABEL_110;
        }
        goto LABEL_111;
      }
    }
    else
    {
      v23 = PspSetupUserStack((ULONG_PTR)Process, ThreadContext, InitialTeb, v44, (UINT64)ExtraInfoa);
      v67 = v23;
      if( v23 >= 0 && (*((_DWORD *)v33 + 29) & 0x100000) != 0 )
      {
        LODWORD(ExtraInfob) = PreferredNode;
        v46 = (__int64)InitialTeb;
        v47 = PspSetupUserShadowStack(Process, (INT32 *)ThreadContext, (INT64)InitialTeb, v74, (UINT64)ExtraInfob);
        goto LABEL_68;
      }
    }
    v46 = (__int64)InitialTeb;
    goto LABEL_73;
  }
  *((_QWORD *)v33 + 138) = StartRoutine;
  *((_QWORD *)v33 + 154) = StartRoutine;
  inited = KeInitThread((_KTHREAD *)v33, (__int64)a8, 0i64, 0i64, (__int64)Process, PreferredNode);
  v49 = (char *)Teb;
LABEL_113:
  v67 = inited;
  v23 = inited;
  if( inited < 0 )
  {
    if( !v49 || !v74 )
      goto LABEL_121;
    goto LABEL_120;
  }
  if( CreateContext )
  {
    if( (CreateContext[1] & 0x8000) != 0 )
    {
      v23 = PspUmsInitThread((INT64)v33, ProbeMode, (__int64)CreateContext, (__int64)v49);
      v67 = v23;
      if( v23 < 0 )
      {
LABEL_120:
        MmDeleteTeb((ULONG_PTR)Process, v49);
LABEL_121:
        if( v74 && v74->StackAllocationFlags )
          PspDeleteUserStack(Process, v39, (_PSP_STACK_ALLOCATION_STATE *)InitialTeb);
        v60 = (void *)*((_QWORD *)v33 + 195);
        if( v60 )
        {
          ExFreePoolWithTag(v60, 0x63537350u);
          *((_QWORD *)v33 + 195) = 0i64;
        }
        if( *((_QWORD *)v33 + 144) )
        {
          if( (_InterlockedExchangeAdd64((volatile signed __int64 *)v33 + 160, 0xFFFFFFFFFFFFFFFFui64) & 6) == 2 )
            ExfTryToWakePushLock((_EX_PUSH_LOCK *)v33 + 160);
          KeAbPostRelease(v33 + 1280);
          v23 = v67;
          v33 = (char *)ObjectPointer;
        }
        if( !*((_QWORD *)v33 + 68) )
          ObfDereferenceObjectWithTag(Process, 0x72437350ui64);
        HalPutDmaAdapter((PADAPTER_OBJECT)v33);
        return v23;
      }
    }
  }
  *(_QWORD *)v94 = v33;
  return 0;
}

Referenced by:

NtCreateUserProcess
PspCreatePicoThread
PspCreateThread