RtlpWow64CreateUserStack

NTSTATUS __stdcall RtlpWow64CreateUserStack(
        UINT64 CommittedStackSize,
        UINT64 MaximumStackSize,
        UINT64 ZeroBits,
        UINT64 PreferredNode,
        PS_INITIAL_TEB *InitialTeb,
        INT64 a6,
        INT64 a7,
        INT64 a8){
  int v8; 
  _PEB *Peb; 
  UINT64 v11; 
  unsigned __int64 v12; 
  unsigned __int64 v13; 
  NTSTATUS result; 
  __int64 v15; 
  unsigned __int64 v16; 
  int v17; 
  char *v18; 
  NTSTATUS v19; 
  __int64 v20; 
  __int64 v21; 
  UINT64 v22; 
  unsigned int v23; 
  UINT64 AllocationType; 
  UINT64 AllocationTypea; 
  UINT64 Protect; 
  UINT64 Protecta; 
  VOID *BaseAddress; 
  int v29; 
  UINT64 v30[2]; 
  UINT64 RegionSize; 
  UINT64 v32; 
  VOID *v33; 
  int ProcessInformation[4]; 
  unsigned __int64 v35; 
  UINT64 v36; 
  __int64 v37; 
  unsigned __int64 MinimumStackCommit; 
  UINT64 v39; 

  v39 = CommittedStackSize;
  v8 = PreferredNode;
  v30[0] = 0i64;
  v37 = 0i64;
  Peb = KeGetCurrentThread()->ApcState.Process->Peb;
  v30[1] = (UINT64)Peb;
  if( !CommittedStackSize || (v11 = MaximumStackSize) == 0 )
  {
    v19 = 0;
    LODWORD(v20) = RtlImageNtHeader((UINT64)KeGetCurrentThread()->ApcState.Process->SectionBaseAddress);
    v21 = v20;
    if( v20 )
    {
      v22 = *(unsigned int *)(v20 + 100);
      v23 = *(_DWORD *)(v21 + 96);
      CommittedStackSize = v39;
      if( !v39 )
        CommittedStackSize = v22;
      v11 = MaximumStackSize;
      if( !MaximumStackSize )
        v11 = v23;
    }
    else
    {
      v19 = -1073741701;
      v29 = -1073741701;
      v11 = MaximumStackSize;
      CommittedStackSize = v39;
    }
    if( v19 < 0 )
      return v19;
  }
  if( !CommittedStackSize )
    CommittedStackSize = 0x4000i64;
  if( CommittedStackSize >= v11 )
    v11 = (CommittedStackSize + 0xFFFFF) & 0xFFFFFFFFFFF00000ui64;
  v12 = (CommittedStackSize + 4095) & 0xFFFFFFFFFFFFF000ui64;
  v13 = (v11 + 0xFFFF) & 0xFFFFFFFFFFFF0000ui64;
  MinimumStackCommit = Peb->MinimumStackCommit;
  if( MinimumStackCommit && v12 < MinimumStackCommit )
  {
    v12 = (MinimumStackCommit + 4095) & 0xFFFFFFFFFFFFF000ui64;
    v13 = (v12 + 0xFFFFF) & 0xFFFFFFFFFFF00000ui64;
  }
  ProcessInformation[0] = v8;
  ProcessInformation[1] = 0;
  ProcessInformation[3] = 0;
  ProcessInformation[2] = 0;
  v35 = v13;
  v36 = ZeroBits;
  result = ZwSetInformationProcess(0xFFFFFFFFFFFFFFFFui64, 0x29ui64, (UINT64)ProcessInformation, 0x28ui64);
  if( result >= 0 )
  {
    v15 = v37;
    *((_QWORD *)InitialTeb + 7) = v37;
    *((_QWORD *)InitialTeb + 5) = v15 + v13;
    BaseAddress = (VOID *)(v13 + v15 - v12);
    v16 = v13 - v12;
    RegionSize = v12;
    LODWORD(Protect) = 4;
    LODWORD(AllocationType) = 4096;
    v17 = ZwAllocateVirtualMemory(
            (VOID *)0xFFFFFFFFFFFFFFFFi64,
            &BaseAddress,
            0i64,
            &RegionSize,
            AllocationType,
            Protect);
    if( v17 < 0
      || (v18 = (char *)BaseAddress, *((_QWORD *)InitialTeb + 6) = BaseAddress, v16 >= 0x2000)
      && (BaseAddress = v18 - 0x2000,
          v30[0] = 0x2000i64,
          LODWORD(Protecta) = 260,
          LODWORD(AllocationTypea) = 4096,
          v17 = ZwAllocateVirtualMemory(
                  (VOID *)0xFFFFFFFFFFFFFFFFi64,
                  &BaseAddress,
                  0i64,
                  v30,
                  AllocationTypea,
                  Protecta),
          v17 < 0) )
    {
      v33 = (VOID *)*((_QWORD *)InitialTeb + 7);
      v32 = 0i64;
      ZwFreeVirtualMemory((VOID *)0xFFFFFFFFFFFFFFFFi64, &v33, &v32, 0x8000ui64);
      *((_QWORD *)InitialTeb + 7) = 0i64;
      *((_QWORD *)InitialTeb + 5) = 0i64;
      *((_QWORD *)InitialTeb + 6) = 0i64;
      return v17;
    }
    else
    {
      return 0;
    }
  }
  return result;
}

Referenced by:

PspWow64SetupUserStack