KeWaitForMultipleObjects
VOID __fastcall KeWaitForMultipleObjects(
_BYTE *Count,
VOID **Object,
_WAIT_TYPE WaitType,
_KWAIT_REASON WaitReason,
CHAR WaitMode,
UINT8 Alertable,
_LARGE_INTEGER *Timeout,
_KWAIT_BLOCK *WaitBlockArray){
_KWAIT_BLOCK *v8;
_ETHREAD *CurrentThread;
unsigned __int8 CurrentIrql;
UINT8 v11;
struct _KPRCB *CurrentPrcb;
char v13;
struct _KPRCB *v14;
__int64 v15;
struct _KPRCB *v16;
volatile unsigned __int8 *p_BlockState;
VOID **v18;
unsigned __int64 v19;
unsigned int v20;
_KMUTANT *v21;
_LIST_ENTRY *v22;
__int64 v23;
int v24;
unsigned __int64 v25;
int v26;
unsigned int v27;
unsigned __int64 v28;
int v29;
VOID **v30;
struct _KPRCB *v31;
__int64 v32;
void *v33;
_KWAIT_BLOCK *v34;
void *v35;
_LIST_ENTRY *Flink;
_LIST_ENTRY *Blink;
__int64 v38;
unsigned __int64 v39;
unsigned __int64 v40;
char v41;
struct _KPRCB *v42;
struct _KPRCB *v43;
unsigned __int8 v45;
__int64 v46;
__int64 v47;
__int64 v48;
__int64 v49;
unsigned __int64 v50;
char v51;
_QWORD *v52;
_QWORD *v53;
__int64 v54;
__int64 v55;
unsigned int v56;
unsigned __int64 v57;
__int64 v58;
unsigned __int64 v59;
_BYTE *v60;
__int64 v61;
void *v62;
struct _KPRCB *v63;
__int64 v64;
int v65;
__int64 v66;
struct _KPRCB *v67;
__int64 v68;
int v69;
char v70;
int v71;
_KPRCB *Prcb;
unsigned __int64 v74;
__int64 v75;
__int64 v76;
unsigned int v77;
LONGLONG QuadPart;
UINT64 SpinCount;
UINT64 v80;
int v81;
int v82;
UINT64 v83;
UINT64 v84;
UINT64 v85;
VOID *v86;
_SINGLE_LIST_ENTRY ReadyList;
_ETHREAD *v88;
__int64 v89;
char v90[8];
v8 = WaitBlockArray;
HIDWORD(SpinCount) = WaitReason;
v77 = (unsigned int)Count;
QuadPart = 0i64;
if( (_DWORD)Count == 1 )
{
KeWaitForSingleObject(*Object, WaitReason, WaitMode, Alertable, Timeout);
return;
}
CurrentThread = (_ETHREAD *)KeGetCurrentThread();
v88 = CurrentThread;
if( !WaitBlockArray )
{
if( (unsigned int)Count <= 3 )
{
v8 = (_KWAIT_BLOCK *)((char *)CurrentThread + 320);
goto LABEL_5;
}
LABEL_117:
KeBugCheck(0xCui64);
}
if( (unsigned int)Count > 0x40 )
goto LABEL_117;
LABEL_5:
if( WaitType == WaitAll )
{
KiWaitForAllObjects((UINT64)Count, Object, WaitReason, WaitMode, Alertable, Timeout, v8);
return;
}
v86 = 0i64;
v89 = 0i64;
v70 = _bittestandreset((signed __int32 *)CurrentThread + 29, 2u);
if( !v70 )
{
CurrentIrql = KeGetCurrentIrql();
__writecr8(2ui64);
*((_BYTE *)CurrentThread + 390) = CurrentIrql;
}
if( Timeout )
{
if( Timeout->HighPart >= 0 )
{
QuadPart = Timeout->QuadPart;
v71 = 1;
}
else
{
v71 = 2;
QuadPart = *(_QWORD *)&KUSER_SHARED_DATA.InterruptTime.LowPart
- KUSER_SHARED_DATA.InterruptTimeBias
- (Timeout->QuadPart
+ *((_QWORD *)CurrentThread + 31));
}
}
else
{
v71 = 0;
}
while( 2 )
{
v11 = *((_BYTE *)CurrentThread + 390);
while( 1 )
{
*((_DWORD *)CurrentThread + 29) &= ~0x10u;
*((_BYTE *)CurrentThread + 112) = 0;
*((_BYTE *)CurrentThread + 391) = WaitMode;
if( Alertable )
*((_DWORD *)CurrentThread + 29) |= 0x10u;
CurrentPrcb = KeGetCurrentPrcb();
LODWORD(SpinCount) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)CurrentThread + 16, 0i64) )
{
do
KeYieldProcessorEx(&SpinCount);
while( *((_QWORD *)CurrentThread + 8) );
v46 = *((_QWORD *)CurrentPrcb + 4247);
if( v46 && *((_BYTE *)CurrentPrcb + 32) <= 1u )
++*(_DWORD *)(v46 + 24);
}
if( !*((_BYTE *)CurrentThread + 193) || *((_WORD *)CurrentThread + 243) || v11 )
break;
KiReleaseThreadLockSafe((INT64)CurrentThread);
__writecr8(1ui64);
KiDeliverApc(0, 0i64, 0i64);
KeGetCurrentIrql();
__writecr8(2ui64);
*((_BYTE *)CurrentThread + 390) = 0;
}
v13 = BYTE4(SpinCount);
if( !Alertable )
{
if( (*((_BYTE *)CurrentThread + 194) & 2) != 0 && WaitMode )
goto LABEL_109;
goto LABEL_19;
}
if( *((_BYTE *)CurrentThread + WaitMode + 114) )
{
*((_BYTE *)CurrentThread + WaitMode + 114) = 0;
goto LABEL_109;
}
if( WaitMode && *((_ETHREAD **)CurrentThread + 21) != (_ETHREAD *)((char *)CurrentThread + 168) )
{
*((_BYTE *)CurrentThread + 194) |= 2u;
goto LABEL_109;
}
if( *((_BYTE *)CurrentThread + 114) )
{
*((_BYTE *)CurrentThread + 114) = 0;
LABEL_109:
KiReleaseThreadLockSafe((INT64)CurrentThread);
KiCheckForThreadDispatch(KeGetCurrentPrcb(), v11);
return;
}
LABEL_19:
*((_BYTE *)CurrentThread + 388) = 5;
*((_BYTE *)CurrentThread + 643) = v13;
*((_DWORD *)CurrentThread + 109) = KUSER_SHARED_DATA.TickCount.LowPart;
*((_QWORD *)CurrentThread + 8) = 0i64;
v14 = KeGetCurrentPrcb();
v15 = *((_QWORD *)v14 + 4247);
if( v15 && *((_BYTE *)v14 + 32) <= 1u )
--*(_DWORD *)(v15 + 24);
v16 = KeGetCurrentPrcb();
p_BlockState = &v8->BlockState;
v18 = Object;
v19 = 0i64;
Prcb = v16;
v20 = 0;
v74 = 0i64;
do
{
LODWORD(v80) = 0;
v21 = (_KMUTANT *)v18[v20];
*((_BYTE *)p_BlockState - 1) = 1;
*p_BlockState = 4;
*(_WORD *)(p_BlockState + 1) = v20;
*(_QWORD *)(p_BlockState + 7) = CurrentThread;
*(_QWORD *)(p_BlockState + 15) = v21;
if( _interlockedbittestandset(&v21->Header.Lock, 7u) )
{
do
{
do
KeYieldProcessorEx(&v80);
while( (v21->Header.LockNV & 0x80u) != 0 );
}
while( _interlockedbittestandset(&v21->Header.Lock, 7u) );
v18 = Object;
v19 = v74;
v16 = Prcb;
}
if( (v21->Header.Type & 0x7F) != 2 )
{
if( v21->Header.SignalState <= 0 )
goto LABEL_24;
v31 = KeGetCurrentPrcb();
HIDWORD(v84) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)CurrentThread + 16, 0i64) )
{
do
KeYieldProcessorEx((UINT64 *)((char *)&v84 + 4));
while( *((_QWORD *)CurrentThread + 8) );
v47 = *((_QWORD *)v31 + 4247);
if( v47 && *((_BYTE *)v31 + 32) <= 1u )
++*(_DWORD *)(v47 + 24);
}
if( (*((_BYTE *)CurrentThread + 112) & 7) == 0 )
{
*((_QWORD *)CurrentThread + 25) = v20;
*((_QWORD *)CurrentThread + 122) = 0i64;
if( (v21->Header.Type & 7) == 1 )
{
v21->Header.SignalState = 0;
}
else if( (v21->Header.Type & 0x7F) == 5 )
{
--v21->Header.SignalState;
}
}
v32 = (__int64)Prcb;
LABEL_43:
_InterlockedAnd(&v21->Header.Lock, 0xFFFFFF7F);
LABEL_44:
*((_BYTE *)CurrentThread + 388) = 2;
*((_QWORD *)CurrentThread + 8) = 0i64;
v33 = (void *)*((_QWORD *)CurrentThread + 122);
if( v33 )
{
*((_QWORD *)CurrentThread + 122) = 0i64;
LODWORD(v66) = KeAbPreAcquire(v33, 0i64, 1ui64);
if( v66 )
*(_BYTE *)(v66 + 26) |= 1u;
}
if( v20 )
{
v34 = &v8[(unsigned __int8)v20];
do
{
if( v8->BlockState < 5u )
{
v35 = v8->Object;
KiAcquireKobjectLockSafe(v35);
if( v8->BlockState == 4 )
{
Flink = v8->WaitListEntry.Flink;
Blink = v8->WaitListEntry.Blink;
if( (_KWAIT_BLOCK *)v8->WaitListEntry.Flink->Blink != v8 || (_KWAIT_BLOCK *)Blink->Flink != v8 )
goto LABEL_50;
Blink->Flink = Flink;
Flink->Blink = Blink;
}
_InterlockedAnd((volatile signed __int32 *)v35, 0xFFFFFF7F);
}
++v8;
}
while( v8 != v34 );
}
v40 = *((unsigned __int8 *)CurrentThread + 390);
v41 = *((_BYTE *)CurrentThread + 112);
if( (v41 & 0x38) != 0 )
{
if( (v41 & 0x18) != 0 )
{
if( (v41 & 8) != 0 )
_interlockedbittestandset((volatile signed __int32 *)CurrentThread + 30, 0xCu);
ReadyList.Next = 0i64;
v67 = KeGetCurrentPrcb();
LODWORD(v85) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)(v32 + 48), 0i64) )
{
do
KeYieldProcessorEx(&v85);
while( *(_QWORD *)(v32 + 48) );
v68 = *((_QWORD *)v67 + 4247);
if( v68 && *((_BYTE *)v67 + 32) <= 1u )
{
v69 = *(_DWORD *)(v68 + 24) + 1;
*(_DWORD *)(v68 + 24) = v69;
}
}
if( !*(_QWORD *)(v32 + 16) )
KiSelectNextThread((_KPRCB *)v32, &ReadyList);
_InterlockedAnd64((volatile signed __int64 *)(v32 + 48), 0i64);
KiProcessDeferredReadyList(v32, &ReadyList, v40);
}
else
{
KiCheckForThreadDispatch((_KPRCB *)v32, 1u);
KiDeliverApc(0, 0i64, 0i64);
__writecr8(0i64);
}
}
else if( v70 )
{
KiCheckForThreadDispatch((_KPRCB *)v32, v40);
}
else
{
__writecr8(v40);
}
return;
}
if( (v21->MutantFlags & 2) != 0 )
{
_bittestandset64((__int64 *)&v19, v20);
v74 = v19;
}
if( v21->Header.SignalState > 0
|| CurrentThread == v21->OwnerThread && v21->Header.Size == *((_BYTE *)v16 + 12586) )
{
if( v21->Header.SignalState == 0x80000000 )
{
_InterlockedAnd(&v21->Header.Lock, 0xFFFFFF7F);
v63 = KeGetCurrentPrcb();
HIDWORD(v83) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)CurrentThread + 16, 0i64) )
{
do
KeYieldProcessorEx((UINT64 *)((char *)&v83 + 4));
while( *((_QWORD *)CurrentThread + 8) );
v64 = *((_QWORD *)v63 + 4247);
if( v64 && *((_BYTE *)v63 + 32) <= 1u )
{
v65 = *(_DWORD *)(v64 + 24) + 1;
*(_DWORD *)(v64 + 24) = v65;
}
}
KiSatisfyThreadWait((__int64)Prcb, (__int64)CurrentThread, v70, (__int64 *)v8, v20);
RtlRaiseStatus(-1073741423);
}
v43 = KeGetCurrentPrcb();
LODWORD(v83) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)CurrentThread + 16, 0i64) )
{
do
KeYieldProcessorEx(&v83);
while( *((_QWORD *)CurrentThread + 8) );
v49 = *((_QWORD *)v43 + 4247);
if( v49 && *((_BYTE *)v43 + 32) <= 1u )
++*(_DWORD *)(v49 + 24);
}
v32 = (__int64)Prcb;
if( (*((_BYTE *)CurrentThread + 112) & 7) == 0 )
{
*((_QWORD *)CurrentThread + 25) = v20;
*((_QWORD *)CurrentThread + 122) = 0i64;
if( v21->Header.SignalState-- == 1 )
KiWaitSatisfyMutant(v21, (_KTHREAD *)CurrentThread, Prcb);
}
goto LABEL_43;
}
LABEL_24:
v22 = v21->Header.WaitListHead.Blink;
if( v22->Flink != &v21->Header.WaitListHead )
LABEL_50:
__fastfail(3u);
*(_QWORD *)(p_BlockState - 9) = v22;
*(_QWORD *)(p_BlockState - 17) = &v21->Header.WaitListHead;
v22->Flink = (_LIST_ENTRY *)(p_BlockState - 17);
v21->Header.WaitListHead.Blink = (_LIST_ENTRY *)(p_BlockState - 17);
_InterlockedAnd(&v21->Header.Lock, 0xFFFFFF7F);
++v20;
p_BlockState += 48;
}
while( v20 < v77 );
v23 = QuadPart;
v24 = v71;
v25 = QuadPart;
if( v71 == 2 )
{
v38 = *((unsigned int *)CurrentThread + 238);
v39 = *(_QWORD *)&KUSER_SHARED_DATA.InterruptTime.LowPart
- *((_QWORD *)CurrentThread + 31)
- KUSER_SHARED_DATA.InterruptTimeBias;
v25 = QuadPart;
if( *((_BYTE *)CurrentThread + 391)
&& !*((_DWORD *)CurrentThread + 121)
&& !*((_BYTE *)CurrentThread + 390)
&& !*((_BYTE *)CurrentThread + 192)
&& (_DWORD)v38 )
{
v25 = QuadPart + v38;
}
goto LABEL_53;
}
if( v71 )
{
if( !QuadPart )
{
LABEL_76:
v42 = KeGetCurrentPrcb();
LODWORD(v84) = 0;
while( _interlockedbittestandset64((volatile signed __int32 *)CurrentThread + 16, 0i64) )
{
do
KeYieldProcessorEx(&v84);
while( *((_QWORD *)CurrentThread + 8) );
v48 = *((_QWORD *)v42 + 4247);
if( v48 && *((_BYTE *)v42 + 32) <= 1u )
++*(_DWORD *)(v48 + 24);
}
v32 = (__int64)Prcb;
if( (*((_BYTE *)CurrentThread + 112) & 7) == 0 )
{
*((_QWORD *)CurrentThread + 25) = 258i64;
*((_QWORD *)CurrentThread + 122) = 0i64;
}
goto LABEL_44;
}
v39 = *(_QWORD *)&KUSER_SHARED_DATA.SystemTime.LowPart;
LABEL_53:
if( v39 <= v25 )
{
v24 = v71;
goto LABEL_28;
}
goto LABEL_76;
}
LABEL_28:
v26 = 0;
*((_BYTE *)CurrentThread + 587) = v77;
v27 = 0;
v28 = 0i64;
if( v19 )
{
do
{
_BitScanForward64(&v50, v19);
v51 = v50;
HIDWORD(v80) = v50;
v75 = v19 & ~(1i64 << v50);
LODWORD(v52) = KeAbPreAcquire(v18[v50], 0i64, 0i64);
v53 = v52;
if( !v52 )
break;
v28 |= 1i64 << v51;
KeAbPreWait(v52);
v19 = v75;
v18 = Object;
v54 = (__int64)v53 - v53[-2 * *((unsigned __int8 *)v53 + 24) + 100];
v55 = v27++;
v90[v55] = (2
* (((((unsigned __int128)(v54 * (__int128)0x2AAAAAAAAAAAAAABi64) >> 64) & 0x8000000000000000ui64) != 0i64)
+ ((__int64)((unsigned __int128)(v54 * (__int128)0x2AAAAAAAAAAAAAABi64) >> 64) >> 4))) | 1;
}
while( v75 );
CurrentThread = v88;
v26 = 0;
v23 = QuadPart;
v24 = v71;
}
v29 = KiCommitThreadWait((__int64)CurrentThread, (__int64 *)v8, v24, v23, &v86);
v30 = Object;
if( v86 )
{
v56 = 0;
v57 = v28;
if( v28 )
{
while( 1 )
{
_BitScanForward64((unsigned __int64 *)&v58, v57);
v57 &= ~(1i64 << v58);
v81 = v58;
if( v86 == Object[v58] )
break;
++v56;
if( !v57 )
goto LABEL_132;
}
v28 &= ~(1i64 << v58);
v59 = v56;
v60 = (_BYTE *)(*((_QWORD *)KeGetCurrentThread() + 100) + 96i64 * ((unsigned __int8)v90[v56] >> 1));
KeAbPreAcquire(Object[v58], v60, 0i64);
v60[26] |= 1u;
if( v59 >= 6 )
_report_rangecheckfailure();
v30 = Object;
v90[v59] = 0;
v26 = 0;
}
LABEL_132:
*((_QWORD *)CurrentThread + 122) = 0i64;
}
for( ; v28; ++v26 )
{
_BitScanForward64((unsigned __int64 *)&v61, v28);
v82 = v61;
v28 &= ~(1i64 << v61);
v76 = (unsigned int)v61;
if( !v90[v26] )
++v26;
v62 = (void *)(*((_QWORD *)KeGetCurrentThread() + 100) + 96i64 * ((unsigned __int8)v90[v26] >> 1));
KeAbPreAcquire(v30[(unsigned int)v61], v62, 0i64);
KeAbPostReleaseEx(Object[v76], v62);
v30 = Object;
}
if( v29 == 256 )
{
v70 = 0;
v45 = KeGetCurrentIrql();
__writecr8(2ui64);
*((_BYTE *)CurrentThread + 390) = v45;
continue;
}
break;
}
}Referenced by:
CcAsyncReadWorker
CcQueueLazyWriteScanThread
CmpDoFileWrite
CmpFinishSystemHivesLoad
EtwpCovSampCaptureWorkerThread
EtwpLogger
ExpWorkQueueManagerThread
FsRtlCancellableWaitForMultipleObjects
KeBalanceSetManager
MiDereferenceSegmentThread
MiIssueAsynchronousFlush
MiMappedPageWriter
MiModifiedPageWriter
MiPartitionWorkingSetManager
MiRebuildLargePagesThread
MiStoreEvictThread
MiWaitForAsynchronousFlushes
MiWaitForFreePagesToZero
MiZeroAllPageFiles
ObWaitForMultipleObjects
PfGenerateTrace
PfTLoggingWorker
PiUEventNotifyUserMode
PnprQuiesceWorker
PopFxProcessWorkPool
PopSleepDeviceList
PopThermalReadCounters
PsShutdownSystem
SMKM_STORE::SmStReadThread
SMKM_STORE::SmStWorker