PspDisassociateUmsThreadFromPrimary

NTSTATUS __stdcall PspDisassociateUmsThreadFromPrimary(PETHREAD Thread, PVOID DmaAdapter, INT64 *a3){
  NTSTATUS updated; 
  INT64 CurrentUmsTeb; 
  char v8; 
  char v9; 
  INT64 v10; 
  _DWORD *v11; 
  _ETHREAD *ThreadForTeb; 
  _QWORD *Object; 
  int v14; 
  unsigned __int64 v15; 
  void *v16; 
  _CONTEXT *v17; 
  INT64 v18; 
  _CONTEXT_EX *v19; 
  INT64 v20; 
  __int64 v21; 
  _ADAPTER_OBJECT *v22; 
  _CONTEXT *v23; 
  _CONTEXT *Buffer; 
  UINT64 ContextLength; 

  Buffer = 0i64;
  LODWORD(ContextLength) = 0;
  updated = 0;
  CurrentUmsTeb = KeGetCurrentUmsTeb(Thread);
  v8 = 0;
  v9 = 0;
  if( KeDoesTebMatchThread((INT64)Thread, CurrentUmsTeb) )
    goto LABEL_2;
  if( DmaAdapter )
  {
    if( v10 != *((_QWORD *)DmaAdapter + 30) )
    {
LABEL_2:
      *v11 |= 2u;
      goto LABEL_23;
    }
LABEL_10:
    Object = Thread->Tcb.WaitBlock[3].Object;
    if( (Thread->Tcb._bf_0 & 0x100) != 0 )
    {
      *(_DWORD *)a3 |= 1u;
      v9 = v8;
    }
    else
    {
      KeSetCurrentUmsTeb(&Thread->Tcb, (UINT64)Thread->Tcb.Teb);
      v14 = KUSER_SHARED_DATA.XState.EnabledFeatures != 0 ? 0x40 : 0;
      RtlGetExtendedContextLength((unsigned int)(v14 + 1048603), &ContextLength);
      v15 = (unsigned int)ContextLength + 15i64;
      if( v15 <= (unsigned int)ContextLength )
        v15 = 0xFFFFFFFFFFFFFF0i64;
      v16 = alloca(v15 & 0xFFFFFFFFFFFFFFF0ui64);
      memset(&Buffer, 0i64, ContextLength);
      RtlInitializeExtendedContext(&Buffer, (unsigned int)(v14 + 1048603), (_CONTEXT_EX **)&Buffer);
      v17 = --Buffer;
      PspGetContextThreadInternal(Thread, Buffer, 0, 1, 1u);
      ContextLength = **((_QWORD **)DmaAdapter + 62);
      v18 = ContextLength;
      KeFixUserSwitchContext((INT64)DmaAdapter, ContextLength, 0i64, v17);
      updated = KeRemoveUmsThreadCidOwnership(v18, 1);
      v9 = v8;
      if( updated >= 0 )
      {
        v19 = (_CONTEXT_EX *)Buffer;
        *(_DWORD *)a3 |= 2u;
        updated = PspSetUmsThreadContext((__int64)DmaAdapter, (INT64)v19, a3);
        if( updated >= 0 )
        {
          v20 = Object[2];
          if( *(_QWORD *)(*((_QWORD *)DmaAdapter + 62) + 16i64) != v20 )
          {
            ObReferenceObjectSafe(v20);
            v21 = *((_QWORD *)DmaAdapter + 62);
            v22 = *(_ADAPTER_OBJECT **)(v21 + 16);
            if( v22 )
            {
              HalPutDmaAdapter(v22);
              v21 = *((_QWORD *)DmaAdapter + 62);
            }
            *(_QWORD *)(v21 + 8) = Object[1];
            *(_QWORD *)(*((_QWORD *)DmaAdapter + 62) + 16i64) = Object[2];
          }
          v23 = Buffer;
          updated = KeBuildPrimaryThreadContext((INT64)Thread, 0i64, (INT64)Buffer, 1i64, 0i64, 0i64);
          if( updated >= 0 )
          {
            PspSetContextThreadInternal(Thread, v23, 0, 1, 1u);
            *(_DWORD *)a3 |= 8u;
            if( v8 )
              updated = KeUpdateUmsThreadState(ContextLength, 0i64, 1);
          }
        }
      }
    }
    goto LABEL_23;
  }
  ThreadForTeb = PspFindThreadForTeb(v10);
  DmaAdapter = ThreadForTeb;
  if( !ThreadForTeb )
  {
LABEL_5:
    updated = -1073740004;
    goto LABEL_23;
  }
  v8 = 1;
  if( ExAcquireRundownProtection(&ThreadForTeb->RundownProtect) )
    goto LABEL_10;
  KeSetCurrentUmsTeb(&Thread->Tcb, (UINT64)Thread->Tcb.Teb);
  if( _interlockedbittestandset((volatile signed __int32 *)DmaAdapter + 324, 0x10u) )
    goto LABEL_5;
LABEL_23:
  if( v8 )
  {
    if( v9 )
      ExReleaseRundownProtection((_EX_RUNDOWN_REF *)DmaAdapter + 159);
    HalPutDmaAdapter((PADAPTER_OBJECT)DmaAdapter);
  }
  return updated;
}

Referenced by:

PspRelinquishUmsThreadSpecialApc
PspUmsUnInitThread