WaitForMultipleObjects: WaitAll waits were buggy

Many small fixes and cleanups

svn path=/trunk/; revision=4205
This commit is contained in:
Gunnar Dalsnes 2003-02-27 15:38:36 +00:00
parent 3013b90260
commit 5852f3f492

View file

@ -33,6 +33,9 @@ static BOOLEAN WaitSet = FALSE;
static KIRQL oldlvl = PASSIVE_LEVEL;
static PKTHREAD Owner = NULL;
#define KeDispatcherObjectWakeOne(hdr) KeDispatcherObjectWakeOneOrAll(hdr, FALSE)
#define KeDispatcherObjectWakeAll(hdr) KeDispatcherObjectWakeOneOrAll(hdr, TRUE)
/* FUNCTIONS *****************************************************************/
VOID KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header,
@ -85,16 +88,15 @@ VOID KeReleaseDispatcherDatabaseLock(BOOLEAN Wait)
}
}
static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
PKTHREAD Thread,
PBOOLEAN Abandoned)
static BOOLEAN
KiSideEffectsBeforeWake(DISPATCHER_HEADER * hdr,
PKTHREAD Thread)
/*
* FUNCTION: Perform side effects on object before a wait for a thread is
* satisfied
*/
{
if (Abandoned != NULL)
*Abandoned = FALSE;
BOOLEAN Abandoned = FALSE;
switch (hdr->Type)
{
@ -133,14 +135,12 @@ static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
{
if (Thread == NULL)
{
DPRINT1("Thread == NULL!\n");
DPRINT("Thread == NULL!\n");
KeBugCheck(0);
}
if (Abandoned != NULL)
*Abandoned = Mutex->Abandoned;
Abandoned = Mutex->Abandoned;
if (Thread != NULL)
InsertTailList(&Thread->MutantListHead,
&Mutex->MutantListEntry);
InsertTailList(&Thread->MutantListHead, &Mutex->MutantListEntry);
Mutex->OwnerThread = Thread;
Mutex->Abandoned = FALSE;
}
@ -148,20 +148,17 @@ static VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr,
break;
default:
DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n",
__FILE__,__LINE__,hdr);
DbgPrint("(%s:%d) Dispatcher object %x has unknown type\n", __FILE__, __LINE__, hdr);
KeBugCheck(0);
}
return Abandoned;
}
static BOOLEAN
KiIsObjectSignalled(DISPATCHER_HEADER * hdr,
PKTHREAD Thread,
PBOOLEAN Abandoned)
PKTHREAD Thread)
{
if (Abandoned != NULL)
*Abandoned = FALSE;
if (hdr->Type == InternalMutexType)
{
PKMUTEX Mutex;
@ -169,12 +166,9 @@ KiIsObjectSignalled(DISPATCHER_HEADER* hdr,
Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header);
assert(hdr->SignalState <= 1);
if ((hdr->SignalState < 1 && Mutex->OwnerThread == Thread) ||
hdr->SignalState == 1)
if ((hdr->SignalState < 1 && Mutex->OwnerThread == Thread) || hdr->SignalState == 1)
{
KiSideEffectsBeforeWake(hdr,
Thread,
Abandoned);
return (TRUE);
}
else
@ -182,15 +176,13 @@ KiIsObjectSignalled(DISPATCHER_HEADER* hdr,
return (FALSE);
}
}
if (hdr->SignalState <= 0)
{
return (FALSE);
}
else
{
KiSideEffectsBeforeWake(hdr,
Thread,
Abandoned);
return (TRUE);
}
}
@ -222,156 +214,114 @@ VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus)
KeReleaseDispatcherDatabaseLock(FALSE);
}
static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr)
static BOOLEAN
KeDispatcherObjectWakeOneOrAll(DISPATCHER_HEADER * hdr,
BOOLEAN WakeAll)
{
PKWAIT_BLOCK current;
PLIST_ENTRY current_entry;
PKWAIT_BLOCK PrevBlock;
PKWAIT_BLOCK Waiter;
PKWAIT_BLOCK WaiterHead;
PLIST_ENTRY EnumEntry;
NTSTATUS Status;
BOOLEAN Abandoned;
BOOLEAN AllSignaled;
BOOLEAN WakedAny = FALSE;
DPRINT("KeDispatcherObjectWakeAll(hdr %x)\n",hdr);
DPRINT("KeDispatcherObjectWakeOnOrAll(hdr %x)\n", hdr);
DPRINT ("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
hdr->WaitListHead.Flink, hdr->WaitListHead.Blink);
if (IsListEmpty(&hdr->WaitListHead))
{
return (FALSE);
}
while (!IsListEmpty(&hdr->WaitListHead))
//enum waiters for this dispatcher object
EnumEntry = hdr->WaitListHead.Flink;
while (EnumEntry != &hdr->WaitListHead && (WakeAll || !WakedAny))
{
current_entry = RemoveHeadList(&hdr->WaitListHead);
current = CONTAINING_RECORD(current_entry,
KWAIT_BLOCK,
WaitListEntry);
DPRINT("Waking %x\n",current->Thread);
if (current->WaitType == WaitAny)
WaiterHead = CONTAINING_RECORD(EnumEntry, KWAIT_BLOCK, WaitListEntry);
DPRINT("current_entry %x current %x\n", EnumEntry, WaiterHead);
EnumEntry = EnumEntry->Flink;
assert(WaiterHead->Thread->WaitBlockList != NULL);
Abandoned = FALSE;
if (WaiterHead->WaitType == WaitAny)
{
DPRINT("WaitAny: Remove all wait blocks.\n");
for(PrevBlock = current->Thread->WaitBlockList; PrevBlock;
PrevBlock = PrevBlock->NextWaitBlock)
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
{
if (PrevBlock != current)
RemoveEntryList(&PrevBlock->WaitListEntry);
RemoveEntryList(&Waiter->WaitListEntry);
}
current->Thread->WaitBlockList = 0;
}
else
{
DPRINT("WaitAll: Remove the current wait block only.\n");
PrevBlock = current->Thread->WaitBlockList;
if (PrevBlock == current)
{
DPRINT( "WaitAll: Current block is list head.\n" );
current->Thread->WaitBlockList = current->NextWaitBlock;
WaiterHead->Thread->WaitBlockList = NULL;
/*
* If a WakeAll KiSideEffectsBeforeWake(hdr,.. will be called several times,
* but thats ok since WakeAll objects has no sideeffects.
*/
Abandoned = KiSideEffectsBeforeWake(hdr, WaiterHead->Thread) ? TRUE : Abandoned;
}
else
{
DPRINT( "WaitAll: Current block is not list head.\n" );
while (PrevBlock && PrevBlock->NextWaitBlock != current)
DPRINT("WaitAll: All WaitAll objects must be signaled.\n");
AllSignaled = TRUE;
//all WaitAll obj. for thread need to be signaled to satisfy a wake
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
{
PrevBlock = PrevBlock->NextWaitBlock;
}
if (PrevBlock)
//no need to check hdr since it has to be signaled
if (Waiter->WaitType == WaitAll && Waiter->Object != hdr)
{
PrevBlock->NextWaitBlock = current->NextWaitBlock;
}
current->NextWaitBlock = NULL;
/* if the last block is the timeout block then remove this block */
PrevBlock = current->Thread->WaitBlockList;
if (PrevBlock == &current->Thread->WaitBlock[3] && PrevBlock->NextWaitBlock == NULL)
if (!KiIsObjectSignalled(Waiter->Object, Waiter->Thread))
{
RemoveEntryList(&current->Thread->WaitBlock[3].WaitListEntry);
current->Thread->WaitBlockList = NULL;
AllSignaled = FALSE;
break;
}
}
}
KiSideEffectsBeforeWake(hdr, current->Thread, &Abandoned);
Status = current->WaitKey;
if (AllSignaled)
{
for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
{
RemoveEntryList(&Waiter->WaitListEntry);
if (Waiter->WaitType == WaitAll)
{
Abandoned = KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread)
? TRUE : Abandoned;
}
//no WaitAny objects can possibly be signaled since we are here
assert(!(Waiter->WaitType == WaitAny
&& KiIsObjectSignalled(Waiter->Object, Waiter->Thread)));
}
WaiterHead->Thread->WaitBlockList = NULL;
}
}
if (WaiterHead->Thread->WaitBlockList == NULL)
{
Status = WaiterHead->WaitKey;
if (Abandoned)
{
DPRINT("Abandoned mutex among objects");
Status += STATUS_ABANDONED_WAIT_0;
if (current->Thread->WaitBlockList == NULL)
{
PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
}
}
return(TRUE);
}
static BOOLEAN KeDispatcherObjectWakeOne(DISPATCHER_HEADER* hdr)
{
PKWAIT_BLOCK current;
PLIST_ENTRY current_entry;
PKWAIT_BLOCK PrevBlock;
NTSTATUS Status;
BOOLEAN Abandoned;
DPRINT("KeDispatcherObjectWakeOn(hdr %x)\n",hdr);
DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x\n",
hdr->WaitListHead.Flink,hdr->WaitListHead.Blink);
if (IsListEmpty(&(hdr->WaitListHead)))
{
return(FALSE);
}
current_entry = RemoveHeadList(&(hdr->WaitListHead));
current = CONTAINING_RECORD(current_entry,KWAIT_BLOCK,
WaitListEntry);
DPRINT("current_entry %x current %x\n",current_entry,current);
if (current->WaitType == WaitAny)
{
DPRINT("WaitAny: Remove all wait blocks.\n");
for( PrevBlock = current->Thread->WaitBlockList; PrevBlock; PrevBlock = PrevBlock->NextWaitBlock )
if( PrevBlock != current )
RemoveEntryList( &(PrevBlock->WaitListEntry) );
current->Thread->WaitBlockList = 0;
}
else
{
DPRINT("WaitAll: Remove the current wait block only.\n");
PrevBlock = current->Thread->WaitBlockList;
if (PrevBlock == current)
{
DPRINT( "WaitAll: Current block is list head.\n" );
current->Thread->WaitBlockList = current->NextWaitBlock;
}
else
{
DPRINT( "WaitAll: Current block is not list head.\n" );
while ( PrevBlock && PrevBlock->NextWaitBlock != current)
{
PrevBlock = PrevBlock->NextWaitBlock;
}
if (PrevBlock)
{
PrevBlock->NextWaitBlock = current->NextWaitBlock;
}
}
current->NextWaitBlock = NULL;
/* if the last block is the timeout block then remove this block */
PrevBlock = current->Thread->WaitBlockList;
if (PrevBlock == &current->Thread->WaitBlock[3] && PrevBlock->NextWaitBlock == NULL)
{
RemoveEntryList(&current->Thread->WaitBlock[3].WaitListEntry);
current->Thread->WaitBlockList = NULL;
WakedAny = TRUE;
DPRINT("Waking %x status = %x\n", WaiterHead->Thread, Status);
PsUnblockThread(CONTAINING_RECORD(WaiterHead->Thread, ETHREAD, Tcb), &Status);
}
}
DPRINT("Waking %x\n",current->Thread);
KiSideEffectsBeforeWake(hdr, current->Thread, &Abandoned);
Status = current->WaitKey;
if (Abandoned)
Status += STATUS_ABANDONED_WAIT_0;
if (current->Thread->WaitBlockList == NULL)
{
PsUnblockThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb),
&Status);
}
return(TRUE);
return WakedAny;
}
BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
/*
* FUNCTION: Wake threads waiting on a dispatcher object
@ -446,103 +396,14 @@ KeWaitForSingleObject(PVOID Object,
* RETURNS: Status
*/
{
DISPATCHER_HEADER* hdr = (DISPATCHER_HEADER *)Object;
PKTHREAD CurrentThread;
NTSTATUS Status;
KIRQL WaitIrql;
BOOLEAN Abandoned;
CurrentThread = KeGetCurrentThread();
WaitIrql = KeGetCurrentIrql();
/*
* Set up the timeout
* FIXME: Check for zero timeout
*/
if (Timeout != NULL)
{
KeInitializeTimer(&CurrentThread->Timer);
KeSetTimer(&CurrentThread->Timer, *Timeout, NULL);
}
do
{
KeAcquireDispatcherDatabaseLock(FALSE);
/*
* If we are going to wait alertably and a user apc is pending
* then return
*/
if (Alertable && KiTestAlert())
{
KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_USER_APC);
}
/*
* If the object is signalled
*/
if (KiIsObjectSignalled(hdr, CurrentThread, &Abandoned))
{
if (Timeout != NULL)
{
KeCancelTimer(&CurrentThread->Timer);
}
KeReleaseDispatcherDatabaseLock(FALSE);
if (Abandoned == TRUE)
return(STATUS_ABANDONED_WAIT_0);
return(STATUS_WAIT_0);
}
/*
* Check if we have already timed out
*/
if (Timeout != NULL &&
KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread, NULL))
{
KeCancelTimer(&CurrentThread->Timer);
KeReleaseDispatcherDatabaseLock(FALSE);
return(STATUS_TIMEOUT);
}
/*
* Set up for a wait
*/
CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL;
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = &CurrentThread->WaitBlock[0];
CurrentThread->WaitBlock[0].Object = Object;
CurrentThread->WaitBlock[0].Thread = CurrentThread;
CurrentThread->WaitBlock[0].WaitKey = STATUS_WAIT_0;
CurrentThread->WaitBlock[0].WaitType = WaitAny;
InsertTailList(&hdr->WaitListHead,
&CurrentThread->WaitBlock[0].WaitListEntry);
if (Timeout != NULL)
{
CurrentThread->WaitBlock[0].NextWaitBlock =
&CurrentThread->WaitBlock[3];
CurrentThread->WaitBlock[3].Object = (PVOID)&CurrentThread->Timer;
CurrentThread->WaitBlock[3].Thread = CurrentThread;
CurrentThread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
CurrentThread->WaitBlock[3].WaitType = WaitAny;
CurrentThread->WaitBlock[3].NextWaitBlock = NULL;
InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
&CurrentThread->WaitBlock[3].WaitListEntry);
}
else
{
CurrentThread->WaitBlock[0].NextWaitBlock = NULL;
}
PsBlockThread(&Status, (UCHAR)Alertable, WaitMode, TRUE, WaitIrql);
} while (Status == STATUS_KERNEL_APC);
if (Timeout != NULL)
{
KeCancelTimer(&CurrentThread->Timer);
}
DPRINT("Returning from KeWaitForSingleObject()\n");
return(Status);
return KeWaitForMultipleObjects(1,
&Object,
WaitAny,
WaitReason,
WaitMode,
Alertable,
Timeout,
NULL);
}
@ -568,7 +429,6 @@ KeWaitForMultipleObjects(ULONG Count,
DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
"PsGetCurrentThread() %x\n", Count, Object, PsGetCurrentThread());
CountSignaled = 0;
CurrentThread = KeGetCurrentThread();
WaitIrql = KeGetCurrentIrql();
@ -579,8 +439,7 @@ KeWaitForMultipleObjects(ULONG Count,
{
if (Count > THREAD_WAIT_OBJECTS)
{
DbgPrint("(%s:%d) Too many objects!\n",
__FILE__,__LINE__);
DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
return (STATUS_UNSUCCESSFUL);
}
WaitBlockArray = &CurrentThread->WaitBlock[0];
@ -589,8 +448,7 @@ KeWaitForMultipleObjects(ULONG Count,
{
if (Count > EX_MAXIMUM_WAIT_OBJECTS)
{
DbgPrint("(%s:%d) Too many objects!\n",
__FILE__,__LINE__);
DPRINT("(%s:%d) Too many objects!\n", __FILE__, __LINE__);
return (STATUS_UNSUCCESSFUL);
}
}
@ -598,7 +456,7 @@ KeWaitForMultipleObjects(ULONG Count,
/*
* Set up the timeout if required
*/
if (Timeout != NULL)
if (Timeout != NULL && Timeout->QuadPart != 0)
{
KeInitializeTimer(&CurrentThread->Timer);
KeSetTimer(&CurrentThread->Timer, *Timeout, NULL);
@ -619,48 +477,78 @@ KeWaitForMultipleObjects(ULONG Count,
}
/*
* Check if the wait is already satisfied
* Check if the wait is (already) satisfied
*/
CountSignaled = 0;
Abandoned = FALSE;
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *) Object[i];
if (KiIsObjectSignalled(hdr, CurrentThread, &Abandoned))
if (KiIsObjectSignalled(hdr, CurrentThread))
{
CountSignaled++;
if (WaitType == WaitAny)
{
if (Timeout != NULL)
Abandoned = KiSideEffectsBeforeWake(hdr, CurrentThread) ? TRUE : Abandoned;
if (Timeout != NULL && Timeout->QuadPart != 0)
{
KeCancelTimer(&CurrentThread->Timer);
}
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("One object is already signaled!\n");
DPRINT("One object is (already) signaled!\n");
if (Abandoned == TRUE)
{
return (STATUS_ABANDONED_WAIT_0 + i);
}
return (STATUS_WAIT_0 + i);
}
}
}
Abandoned = FALSE;
if ((WaitType == WaitAll) && (CountSignaled == Count))
{
if (Timeout != NULL)
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *) Object[i];
Abandoned = KiSideEffectsBeforeWake(hdr, CurrentThread) ? TRUE : Abandoned;
}
if (Timeout != NULL && Timeout->QuadPart != 0)
{
KeCancelTimer(&CurrentThread->Timer);
}
KeReleaseDispatcherDatabaseLock(FALSE);
DPRINT("All objects are already signaled!\n");
DPRINT("All objects are (already) signaled!\n");
if (Abandoned == TRUE)
{
return (STATUS_ABANDONED_WAIT_0);
}
return (STATUS_WAIT_0);
}
//zero timeout is used for testing if the object(s) can be immediately acquired
if (Timeout != NULL && Timeout->QuadPart == 0)
{
KeReleaseDispatcherDatabaseLock(FALSE);
return STATUS_TIMEOUT;
}
/*
* Check if we have already timed out
*/
if (Timeout != NULL &&
KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread, NULL))
if (Timeout != NULL && KiIsObjectSignalled(&CurrentThread->Timer.Header, CurrentThread))
{
KiSideEffectsBeforeWake(&CurrentThread->Timer.Header, CurrentThread);
KeCancelTimer(&CurrentThread->Timer);
KeReleaseDispatcherDatabaseLock(FALSE);
return (STATUS_TIMEOUT);
@ -673,6 +561,7 @@ KeWaitForMultipleObjects(ULONG Count,
* Set up the wait
*/
CurrentThread->WaitStatus = STATUS_UNSUCCESSFUL;
for (i = 0; i < Count; i++)
{
hdr = (DISPATCHER_HEADER *) Object[i];
@ -681,6 +570,7 @@ KeWaitForMultipleObjects(ULONG Count,
blk->Thread = CurrentThread;
blk->WaitKey = STATUS_WAIT_0 + i;
blk->WaitType = WaitType;
if (i == (Count - 1))
{
if (Timeout != NULL)
@ -697,10 +587,12 @@ KeWaitForMultipleObjects(ULONG Count,
blk->NextWaitBlock = blk + 1;
}
//add wait block to disp. obj. wait list
InsertTailList(&hdr->WaitListHead, &blk->WaitListEntry);
blk = blk->NextWaitBlock;
}
if (Timeout != NULL)
{
CurrentThread->WaitBlock[3].Object = (PVOID) & CurrentThread->Timer;
@ -708,12 +600,14 @@ KeWaitForMultipleObjects(ULONG Count,
CurrentThread->WaitBlock[3].WaitKey = STATUS_TIMEOUT;
CurrentThread->WaitBlock[3].WaitType = WaitAny;
CurrentThread->WaitBlock[3].NextWaitBlock = NULL;
InsertTailList(&CurrentThread->Timer.Header.WaitListHead,
&CurrentThread->WaitBlock[3].WaitListEntry);
}
PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql);
} while(Status == STATUS_KERNEL_APC);
}
while (Status == STATUS_KERNEL_APC);
if (Timeout != NULL)
{
@ -732,7 +626,7 @@ VOID KeInitializeDispatcher(VOID)
NTSTATUS STDCALL
NtWaitForMultipleObjects(IN ULONG Count,
IN HANDLE Object [],
IN CINT WaitType,
IN WAIT_TYPE WaitType,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time)
{
@ -740,6 +634,7 @@ NtWaitForMultipleObjects(IN ULONG Count,
PVOID ObjectPtrArray[EX_MAXIMUM_WAIT_OBJECTS];
NTSTATUS Status;
ULONG i, j;
KPROCESSOR_MODE WaitMode;
DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, "
"Time %x)\n", Count,Object,Alertable,Time);
@ -747,13 +642,15 @@ NtWaitForMultipleObjects(IN ULONG Count,
if (Count > EX_MAXIMUM_WAIT_OBJECTS)
return STATUS_UNSUCCESSFUL;
WaitMode = ExGetPreviousMode();
/* reference all objects */
for (i = 0; i < Count; i++)
{
Status = ObReferenceObjectByHandle(Object[i],
SYNCHRONIZE,
NULL,
UserMode,
WaitMode,
&ObjectPtrArray[i],
NULL);
if (Status != STATUS_SUCCESS)
@ -772,7 +669,7 @@ NtWaitForMultipleObjects(IN ULONG Count,
ObjectPtrArray,
WaitType,
UserRequest,
UserMode,
WaitMode,
Alertable,
Time,
WaitBlockArray);
@ -794,14 +691,17 @@ NtWaitForSingleObject(IN HANDLE Object,
{
PVOID ObjectPtr;
NTSTATUS Status;
KPROCESSOR_MODE WaitMode;
DPRINT("NtWaitForSingleObject(Object %x, Alertable %d, Time %x)\n",
Object,Alertable,Time);
WaitMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(Object,
SYNCHRONIZE,
NULL,
UserMode,
WaitMode,
&ObjectPtr,
NULL);
if (!NT_SUCCESS(Status))
@ -810,8 +710,8 @@ NtWaitForSingleObject(IN HANDLE Object,
}
Status = KeWaitForSingleObject(ObjectPtr,
UserMode,
UserMode,
UserRequest,
WaitMode,
Alertable,
Time);
@ -827,17 +727,17 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time)
{
KPROCESSOR_MODE ProcessorMode;
KPROCESSOR_MODE WaitMode;
DISPATCHER_HEADER* hdr;
PVOID SignalObj;
PVOID WaitObj;
NTSTATUS Status;
ProcessorMode = ExGetPreviousMode();
WaitMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(SignalObject,
0,
NULL,
ProcessorMode,
WaitMode,
&SignalObj,
NULL);
if (!NT_SUCCESS(Status))
@ -848,7 +748,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
Status = ObReferenceObjectByHandle(WaitObject,
SYNCHRONIZE,
NULL,
ProcessorMode,
WaitMode,
&WaitObj,
NULL);
if (!NT_SUCCESS(Status))
@ -887,7 +787,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
Status = KeWaitForSingleObject(WaitObj,
UserRequest,
ProcessorMode,
WaitMode,
Alertable,
Time);