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