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