xref: /reactos/ntoskrnl/ex/evtpair.c (revision cc7cf826)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel
4  * FILE:            ntoskrnl/ex/evtpair.c
5  * PURPOSE:         Support for event pairs
6  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
7  *                  Thomas Weidenmueller
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, ExpInitializeEventPairImplementation)
18 #endif
19 
20 /* GLOBALS *******************************************************************/
21 
22 POBJECT_TYPE ExEventPairObjectType = NULL;
23 
24 GENERIC_MAPPING ExEventPairMapping =
25 {
26     STANDARD_RIGHTS_READ | SYNCHRONIZE,
27     STANDARD_RIGHTS_WRITE | SYNCHRONIZE,
28     STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
29     EVENT_PAIR_ALL_ACCESS
30 };
31 
32 /* FUNCTIONS *****************************************************************/
33 
34 INIT_FUNCTION
35 BOOLEAN
36 NTAPI
37 ExpInitializeEventPairImplementation(VOID)
38 {
39     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
40     UNICODE_STRING Name;
41     NTSTATUS Status;
42     DPRINT("Creating Event Pair Object Type\n");
43 
44     /* Create the Event Pair Object Type */
45     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
46     RtlInitUnicodeString(&Name, L"EventPair");
47     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
48     ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT_PAIR);
49     ObjectTypeInitializer.GenericMapping = ExEventPairMapping;
50     ObjectTypeInitializer.PoolType = NonPagedPool;
51     ObjectTypeInitializer.ValidAccessMask = EVENT_PAIR_ALL_ACCESS;
52     ObjectTypeInitializer.UseDefaultObject = TRUE;
53     ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
54     Status = ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ExEventPairObjectType);
55     if (!NT_SUCCESS(Status)) return FALSE;
56     return TRUE;
57 }
58 
59 NTSTATUS
60 NTAPI
61 NtCreateEventPair(OUT PHANDLE EventPairHandle,
62                   IN ACCESS_MASK DesiredAccess,
63                   IN POBJECT_ATTRIBUTES ObjectAttributes)
64 {
65     PKEVENT_PAIR EventPair;
66     HANDLE hEventPair;
67     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
68     NTSTATUS Status;
69     PAGED_CODE();
70     DPRINT("NtCreateEventPair: 0x%p\n", EventPairHandle);
71 
72     /* Check if we were called from user-mode */
73     if (PreviousMode != KernelMode)
74     {
75         /* Enter SEH Block */
76         _SEH2_TRY
77         {
78             /* Check handle pointer */
79             ProbeForWriteHandle(EventPairHandle);
80         }
81         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
82         {
83             /* Return the exception code */
84             _SEH2_YIELD(return _SEH2_GetExceptionCode());
85         }
86         _SEH2_END;
87     }
88 
89     /* Create the Object */
90     DPRINT("Creating EventPair\n");
91     Status = ObCreateObject(PreviousMode,
92                             ExEventPairObjectType,
93                             ObjectAttributes,
94                             PreviousMode,
95                             NULL,
96                             sizeof(KEVENT_PAIR),
97                             0,
98                             0,
99                             (PVOID*)&EventPair);
100 
101     /* Check for Success */
102     if (NT_SUCCESS(Status))
103     {
104         /* Initialize the Event */
105         DPRINT("Initializing EventPair\n");
106         KeInitializeEventPair(EventPair);
107 
108         /* Insert it */
109         Status = ObInsertObject((PVOID)EventPair,
110                                  NULL,
111                                  DesiredAccess,
112                                  0,
113                                  NULL,
114                                  &hEventPair);
115 
116         /* Check for success */
117         if (NT_SUCCESS(Status))
118         {
119             /* Enter SEH */
120             _SEH2_TRY
121             {
122                 /* Return the handle */
123                 *EventPairHandle = hEventPair;
124             }
125             _SEH2_EXCEPT(ExSystemExceptionFilter())
126             {
127                 /* Get the exception code */
128                 Status = _SEH2_GetExceptionCode();
129             }
130             _SEH2_END;
131         }
132     }
133 
134     /* Return Status */
135     return Status;
136 }
137 
138 NTSTATUS
139 NTAPI
140 NtOpenEventPair(OUT PHANDLE EventPairHandle,
141                 IN ACCESS_MASK DesiredAccess,
142                 IN POBJECT_ATTRIBUTES ObjectAttributes)
143 {
144     HANDLE hEventPair;
145     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
146     NTSTATUS Status;
147     PAGED_CODE();
148 
149     /* Check if we were called from user-mode */
150     if (PreviousMode != KernelMode)
151     {
152         /* Enter SEH Block */
153         _SEH2_TRY
154         {
155             /* Check handle pointer */
156             ProbeForWriteHandle(EventPairHandle);
157         }
158         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
159         {
160             /* Return the exception code */
161             _SEH2_YIELD(return _SEH2_GetExceptionCode());
162         }
163         _SEH2_END;
164     }
165 
166     /* Open the Object */
167     Status = ObOpenObjectByName(ObjectAttributes,
168                                 ExEventPairObjectType,
169                                 PreviousMode,
170                                 NULL,
171                                 DesiredAccess,
172                                 NULL,
173                                 &hEventPair);
174 
175     /* Check for success */
176     if (NT_SUCCESS(Status))
177     {
178         /* Enter SEH */
179         _SEH2_TRY
180         {
181             /* Return the handle */
182             *EventPairHandle = hEventPair;
183         }
184         _SEH2_EXCEPT(ExSystemExceptionFilter())
185         {
186             /* Get the exception code */
187             Status = _SEH2_GetExceptionCode();
188         }
189         _SEH2_END;
190     }
191 
192     /* Return status */
193     return Status;
194 }
195 
196 NTSTATUS
197 NTAPI
198 NtSetHighEventPair(IN HANDLE EventPairHandle)
199 {
200     PKEVENT_PAIR EventPair;
201     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
202     NTSTATUS Status;
203     PAGED_CODE();
204     DPRINT("NtSetHighEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
205 
206     /* Open the Object */
207     Status = ObReferenceObjectByHandle(EventPairHandle,
208                                        SYNCHRONIZE,
209                                        ExEventPairObjectType,
210                                        PreviousMode,
211                                        (PVOID*)&EventPair,
212                                        NULL);
213 
214     /* Check for Success */
215     if(NT_SUCCESS(Status))
216     {
217         /* Set the Event */
218         KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
219 
220         /* Dereference Object */
221         ObDereferenceObject(EventPair);
222     }
223 
224     /* Return status */
225     return Status;
226 }
227 
228 NTSTATUS
229 NTAPI
230 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
231 {
232     PKEVENT_PAIR EventPair;
233     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
234     NTSTATUS Status;
235     PAGED_CODE();
236     DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
237 
238     /* Open the Object */
239     Status = ObReferenceObjectByHandle(EventPairHandle,
240                                        SYNCHRONIZE,
241                                        ExEventPairObjectType,
242                                        PreviousMode,
243                                        (PVOID*)&EventPair,
244                                        NULL);
245 
246     /* Check for Success */
247     if(NT_SUCCESS(Status))
248     {
249         /* Set the Event */
250         KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
251 
252         /* Wait for the Other one */
253         KeWaitForSingleObject(&EventPair->LowEvent,
254                               WrEventPair,
255                               PreviousMode,
256                               FALSE,
257                               NULL);
258 
259         /* Dereference Object */
260         ObDereferenceObject(EventPair);
261     }
262 
263     /* Return status */
264     return Status;
265 }
266 
267 NTSTATUS
268 NTAPI
269 NtSetLowEventPair(IN HANDLE EventPairHandle)
270 {
271     PKEVENT_PAIR EventPair;
272     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
273     NTSTATUS Status;
274     PAGED_CODE();
275     DPRINT1("NtSetHighEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
276 
277     /* Open the Object */
278     Status = ObReferenceObjectByHandle(EventPairHandle,
279                                        SYNCHRONIZE,
280                                        ExEventPairObjectType,
281                                        PreviousMode,
282                                        (PVOID*)&EventPair,
283                                        NULL);
284 
285     /* Check for Success */
286     if(NT_SUCCESS(Status))
287     {
288         /* Set the Event */
289         KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
290 
291         /* Dereference Object */
292         ObDereferenceObject(EventPair);
293     }
294 
295     /* Return status */
296     return Status;
297 }
298 
299 NTSTATUS
300 NTAPI
301 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
302 {
303     PKEVENT_PAIR EventPair;
304     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
305     NTSTATUS Status;
306     PAGED_CODE();
307     DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
308 
309     /* Open the Object */
310     Status = ObReferenceObjectByHandle(EventPairHandle,
311                                        SYNCHRONIZE,
312                                        ExEventPairObjectType,
313                                        PreviousMode,
314                                        (PVOID*)&EventPair,
315                                        NULL);
316 
317     /* Check for Success */
318     if(NT_SUCCESS(Status))
319     {
320         /* Set the Event */
321         KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
322 
323         /* Wait for the Other one */
324         KeWaitForSingleObject(&EventPair->HighEvent,
325                               WrEventPair,
326                               PreviousMode,
327                               FALSE,
328                               NULL);
329 
330         /* Dereference Object */
331         ObDereferenceObject(EventPair);
332     }
333 
334     /* Return status */
335     return Status;
336 }
337 
338 
339 NTSTATUS
340 NTAPI
341 NtWaitLowEventPair(IN HANDLE EventPairHandle)
342 {
343     PKEVENT_PAIR EventPair;
344     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
345     NTSTATUS Status;
346     PAGED_CODE();
347     DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
348 
349     /* Open the Object */
350     Status = ObReferenceObjectByHandle(EventPairHandle,
351                                        SYNCHRONIZE,
352                                        ExEventPairObjectType,
353                                        PreviousMode,
354                                        (PVOID*)&EventPair,
355                                        NULL);
356 
357     /* Check for Success */
358     if(NT_SUCCESS(Status))
359     {
360         /* Wait for the Event */
361         KeWaitForSingleObject(&EventPair->LowEvent,
362                               WrEventPair,
363                               PreviousMode,
364                               FALSE,
365                               NULL);
366 
367         /* Dereference Object */
368         ObDereferenceObject(EventPair);
369     }
370 
371     /* Return status */
372     return Status;
373 }
374 
375 NTSTATUS
376 NTAPI
377 NtWaitHighEventPair(IN HANDLE EventPairHandle)
378 {
379     PKEVENT_PAIR EventPair;
380     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
381     NTSTATUS Status;
382 
383     PAGED_CODE();
384     DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
385 
386     /* Open the Object */
387     Status = ObReferenceObjectByHandle(EventPairHandle,
388                                        SYNCHRONIZE,
389                                        ExEventPairObjectType,
390                                        PreviousMode,
391                                        (PVOID*)&EventPair,
392                                        NULL);
393 
394     /* Check for Success */
395     if(NT_SUCCESS(Status))
396     {
397         /* Wait for the Event */
398         KeWaitForSingleObject(&EventPair->HighEvent,
399                               WrEventPair,
400                               PreviousMode,
401                               FALSE,
402                               NULL);
403 
404         /* Dereference Object */
405         ObDereferenceObject(EventPair);
406     }
407 
408     /* Return status */
409     return Status;
410 }
411 
412 /* EOF */
413