1 /* $Id: evtpair.c,v 1.23 2004/09/28 15:02:29 weiden 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 *****************************************************************/
20 #include <internal/debug.h>
31 /* GLOBALS *******************************************************************/
33 POBJECT_TYPE EXPORTED ExEventPairObjectType
= NULL
;
35 static GENERIC_MAPPING ExEventPairMapping
= {
37 STANDARD_RIGHTS_WRITE
,
38 STANDARD_RIGHTS_EXECUTE
| SYNCHRONIZE
,
39 EVENT_PAIR_ALL_ACCESS
};
41 static KSPIN_LOCK ExThreadEventPairSpinLock
;
43 /* FUNCTIONS *****************************************************************/
46 NtpCreateEventPair(PVOID ObjectBody
,
49 POBJECT_ATTRIBUTES ObjectAttributes
)
51 DPRINT("NtpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n",
52 ObjectBody
, Parent
, RemainingPath
);
54 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+1, '\\') != NULL
)
56 return(STATUS_UNSUCCESSFUL
);
59 return(STATUS_SUCCESS
);
63 NtInitializeEventPairImplementation(VOID
)
65 ExEventPairObjectType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
67 RtlCreateUnicodeString(&ExEventPairObjectType
->TypeName
, L
"EventPair");
68 ExEventPairObjectType
->Tag
= TAG('E', 'v', 'P', 'a');
69 ExEventPairObjectType
->MaxObjects
= ULONG_MAX
;
70 ExEventPairObjectType
->MaxHandles
= ULONG_MAX
;
71 ExEventPairObjectType
->TotalObjects
= 0;
72 ExEventPairObjectType
->TotalHandles
= 0;
73 ExEventPairObjectType
->PagedPoolCharge
= 0;
74 ExEventPairObjectType
->NonpagedPoolCharge
= sizeof(KEVENT_PAIR
);
75 ExEventPairObjectType
->Mapping
= &ExEventPairMapping
;
76 ExEventPairObjectType
->Dump
= NULL
;
77 ExEventPairObjectType
->Open
= NULL
;
78 ExEventPairObjectType
->Close
= NULL
;
79 ExEventPairObjectType
->Delete
= NULL
;
80 ExEventPairObjectType
->Parse
= NULL
;
81 ExEventPairObjectType
->Security
= NULL
;
82 ExEventPairObjectType
->QueryName
= NULL
;
83 ExEventPairObjectType
->OkayToClose
= NULL
;
84 ExEventPairObjectType
->Create
= NtpCreateEventPair
;
85 ExEventPairObjectType
->DuplicationNotify
= NULL
;
87 KeInitializeSpinLock(&ExThreadEventPairSpinLock
);
88 ObpCreateTypeObject(ExEventPairObjectType
);
93 NtCreateEventPair(OUT PHANDLE EventPairHandle
,
94 IN ACCESS_MASK DesiredAccess
,
95 IN POBJECT_ATTRIBUTES ObjectAttributes
)
97 PKEVENT_PAIR EventPair
;
100 DPRINT("NtCreateEventPair()\n");
101 Status
= ObCreateObject(ExGetPreviousMode(),
102 ExEventPairObjectType
,
110 if (!NT_SUCCESS(Status
))
115 KeInitializeEvent(&EventPair
->LowEvent
,
116 SynchronizationEvent
,
118 KeInitializeEvent(&EventPair
->HighEvent
,
119 SynchronizationEvent
,
122 Status
= ObInsertObject ((PVOID
)EventPair
,
129 ObDereferenceObject(EventPair
);
136 NtOpenEventPair(OUT PHANDLE EventPairHandle
,
137 IN ACCESS_MASK DesiredAccess
,
138 IN POBJECT_ATTRIBUTES ObjectAttributes
)
142 DPRINT("NtOpenEventPair()\n");
144 Status
= ObOpenObjectByName(ObjectAttributes
,
145 ExEventPairObjectType
,
157 NtSetHighEventPair(IN HANDLE EventPairHandle
)
159 PKEVENT_PAIR EventPair
;
162 DPRINT("NtSetHighEventPair(EventPairHandle %x)\n",
165 Status
= ObReferenceObjectByHandle(EventPairHandle
,
166 EVENT_PAIR_ALL_ACCESS
,
167 ExEventPairObjectType
,
171 if (!NT_SUCCESS(Status
))
174 KeSetEvent(&EventPair
->HighEvent
,
178 ObDereferenceObject(EventPair
);
179 return(STATUS_SUCCESS
);
184 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle
)
186 PKEVENT_PAIR EventPair
;
189 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n",
192 Status
= ObReferenceObjectByHandle(EventPairHandle
,
193 EVENT_PAIR_ALL_ACCESS
,
194 ExEventPairObjectType
,
198 if (!NT_SUCCESS(Status
))
201 KeSetEvent(&EventPair
->HighEvent
,
205 KeWaitForSingleObject(&EventPair
->LowEvent
,
211 ObDereferenceObject(EventPair
);
212 return(STATUS_SUCCESS
);
217 NtSetLowEventPair(IN HANDLE EventPairHandle
)
219 PKEVENT_PAIR EventPair
;
222 DPRINT("NtSetLowEventPair(EventPairHandle %x)\n",
225 Status
= ObReferenceObjectByHandle(EventPairHandle
,
226 EVENT_PAIR_ALL_ACCESS
,
227 ExEventPairObjectType
,
231 if (!NT_SUCCESS(Status
))
234 KeSetEvent(&EventPair
->LowEvent
,
238 ObDereferenceObject(EventPair
);
239 return(STATUS_SUCCESS
);
244 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle
)
246 PKEVENT_PAIR EventPair
;
249 DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n",
252 Status
= ObReferenceObjectByHandle(EventPairHandle
,
253 EVENT_PAIR_ALL_ACCESS
,
254 ExEventPairObjectType
,
258 if (!NT_SUCCESS(Status
))
261 KeSetEvent(&EventPair
->LowEvent
,
265 KeWaitForSingleObject(&EventPair
->HighEvent
,
271 ObDereferenceObject(EventPair
);
272 return(STATUS_SUCCESS
);
277 NtWaitLowEventPair(IN HANDLE EventPairHandle
)
279 PKEVENT_PAIR EventPair
;
282 DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
285 Status
= ObReferenceObjectByHandle(EventPairHandle
,
286 EVENT_PAIR_ALL_ACCESS
,
287 ExEventPairObjectType
,
291 if (!NT_SUCCESS(Status
))
294 KeWaitForSingleObject(&EventPair
->LowEvent
,
300 ObDereferenceObject(EventPair
);
301 return(STATUS_SUCCESS
);
306 NtWaitHighEventPair(IN HANDLE EventPairHandle
)
308 PKEVENT_PAIR EventPair
;
311 DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
314 Status
= ObReferenceObjectByHandle(EventPairHandle
,
315 EVENT_PAIR_ALL_ACCESS
,
316 ExEventPairObjectType
,
320 if (!NT_SUCCESS(Status
))
323 KeWaitForSingleObject(&EventPair
->HighEvent
,
329 ObDereferenceObject(EventPair
);
330 return(STATUS_SUCCESS
);
333 #ifdef _ENABLE_THRDEVTPAIR
336 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
337 * Note that the eventpair spinlock must be acquired when setting the thread
338 * eventpair via NtSetInformationThread.
344 NtSetLowWaitHighThread(
349 PKEVENT_PAIR EventPair
;
353 Thread
= PsGetCurrentThread();
355 if(!Thread
->EventPair
)
356 return STATUS_NO_EVENT_PAIR
;
358 KeAcquireSpinLock(&ExThreadEventPairSpinLock
, &Irql
);
360 EventPair
= Thread
->EventPair
;
363 ObReferenceObjectByPointer(EventPair
,
364 EVENT_PAIR_ALL_ACCESS
,
365 ExEventPairObjectType
,
368 KeReleaseSpinLock(&ExThreadEventPairSpinLock
, Irql
);
370 if(EventPair
== NULL
)
371 return STATUS_NO_EVENT_PAIR
;
373 KeSetEvent(&EventPair
->LowEvent
,
377 Status
= KeWaitForSingleObject(&EventPair
->HighEvent
,
383 ObDereferenceObject(EventPair
);
390 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
391 * Note that the eventpair spinlock must be acquired when setting the thread
392 * eventpair via NtSetInformationThread.
398 NtSetHighWaitLowThread(
403 PKEVENT_PAIR EventPair
;
407 Thread
= PsGetCurrentThread();
409 if(!Thread
->EventPair
)
410 return STATUS_NO_EVENT_PAIR
;
412 KeAcquireSpinLock(&ExThreadEventPairSpinLock
, &Irql
);
414 EventPair
= PsGetCurrentThread()->EventPair
;
417 ObReferenceObjectByPointer(EventPair
,
418 EVENT_PAIR_ALL_ACCESS
,
419 ExEventPairObjectType
,
422 KeReleaseSpinLock(&ExThreadEventPairSpinLock
, Irql
);
424 if(EventPair
== NULL
)
425 return STATUS_NO_EVENT_PAIR
;
427 KeSetEvent(&EventPair
->HighEvent
,
431 Status
= KeWaitForSingleObject(&EventPair
->LowEvent
,
437 ObDereferenceObject(EventPair
);
443 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
444 * Note that the eventpair spinlock must be acquired when waiting on the
445 * eventpair via NtSetLow/HighWaitHigh/LowThread. Additionally, when
446 * deleting a thread object, NtpSwapThreadEventPair(Thread, NULL) should
447 * be called to release any preexisting eventpair object associated with
448 * the thread. The Microsoft name for this function is not known.
451 ExpSwapThreadEventPair(
453 IN PKEVENT_PAIR EventPair
456 PKEVENT_PAIR OriginalEventPair
;
459 KeAcquireSpinLock(&ExThreadEventPairSpinLock
, &Irql
);
461 OriginalEventPair
= Thread
->EventPair
;
462 Thread
->EventPair
= EventPair
;
464 if(OriginalEventPair
)
465 ObDereferenceObject(OriginalEventPair
);
467 KeReleaseSpinLock(&ExThreadEventPairSpinLock
, Irql
);
470 #else /* !_ENABLE_THRDEVTPAIR */
475 NtSetLowWaitHighThread(
479 DPRINT1("NtSetLowWaitHighThread() not supported anymore (NT4 only)!\n");
480 return STATUS_NOT_IMPLEMENTED
;
486 NtSetHighWaitLowThread(
490 DPRINT1("NtSetHighWaitLowThread() not supported anymore (NT4 only)!\n");
491 return STATUS_NOT_IMPLEMENTED
;
494 #endif /* _ENABLE_THRDEVTPAIR */