* PROGRAMMER: David Welch (welch@mcmail.com)
* UPDATE HISTORY:
* Created 22/05/98
+ * Updated 09/08/2003 by Skywing (skywing@valhallalegends.com)
+ * to correctly maintain ownership of the dispatcher lock
+ * between KeSetEvent and KeWaitForSingleObject calls.
+ * Additionally, implemented the thread-eventpair routines.
*/
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
#include <ntos/synch.h>
+#include <internal/ps.h>
#include <limits.h>
#define NDEBUG
#include <internal/debug.h>
+#ifndef NTSYSAPI
+#define NTSYSAPI
+#endif
+
+#ifndef NTAPI
+#define NTAPI STDCALL
+#endif
+
/* GLOBALS *******************************************************************/
STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
EVENT_PAIR_ALL_ACCESS};
+static KSPIN_LOCK ExThreadEventPairSpinLock;
+
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
ExEventPairObjectType->OkayToClose = NULL;
ExEventPairObjectType->Create = NtpCreateEventPair;
ExEventPairObjectType->DuplicationNotify = NULL;
+
+ KeInitializeSpinLock(&ExThreadEventPairSpinLock);
}
NTSTATUS Status;
DPRINT("NtCreateEventPair()\n");
- Status = ObCreateObject(EventPairHandle,
+ Status = ObRosCreateObject(EventPairHandle,
DesiredAccess,
ObjectAttributes,
ExEventPairObjectType,
KeSetEvent(&EventPair->HighEvent,
EVENT_INCREMENT,
- FALSE);
+ TRUE);
KeWaitForSingleObject(&EventPair->LowEvent,
WrEventPair,
KeSetEvent(&EventPair->LowEvent,
EVENT_INCREMENT,
- FALSE);
+ TRUE);
KeWaitForSingleObject(&EventPair->HighEvent,
WrEventPair,
return(STATUS_SUCCESS);
}
+/*
+ * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
+ * Note that the eventpair spinlock must be acquired when setting the thread
+ * eventpair via NtSetInformationThread.
+ * @implemented
+ */
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtSetLowWaitHighThread(
+ VOID
+ )
+{
+ PETHREAD Thread;
+ PKEVENT_PAIR EventPair;
+ NTSTATUS Status;
+ KIRQL Irql;
+
+ Thread = PsGetCurrentThread();
+
+ if(!Thread->EventPair)
+ return STATUS_NO_EVENT_PAIR;
+
+ KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
+
+ EventPair = Thread->EventPair;
+
+ if(EventPair)
+ ObReferenceObjectByPointer(EventPair,
+ EVENT_PAIR_ALL_ACCESS,
+ ExEventPairObjectType,
+ UserMode);
+
+ KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
+
+ if(EventPair == NULL)
+ return STATUS_NO_EVENT_PAIR;
+
+ KeSetEvent(&EventPair->LowEvent,
+ EVENT_INCREMENT,
+ TRUE);
+
+ Status = KeWaitForSingleObject(&EventPair->HighEvent,
+ WrEventPair,
+ UserMode,
+ FALSE,
+ NULL);
+
+ ObDereferenceObject(EventPair);
+
+ return Status;
+}
+
+
+/*
+ * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
+ * Note that the eventpair spinlock must be acquired when setting the thread
+ * eventpair via NtSetInformationThread.
+ * @implemented
+ */
+NTSYSAPI
+NTSTATUS
+NTAPI
+NtSetHighWaitLowThread(
+ VOID
+ )
+{
+ PETHREAD Thread;
+ PKEVENT_PAIR EventPair;
+ NTSTATUS Status;
+ KIRQL Irql;
+
+ Thread = PsGetCurrentThread();
+
+ if(!Thread->EventPair)
+ return STATUS_NO_EVENT_PAIR;
+
+ KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
+
+ EventPair = PsGetCurrentThread()->EventPair;
+
+ if(EventPair)
+ ObReferenceObjectByPointer(EventPair,
+ EVENT_PAIR_ALL_ACCESS,
+ ExEventPairObjectType,
+ UserMode);
+
+ KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
+
+ if(EventPair == NULL)
+ return STATUS_NO_EVENT_PAIR;
+
+ KeSetEvent(&EventPair->HighEvent,
+ EVENT_INCREMENT,
+ TRUE);
+
+ Status = KeWaitForSingleObject(&EventPair->LowEvent,
+ WrEventPair,
+ UserMode,
+ FALSE,
+ NULL);
+
+ ObDereferenceObject(EventPair);
+
+ return Status;
+}
+
+/*
+ * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
+ * Note that the eventpair spinlock must be acquired when waiting on the
+ * eventpair via NtSetLow/HighWaitHigh/LowThread. Additionally, when
+ * deleting a thread object, NtpSwapThreadEventPair(Thread, NULL) should
+ * be called to release any preexisting eventpair object associated with
+ * the thread. The Microsoft name for this function is not known.
+ */
+VOID
+ExpSwapThreadEventPair(
+ IN PETHREAD Thread,
+ IN PKEVENT_PAIR EventPair
+ )
+{
+ PKEVENT_PAIR OriginalEventPair;
+ KIRQL Irql;
+
+ KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
+
+ OriginalEventPair = Thread->EventPair;
+ Thread->EventPair = EventPair;
+
+ if(OriginalEventPair)
+ ObDereferenceObject(OriginalEventPair);
+
+ KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
+}
+
/* EOF */