3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/nt/evtpair.c
6 * PURPOSE: Support for event pairs
7 * PROGRAMMER: David Welch (welch@mcmail.com)
10 * Updated 09/08/2003 by Skywing (skywing@valhallalegends.com)
11 * to correctly maintain ownership of the dispatcher lock
12 * between KeSetEvent and KeWaitForSingleObject calls.
13 * Additionally, implemented the thread-eventpair routines.
16 /* INCLUDES *****************************************************************/
18 #define NTOS_MODE_KERNEL
20 #include <ntos/synch.h>
21 #include <internal/ps.h>
25 #include <internal/debug.h>
36 /* GLOBALS *******************************************************************/
38 POBJECT_TYPE EXPORTED ExEventPairObjectType = NULL;
40 static GENERIC_MAPPING ExEventPairMapping = {
42 STANDARD_RIGHTS_WRITE,
43 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
44 EVENT_PAIR_ALL_ACCESS};
46 static KSPIN_LOCK ExThreadEventPairSpinLock;
48 /* FUNCTIONS *****************************************************************/
51 NtpCreateEventPair(PVOID ObjectBody,
54 POBJECT_ATTRIBUTES ObjectAttributes)
56 DPRINT("NtpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n",
57 ObjectBody, Parent, RemainingPath);
59 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
61 return(STATUS_UNSUCCESSFUL);
64 return(STATUS_SUCCESS);
67 VOID NtInitializeEventPairImplementation(VOID)
69 ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
71 RtlCreateUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair");
73 ExEventPairObjectType->MaxObjects = ULONG_MAX;
74 ExEventPairObjectType->MaxHandles = ULONG_MAX;
75 ExEventPairObjectType->TotalObjects = 0;
76 ExEventPairObjectType->TotalHandles = 0;
77 ExEventPairObjectType->PagedPoolCharge = 0;
78 ExEventPairObjectType->NonpagedPoolCharge = sizeof(KEVENT_PAIR);
79 ExEventPairObjectType->Mapping = &ExEventPairMapping;
80 ExEventPairObjectType->Dump = NULL;
81 ExEventPairObjectType->Open = NULL;
82 ExEventPairObjectType->Close = NULL;
83 ExEventPairObjectType->Delete = NULL;
84 ExEventPairObjectType->Parse = NULL;
85 ExEventPairObjectType->Security = NULL;
86 ExEventPairObjectType->QueryName = NULL;
87 ExEventPairObjectType->OkayToClose = NULL;
88 ExEventPairObjectType->Create = NtpCreateEventPair;
89 ExEventPairObjectType->DuplicationNotify = NULL;
91 KeInitializeSpinLock(&ExThreadEventPairSpinLock);
96 NtCreateEventPair(OUT PHANDLE EventPairHandle,
97 IN ACCESS_MASK DesiredAccess,
98 IN POBJECT_ATTRIBUTES ObjectAttributes)
100 PKEVENT_PAIR EventPair;
103 DPRINT("NtCreateEventPair()\n");
104 Status = ObRosCreateObject(EventPairHandle,
107 ExEventPairObjectType,
109 if (!NT_SUCCESS(Status))
113 KeInitializeEvent(&EventPair->LowEvent,
114 SynchronizationEvent,
116 KeInitializeEvent(&EventPair->HighEvent,
117 SynchronizationEvent,
119 ObDereferenceObject(EventPair);
120 return(STATUS_SUCCESS);
125 NtOpenEventPair(OUT PHANDLE EventPairHandle,
126 IN ACCESS_MASK DesiredAccess,
127 IN POBJECT_ATTRIBUTES ObjectAttributes)
131 DPRINT("NtOpenEventPair()\n");
133 Status = ObOpenObjectByName(ObjectAttributes,
134 ExEventPairObjectType,
146 NtSetHighEventPair(IN HANDLE EventPairHandle)
148 PKEVENT_PAIR EventPair;
151 DPRINT("NtSetHighEventPair(EventPairHandle %x)\n",
154 Status = ObReferenceObjectByHandle(EventPairHandle,
155 EVENT_PAIR_ALL_ACCESS,
156 ExEventPairObjectType,
160 if (!NT_SUCCESS(Status))
163 KeSetEvent(&EventPair->HighEvent,
167 ObDereferenceObject(EventPair);
168 return(STATUS_SUCCESS);
173 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
175 PKEVENT_PAIR EventPair;
178 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n",
181 Status = ObReferenceObjectByHandle(EventPairHandle,
182 EVENT_PAIR_ALL_ACCESS,
183 ExEventPairObjectType,
187 if (!NT_SUCCESS(Status))
190 KeSetEvent(&EventPair->HighEvent,
194 KeWaitForSingleObject(&EventPair->LowEvent,
200 ObDereferenceObject(EventPair);
201 return(STATUS_SUCCESS);
206 NtSetLowEventPair(IN HANDLE EventPairHandle)
208 PKEVENT_PAIR EventPair;
211 DPRINT("NtSetLowEventPair(EventPairHandle %x)\n",
214 Status = ObReferenceObjectByHandle(EventPairHandle,
215 EVENT_PAIR_ALL_ACCESS,
216 ExEventPairObjectType,
220 if (!NT_SUCCESS(Status))
223 KeSetEvent(&EventPair->LowEvent,
227 ObDereferenceObject(EventPair);
228 return(STATUS_SUCCESS);
233 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
235 PKEVENT_PAIR EventPair;
238 DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n",
241 Status = ObReferenceObjectByHandle(EventPairHandle,
242 EVENT_PAIR_ALL_ACCESS,
243 ExEventPairObjectType,
247 if (!NT_SUCCESS(Status))
250 KeSetEvent(&EventPair->LowEvent,
254 KeWaitForSingleObject(&EventPair->HighEvent,
260 ObDereferenceObject(EventPair);
261 return(STATUS_SUCCESS);
266 NtWaitLowEventPair(IN HANDLE EventPairHandle)
268 PKEVENT_PAIR EventPair;
271 DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
274 Status = ObReferenceObjectByHandle(EventPairHandle,
275 EVENT_PAIR_ALL_ACCESS,
276 ExEventPairObjectType,
280 if (!NT_SUCCESS(Status))
283 KeWaitForSingleObject(&EventPair->LowEvent,
289 ObDereferenceObject(EventPair);
290 return(STATUS_SUCCESS);
295 NtWaitHighEventPair(IN HANDLE EventPairHandle)
297 PKEVENT_PAIR EventPair;
300 DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
303 Status = ObReferenceObjectByHandle(EventPairHandle,
304 EVENT_PAIR_ALL_ACCESS,
305 ExEventPairObjectType,
309 if (!NT_SUCCESS(Status))
312 KeWaitForSingleObject(&EventPair->HighEvent,
318 ObDereferenceObject(EventPair);
319 return(STATUS_SUCCESS);
323 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
324 * Note that the eventpair spinlock must be acquired when setting the thread
325 * eventpair via NtSetInformationThread.
331 NtSetLowWaitHighThread(
336 PKEVENT_PAIR EventPair;
340 Thread = PsGetCurrentThread();
342 if(!Thread->EventPair)
343 return STATUS_NO_EVENT_PAIR;
345 KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
347 EventPair = Thread->EventPair;
350 ObReferenceObjectByPointer(EventPair,
351 EVENT_PAIR_ALL_ACCESS,
352 ExEventPairObjectType,
355 KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
357 if(EventPair == NULL)
358 return STATUS_NO_EVENT_PAIR;
360 KeSetEvent(&EventPair->LowEvent,
364 Status = KeWaitForSingleObject(&EventPair->HighEvent,
370 ObDereferenceObject(EventPair);
377 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
378 * Note that the eventpair spinlock must be acquired when setting the thread
379 * eventpair via NtSetInformationThread.
385 NtSetHighWaitLowThread(
390 PKEVENT_PAIR EventPair;
394 Thread = PsGetCurrentThread();
396 if(!Thread->EventPair)
397 return STATUS_NO_EVENT_PAIR;
399 KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
401 EventPair = PsGetCurrentThread()->EventPair;
404 ObReferenceObjectByPointer(EventPair,
405 EVENT_PAIR_ALL_ACCESS,
406 ExEventPairObjectType,
409 KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
411 if(EventPair == NULL)
412 return STATUS_NO_EVENT_PAIR;
414 KeSetEvent(&EventPair->HighEvent,
418 Status = KeWaitForSingleObject(&EventPair->LowEvent,
424 ObDereferenceObject(EventPair);
430 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
431 * Note that the eventpair spinlock must be acquired when waiting on the
432 * eventpair via NtSetLow/HighWaitHigh/LowThread. Additionally, when
433 * deleting a thread object, NtpSwapThreadEventPair(Thread, NULL) should
434 * be called to release any preexisting eventpair object associated with
435 * the thread. The Microsoft name for this function is not known.
438 ExpSwapThreadEventPair(
440 IN PKEVENT_PAIR EventPair
443 PKEVENT_PAIR OriginalEventPair;
446 KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
448 OriginalEventPair = Thread->EventPair;
449 Thread->EventPair = EventPair;
451 if(OriginalEventPair)
452 ObDereferenceObject(OriginalEventPair);
454 KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);