KeReleaseMutant

LONG __stdcall KeReleaseMutant(PRKMUTANT Mutant, KPRIORITY Increment, BOOLEAN Abandoned, BOOLEAN Wait){
  unsigned int v4; 
  _ETHREAD *CurrentThread; 
  int v8; 
  _ETHREAD *OwnerThread; 
  char v10; 
  __int64 CurrentIrql; 
  struct _KPRCB *CurrentPrcb; 
  int SignalState; 
  int v14; 
  int LockNV; 
  struct _KPRCB *v16; 
  _LIST_ENTRY *Flink; 
  _LIST_ENTRY *Blink; 
  struct _KMUTANT *v19; 
  ULONG_PTR v20; 
  struct _KMUTANT *v22; 
  _KWAIT_BLOCK *v23; 
  _KWAIT_BLOCK **v24; 
  unsigned __int8 WaitType; 
  bool v26; 
  char v27; 
  NTSTATUS v28; 
  __int64 v29; 
  _LIST_ENTRY *v30; 
  _KQUEUE *v31; 
  UINT8 v32; 
  int v33; 
  _KQUEUE **v34; 
  INT64 v35; 
  __int64 v36; 
  unsigned int SessionId; 
  ULONG_PTR BugCheckParameter1; 
  _KQUEUE *Object; 
  _KPRCB *Prcb; 
  UINT64 SpinCount; 
  INT64 Entry; 
  __int64 v43; 
  _LIST_ENTRY *p_WaitListHead; 
  _KPRCB *v45; 
  _KTHREAD *WakeThread; 
  __int64 v47; 
  __int128 v48; 
  __int64 v49; 
  UINT64 v50; 
  INT64 Incrementa; 
  int ApcDisable; 
  BOOLEAN v53; 
  v53 = Wait;
  LODWORD(Incrementa) = Increment;
  v4 = 0;
  CurrentThread = (_ETHREAD *)KeGetCurrentThread();
  BugCheckParameter1 = (ULONG_PTR)CurrentThread;
  v8 = 0;
  OwnerThread = 0i64;
  WakeThread = 0i64;
  v10 = 0;
  CurrentIrql = KeGetCurrentIrql();
  v43 = CurrentIrql;
  __writecr8(2ui64);
  CurrentPrcb = KeGetCurrentPrcb();
  LODWORD(v50) = 0;
  Prcb = CurrentPrcb;
  if( _interlockedbittestandset(&Mutant->Header.Lock, 7u) )
  {
    do
    {
      do
        KeYieldProcessorEx(&v50);
      while( (Mutant->Header.LockNV & 0x80u) != 0 );
    }
    while( _interlockedbittestandset(&Mutant->Header.Lock, 7u) );
    CurrentThread = (_ETHREAD *)BugCheckParameter1;
    LOBYTE(CurrentIrql) = v43;
  }
  SignalState = Mutant->Header.SignalState;
  if( Abandoned )
  {
    Mutant->MutantFlags |= 1u;
    v14 = 1;
    Mutant->Header.SignalState = 1;
  }
  else
  {
    if( Mutant->OwnerThread != CurrentThread || Mutant->Header.Size != *((_BYTE *)CurrentPrcb + 12586) )
    {
      v27 = Mutant->MutantFlags & 1;
      _InterlockedAnd(&Mutant->Header.Lock, 0xFFFFFF7F);
      __writecr8((unsigned __int8)CurrentIrql);
      if( v27 )
        v28 = 128;
      else
        v28 = -1073741754;
      RtlRaiseStatus(v28);
    }
    v14 = ++Mutant->Header.SignalState;
  }
  if( v14 != 1 || SignalState > 0 )
  {
    _InterlockedAnd(&Mutant->Header.Lock, 0xFFFFFF7F);
    v20 = BugCheckParameter1;
    goto LABEL_19;
  }
  v49 = 0i64;
  LockNV = Mutant->Header.LockNV;
  v48 = 0i64;
  LODWORD(v48) = LockNV;
  BYTE2(v48) = 0;
  Mutant->Header.LockNV = v48;
  v16 = KeGetCurrentPrcb();
  OwnerThread = Mutant->OwnerThread;
  ApcDisable = Mutant->ApcDisable;
  LODWORD(SpinCount) = 0;
  while( _interlockedbittestandset64((volatile signed __int32 *)OwnerThread + 16, 0i64) )
  {
    do
      KeYieldProcessorEx(&SpinCount);
    while( *((_QWORD *)OwnerThread + 8) );
    v29 = *((_QWORD *)v16 + 4247);
    if( v29 && *((_BYTE *)v16 + 32) <= 1u )
      ++*(_DWORD *)(v29 + 24);
  }
  Flink = Mutant->MutantListEntry.Flink;
  Blink = Mutant->MutantListEntry.Blink;
  if( Flink->Blink != &Mutant->MutantListEntry || Blink->Flink != &Mutant->MutantListEntry )
LABEL_27:
    __fastfail(3u);
  Blink->Flink = Flink;
  Flink->Blink = Blink;
  *((_QWORD *)OwnerThread + 8) = 0i64;
  v19 = (struct _KMUTANT *)Mutant->Header.WaitListHead.Flink;
  Mutant->OwnerThread = 0i64;
  if( v19 != (struct _KMUTANT *)&Mutant->Header.WaitListHead )
  {
    while( 1 )
    {
      v22 = *(struct _KMUTANT **)&v19->Header.Lock;
      v23 = (_KWAIT_BLOCK *)v19;
      Entry = (INT64)v19;
      v19 = v22;
      v24 = *(_KWAIT_BLOCK ***)(Entry + 8);
      if( v22->Header.WaitListHead.Flink != (_LIST_ENTRY *)Entry || *v24 != v23 )
        goto LABEL_27;
      *v24 = (_KWAIT_BLOCK *)v22;
      v22->Header.WaitListHead.Flink = (_LIST_ENTRY *)v24;
      WaitType = v23->WaitType;
      if( WaitType != 1 )
        break;
      if( KiTryUnwaitThread(Prcb, v23, v23->WaitKey, (_KTHREAD **)&WakeThread) )
      {
        v26 = Mutant->Header.SignalState-- == 1;
        if( v26 )
          goto LABEL_13;
      }
LABEL_44:
      if( v19 == (struct _KMUTANT *)&Mutant->Header.WaitListHead )
        goto LABEL_13;
    }
    if( WaitType != 2 )
    {
      KiTryUnwaitThread(Prcb, v23, 256i64, 0i64);
      goto LABEL_44;
    }
    v23->BlockState = 5;
    Object = v23->NotificationQueue;
    p_WaitListHead = &Object->Header.WaitListHead;
    v23->WaitListEntry.Flink = 0i64;
    KeGetCurrentIrql();
    __writecr8(2ui64);
    v45 = KeGetCurrentPrcb();
    v47 = *((_QWORD *)v45 + 1);
    KiAcquireKobjectLockSafe(Object);
    v30 = p_WaitListHead;
    v31 = Object;
    if( v30->Flink != v30
      && Object->CurrentCount < Object->MaximumCount
      && (*(_KQUEUE **)(v47 + 232) != Object || *(_BYTE *)(v47 + 643) != 15) )
    {
      v32 = KiWakeQueueWaiter(v45, Object, Entry);
      v31 = Object;
      if( v32 )
        goto LABEL_59;
      v30 = p_WaitListHead;
    }
    v33 = v31->Header.SignalState;
    v31->Header.SignalState = v33 + 1;
    v34 = (_KQUEUE **)v31->EntryListHead.Blink;
    if( *v34 != (_KQUEUE *)&v31->EntryListHead )
      goto LABEL_27;
    v35 = Entry;
    *(_QWORD *)Entry = &v31->EntryListHead;
    *(_QWORD *)(v35 + 8) = v34;
    *v34 = (_KQUEUE *)v35;
    v31->EntryListHead.Blink = (_LIST_ENTRY *)v35;
    if( !v33 && v30->Flink != v30 )
    {
      KiWakeOtherQueueWaiters(v45, v31);
      v31 = Object;
    }
LABEL_59:
    _InterlockedAnd(&v31->Header.Lock, 0xFFFFFF7F);
    v26 = Mutant->Header.SignalState-- == 1;
    if( v26 )
      goto LABEL_13;
    goto LABEL_44;
  }
LABEL_13:
  if( (Mutant->MutantFlags & 2) != 0 )
    v10 = 1;
  _InterlockedAnd(&Mutant->Header.Lock, 0xFFFFFF7F);
  if( Abandoned )
    KiAcquireReleaseObjectRundownLockExclusive(Mutant);
  CurrentPrcb = Prcb;
  v20 = BugCheckParameter1;
  if( v10 )
  {
    if( WakeThread )
    {
      v36 = *((_QWORD *)Prcb + 1441);
      if( v36 )
      {
        if( WakeThread == (_ETHREAD *)(v36 - 216) )
          KeAbPreWakeupThread((__int64)WakeThread, (unsigned __int64)Mutant, *(char *)(BugCheckParameter1 + 195));
      }
    }
  }
  v8 = ApcDisable;
LABEL_19:
  if( v53 )
    v4 = 3;
  KiExitDispatcher(CurrentPrcb, v4, AdjustUnwait, (unsigned int)Incrementa, v43);
  if( v10 )
  {
    if( OwnerThread != (_ETHREAD *)v20 )
    {
      SessionId = MmGetSessionIdEx(*(_QWORD *)(v20 + 184));
      KeBugCheckEx(0x162u, v20, (ULONG_PTR)Mutant, SessionId, 1ui64);
    }
    KeAbPostRelease(Mutant);
  }
  if( v8 )
    KeLeaveCriticalRegionThread(v20);
  return SignalState;
}

Referenced by:

KeReleaseMutex
KiExpandKernelStackAndCalloutOnStackSegment
LdrUnloadAlternateResourceModuleEx
LdrpGetAlternateResourceModuleHandleEx
LdrpGetFromMUIMemCache
LdrpSetAlternateResourceModuleHandle
NtReleaseMutant
NtSignalAndWaitForSingleObject