diff --git a/reactos/ntoskrnl/ex/keyedevt.c b/reactos/ntoskrnl/ex/keyedevt.c index 2dad43ee6dd..18721e88d60 100644 --- a/reactos/ntoskrnl/ex/keyedevt.c +++ b/reactos/ntoskrnl/ex/keyedevt.c @@ -132,6 +132,7 @@ ExpReleaseOrWaitForKeyedEvent( PLIST_ENTRY ListEntry, WaitListHead1, WaitListHead2; NTSTATUS Status; ULONG_PTR HashIndex; + PVOID PreviousKeyedWaitValue; /* Get the current process */ CurrentProcess = KeGetCurrentProcess(); @@ -167,6 +168,7 @@ ExpReleaseOrWaitForKeyedEvent( be signaled by this thread or, when the wait is aborted due to thread termination, then it first needs to acquire the list lock. */ Thread = CONTAINING_RECORD(ListEntry, ETHREAD, KeyedWaitChain); + ListEntry = ListEntry->Flink; /* Check if this thread is a correct waiter */ if ((Thread->Tcb.Process == CurrentProcess) && @@ -179,7 +181,10 @@ ExpReleaseOrWaitForKeyedEvent( InitializeListHead(&Thread->KeyedWaitChain); /* Wake the thread */ - KeReleaseSemaphore(&Thread->KeyedWaitSemaphore, 0, 1, FALSE); + KeReleaseSemaphore(&Thread->KeyedWaitSemaphore, + IO_NO_INCREMENT, + 1, + FALSE); Thread = NULL; /* Unlock the list. After this it is not safe to access Thread */ @@ -193,7 +198,8 @@ ExpReleaseOrWaitForKeyedEvent( /* Get the current thread */ CurrentThread = PsGetCurrentThread(); - /* Set the wait key */ + /* Set the wait key and remember the old value */ + PreviousKeyedWaitValue = CurrentThread->KeyedWaitValue; CurrentThread->KeyedWaitValue = KeyedWaitValue; /* Initialize the wait semaphore */ @@ -221,10 +227,11 @@ ExpReleaseOrWaitForKeyedEvent( ExAcquirePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock); /* Check if the wait list entry is still in the list */ - if (CurrentThread->KeyedWaitChain.Flink != &CurrentThread->KeyedWaitChain) + if (!IsListEmpty(&CurrentThread->KeyedWaitChain)) { /* Remove the thread from the list */ RemoveEntryList(&CurrentThread->KeyedWaitChain); + InitializeListHead(&CurrentThread->KeyedWaitChain); } /* Unlock the list */ @@ -232,6 +239,9 @@ ExpReleaseOrWaitForKeyedEvent( KeLeaveCriticalRegion(); } + /* Restore the previous KeyedWaitValue, since this is a union member */ + CurrentThread->KeyedWaitValue = PreviousKeyedWaitValue; + return Status; } @@ -412,6 +422,12 @@ NtWaitForKeyedEvent( NTSTATUS Status; LARGE_INTEGER TimeoutCopy; + /* Key must always be two-byte aligned */ + if ((ULONG_PTR)Key & 1) + { + return STATUS_INVALID_PARAMETER_1; + } + /* Check if the caller passed a timeout value and this is from user mode */ if ((Timeout != NULL) && (PreviousMode != KernelMode)) { @@ -472,6 +488,12 @@ NtReleaseKeyedEvent( NTSTATUS Status; LARGE_INTEGER TimeoutCopy; + /* Key must always be two-byte aligned */ + if ((ULONG_PTR)Key & 1) + { + return STATUS_INVALID_PARAMETER_1; + } + /* Check if the caller passed a timeout value and this is from user mode */ if ((Timeout != NULL) && (PreviousMode != KernelMode)) { diff --git a/reactos/ntoskrnl/ke/thrdobj.c b/reactos/ntoskrnl/ke/thrdobj.c index 1e3e79e7abd..15a18b59583 100644 --- a/reactos/ntoskrnl/ke/thrdobj.c +++ b/reactos/ntoskrnl/ke/thrdobj.c @@ -838,8 +838,9 @@ KeInitThread(IN OUT PKTHREAD Thread, TimerWaitBlock->WaitListEntry.Flink = &Timer->Header.WaitListHead; TimerWaitBlock->WaitListEntry.Blink = &Timer->Header.WaitListHead; - /* Set the TEB */ + /* Set the TEB and process */ Thread->Teb = Teb; + Thread->Process = Process; /* Check if we have a kernel stack */ if (!KernelStack) diff --git a/rostests/winetests/ntdll/om.c b/rostests/winetests/ntdll/om.c index cca05c90819..ca843993294 100644 --- a/rostests/winetests/ntdll/om.c +++ b/rostests/winetests/ntdll/om.c @@ -1080,8 +1080,5 @@ START_TEST(om) test_query_object(); test_type_mismatch(); test_event(); - if (winetest_interactive) - test_keyed_events(); - else - skip("Skipping test_keyed_events(). ROSTESTS-118.\n"); + test_keyed_events(); }