1 /* $Id: evtpair.c,v 1.20 2003/12/30 18:52:05 fireball Exp $
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/ob.h>
22 #include <internal/ps.h>
26 #include <internal/debug.h>
37 /* GLOBALS *******************************************************************/
39 POBJECT_TYPE EXPORTED ExEventPairObjectType
= NULL
;
41 static GENERIC_MAPPING ExEventPairMapping
= {
43 STANDARD_RIGHTS_WRITE
,
44 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
45 EVENT_PAIR_ALL_ACCESS
};
47 static KSPIN_LOCK ExThreadEventPairSpinLock
;
49 /* FUNCTIONS *****************************************************************/
52 NtpCreateEventPair(PVOID ObjectBody
,
55 POBJECT_ATTRIBUTES ObjectAttributes
)
57 DPRINT("NtpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n",
58 ObjectBody
, Parent
, RemainingPath
);
60 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+1, '\\') != NULL
)
62 return(STATUS_UNSUCCESSFUL
);
65 return(STATUS_SUCCESS
);
69 NtInitializeEventPairImplementation(VOID
)
71 ExEventPairObjectType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
73 RtlCreateUnicodeString(&ExEventPairObjectType
->TypeName
, L
"EventPair");
75 ExEventPairObjectType
->MaxObjects
= ULONG_MAX
;
76 ExEventPairObjectType
->MaxHandles
= ULONG_MAX
;
77 ExEventPairObjectType
->TotalObjects
= 0;
78 ExEventPairObjectType
->TotalHandles
= 0;
79 ExEventPairObjectType
->PagedPoolCharge
= 0;
80 ExEventPairObjectType
->NonpagedPoolCharge
= sizeof(KEVENT_PAIR
);
81 ExEventPairObjectType
->Mapping
= &ExEventPairMapping
;
82 ExEventPairObjectType
->Dump
= NULL
;
83 ExEventPairObjectType
->Open
= NULL
;
84 ExEventPairObjectType
->Close
= NULL
;
85 ExEventPairObjectType
->Delete
= NULL
;
86 ExEventPairObjectType
->Parse
= NULL
;
87 ExEventPairObjectType
->Security
= NULL
;
88 ExEventPairObjectType
->QueryName
= NULL
;
89 ExEventPairObjectType
->OkayToClose
= NULL
;
90 ExEventPairObjectType
->Create
= NtpCreateEventPair
;
91 ExEventPairObjectType
->DuplicationNotify
= NULL
;
93 KeInitializeSpinLock(&ExThreadEventPairSpinLock
);
94 ObpCreateTypeObject(ExEventPairObjectType
);
99 NtCreateEventPair(OUT PHANDLE EventPairHandle
,
100 IN ACCESS_MASK DesiredAccess
,
101 IN POBJECT_ATTRIBUTES ObjectAttributes
)
103 PKEVENT_PAIR EventPair
;
106 DPRINT("NtCreateEventPair()\n");
107 Status
= ObCreateObject(ExGetPreviousMode(),
108 ExEventPairObjectType
,
116 if (!NT_SUCCESS(Status
))
121 KeInitializeEvent(&EventPair
->LowEvent
,
122 SynchronizationEvent
,
124 KeInitializeEvent(&EventPair
->HighEvent
,
125 SynchronizationEvent
,
128 Status
= ObInsertObject ((PVOID
)EventPair
,
135 ObDereferenceObject(EventPair
);
142 NtOpenEventPair(OUT PHANDLE EventPairHandle
,
143 IN ACCESS_MASK DesiredAccess
,
144 IN POBJECT_ATTRIBUTES ObjectAttributes
)
148 DPRINT("NtOpenEventPair()\n");
150 Status
= ObOpenObjectByName(ObjectAttributes
,
151 ExEventPairObjectType
,
163 NtSetHighEventPair(IN HANDLE EventPairHandle
)
165 PKEVENT_PAIR EventPair
;
168 DPRINT("NtSetHighEventPair(EventPairHandle %x)\n",
171 Status
= ObReferenceObjectByHandle(EventPairHandle
,
172 EVENT_PAIR_ALL_ACCESS
,
173 ExEventPairObjectType
,
177 if (!NT_SUCCESS(Status
))
180 KeSetEvent(&EventPair
->HighEvent
,
184 ObDereferenceObject(EventPair
);
185 return(STATUS_SUCCESS
);
190 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle
)
192 PKEVENT_PAIR EventPair
;
195 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n",
198 Status
= ObReferenceObjectByHandle(EventPairHandle
,
199 EVENT_PAIR_ALL_ACCESS
,
200 ExEventPairObjectType
,
204 if (!NT_SUCCESS(Status
))
207 KeSetEvent(&EventPair
->HighEvent
,
211 KeWaitForSingleObject(&EventPair
->LowEvent
,
217 ObDereferenceObject(EventPair
);
218 return(STATUS_SUCCESS
);
223 NtSetLowEventPair(IN HANDLE EventPairHandle
)
225 PKEVENT_PAIR EventPair
;
228 DPRINT("NtSetLowEventPair(EventPairHandle %x)\n",
231 Status
= ObReferenceObjectByHandle(EventPairHandle
,
232 EVENT_PAIR_ALL_ACCESS
,
233 ExEventPairObjectType
,
237 if (!NT_SUCCESS(Status
))
240 KeSetEvent(&EventPair
->LowEvent
,
244 ObDereferenceObject(EventPair
);
245 return(STATUS_SUCCESS
);
250 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle
)
252 PKEVENT_PAIR EventPair
;
255 DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n",
258 Status
= ObReferenceObjectByHandle(EventPairHandle
,
259 EVENT_PAIR_ALL_ACCESS
,
260 ExEventPairObjectType
,
264 if (!NT_SUCCESS(Status
))
267 KeSetEvent(&EventPair
->LowEvent
,
271 KeWaitForSingleObject(&EventPair
->HighEvent
,
277 ObDereferenceObject(EventPair
);
278 return(STATUS_SUCCESS
);
283 NtWaitLowEventPair(IN HANDLE EventPairHandle
)
285 PKEVENT_PAIR EventPair
;
288 DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
291 Status
= ObReferenceObjectByHandle(EventPairHandle
,
292 EVENT_PAIR_ALL_ACCESS
,
293 ExEventPairObjectType
,
297 if (!NT_SUCCESS(Status
))
300 KeWaitForSingleObject(&EventPair
->LowEvent
,
306 ObDereferenceObject(EventPair
);
307 return(STATUS_SUCCESS
);
312 NtWaitHighEventPair(IN HANDLE EventPairHandle
)
314 PKEVENT_PAIR EventPair
;
317 DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
320 Status
= ObReferenceObjectByHandle(EventPairHandle
,
321 EVENT_PAIR_ALL_ACCESS
,
322 ExEventPairObjectType
,
326 if (!NT_SUCCESS(Status
))
329 KeWaitForSingleObject(&EventPair
->HighEvent
,
335 ObDereferenceObject(EventPair
);
336 return(STATUS_SUCCESS
);
340 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
341 * Note that the eventpair spinlock must be acquired when setting the thread
342 * eventpair via NtSetInformationThread.
348 NtSetLowWaitHighThread(
353 PKEVENT_PAIR EventPair
;
357 Thread
= PsGetCurrentThread();
359 if(!Thread
->EventPair
)
360 return STATUS_NO_EVENT_PAIR
;
362 KeAcquireSpinLock(&ExThreadEventPairSpinLock
, &Irql
);
364 EventPair
= Thread
->EventPair
;
367 ObReferenceObjectByPointer(EventPair
,
368 EVENT_PAIR_ALL_ACCESS
,
369 ExEventPairObjectType
,
372 KeReleaseSpinLock(&ExThreadEventPairSpinLock
, Irql
);
374 if(EventPair
== NULL
)
375 return STATUS_NO_EVENT_PAIR
;
377 KeSetEvent(&EventPair
->LowEvent
,
381 Status
= KeWaitForSingleObject(&EventPair
->HighEvent
,
387 ObDereferenceObject(EventPair
);
394 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
395 * Note that the eventpair spinlock must be acquired when setting the thread
396 * eventpair via NtSetInformationThread.
402 NtSetHighWaitLowThread(
407 PKEVENT_PAIR EventPair
;
411 Thread
= PsGetCurrentThread();
413 if(!Thread
->EventPair
)
414 return STATUS_NO_EVENT_PAIR
;
416 KeAcquireSpinLock(&ExThreadEventPairSpinLock
, &Irql
);
418 EventPair
= PsGetCurrentThread()->EventPair
;
421 ObReferenceObjectByPointer(EventPair
,
422 EVENT_PAIR_ALL_ACCESS
,
423 ExEventPairObjectType
,
426 KeReleaseSpinLock(&ExThreadEventPairSpinLock
, Irql
);
428 if(EventPair
== NULL
)
429 return STATUS_NO_EVENT_PAIR
;
431 KeSetEvent(&EventPair
->HighEvent
,
435 Status
= KeWaitForSingleObject(&EventPair
->LowEvent
,
441 ObDereferenceObject(EventPair
);
447 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
448 * Note that the eventpair spinlock must be acquired when waiting on the
449 * eventpair via NtSetLow/HighWaitHigh/LowThread. Additionally, when
450 * deleting a thread object, NtpSwapThreadEventPair(Thread, NULL) should
451 * be called to release any preexisting eventpair object associated with
452 * the thread. The Microsoft name for this function is not known.
455 ExpSwapThreadEventPair(
457 IN PKEVENT_PAIR EventPair
460 PKEVENT_PAIR OriginalEventPair
;
463 KeAcquireSpinLock(&ExThreadEventPairSpinLock
, &Irql
);
465 OriginalEventPair
= Thread
->EventPair
;
466 Thread
->EventPair
= EventPair
;
468 if(OriginalEventPair
)
469 ObDereferenceObject(OriginalEventPair
);
471 KeReleaseSpinLock(&ExThreadEventPairSpinLock
, Irql
);