bc6693e1bcf3b989e86084fac769bc1e642324a5
[reactos.git] / reactos / ntoskrnl / ex / evtpair.c
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 *
7 * PROGRAMMERS: Alex Ionescu (Commented, reorganized, removed Thread Pair, used
8 * KeInitializeEventPair, added SEH)
9 * David Welch (welch@mcmail.com)
10 * Skywing (skywing@valhallalegends.com)
11 */
12
13 /* INCLUDES *****************************************************************/
14
15 #include <ntoskrnl.h>
16 #define NDEBUG
17 #include <internal/debug.h>
18
19 #if defined (ALLOC_PRAGMA)
20 #pragma alloc_text(INIT, ExpInitializeEventPairImplementation)
21 #endif
22
23 /* GLOBALS *******************************************************************/
24
25 POBJECT_TYPE ExEventPairObjectType = NULL;
26
27 static GENERIC_MAPPING ExEventPairMapping = {
28 STANDARD_RIGHTS_READ,
29 STANDARD_RIGHTS_WRITE,
30 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
31 EVENT_PAIR_ALL_ACCESS};
32
33
34 /* FUNCTIONS *****************************************************************/
35
36 VOID
37 INIT_FUNCTION
38 STDCALL
39 ExpInitializeEventPairImplementation(VOID)
40 {
41 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
42 UNICODE_STRING Name;
43
44 DPRINT("Creating Event Pair Object Type\n");
45
46 /* Create the Event Pair Object Type */
47 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
48 RtlInitUnicodeString(&Name, L"EventPair");
49 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
50 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT_PAIR);
51 ObjectTypeInitializer.GenericMapping = ExEventPairMapping;
52 ObjectTypeInitializer.PoolType = NonPagedPool;
53 ObjectTypeInitializer.ValidAccessMask = EVENT_PAIR_ALL_ACCESS;
54 ObjectTypeInitializer.UseDefaultObject = TRUE;
55 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExEventPairObjectType);
56 }
57
58 NTSTATUS
59 STDCALL
60 NtCreateEventPair(OUT PHANDLE EventPairHandle,
61 IN ACCESS_MASK DesiredAccess,
62 IN POBJECT_ATTRIBUTES ObjectAttributes)
63 {
64 PKEVENT_PAIR EventPair;
65 HANDLE hEventPair;
66 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
67 NTSTATUS Status = STATUS_SUCCESS;
68
69 PAGED_CODE();
70 DPRINT("NtCreateEventPair: 0x%p\n", EventPairHandle);
71
72 /* Check Output Safety */
73 if(PreviousMode != KernelMode) {
74
75 _SEH_TRY {
76
77 ProbeForWriteHandle(EventPairHandle);
78 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
79
80 Status = _SEH_GetExceptionCode();
81
82 } _SEH_END;
83
84 if(!NT_SUCCESS(Status)) return Status;
85 }
86
87 /* Create the Object */
88 DPRINT("Creating EventPair\n");
89 Status = ObCreateObject(PreviousMode,
90 ExEventPairObjectType,
91 ObjectAttributes,
92 PreviousMode,
93 NULL,
94 sizeof(KEVENT_PAIR),
95 0,
96 0,
97 (PVOID*)&EventPair);
98
99 /* Check for Success */
100 if(NT_SUCCESS(Status)) {
101
102 /* Initalize the Event */
103 DPRINT("Initializing EventPair\n");
104 KeInitializeEventPair(EventPair);
105
106 /* Insert it */
107 Status = ObInsertObject((PVOID)EventPair,
108 NULL,
109 DesiredAccess,
110 0,
111 NULL,
112 &hEventPair);
113 ObDereferenceObject(EventPair);
114
115 /* Check for success and return handle */
116 if(NT_SUCCESS(Status)) {
117
118 _SEH_TRY {
119
120 *EventPairHandle = hEventPair;
121
122 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
123
124 Status = _SEH_GetExceptionCode();
125
126 } _SEH_END;
127 }
128 }
129
130 /* Return Status */
131 return Status;
132 }
133
134 NTSTATUS
135 STDCALL
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 = STATUS_SUCCESS;
143
144 PAGED_CODE();
145
146 /* Check Output Safety */
147 if(PreviousMode != KernelMode) {
148
149 _SEH_TRY {
150
151 ProbeForWriteHandle(EventPairHandle);
152 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
153
154 Status = _SEH_GetExceptionCode();
155
156 } _SEH_END;
157
158 if(!NT_SUCCESS(Status)) return Status;
159 }
160
161 /* Open the Object */
162 Status = ObOpenObjectByName(ObjectAttributes,
163 ExEventPairObjectType,
164 NULL,
165 PreviousMode,
166 DesiredAccess,
167 NULL,
168 &hEventPair);
169
170 /* Check for success and return handle */
171 if(NT_SUCCESS(Status)) {
172
173 _SEH_TRY {
174
175 *EventPairHandle = hEventPair;
176
177 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
178
179 Status = _SEH_GetExceptionCode();
180
181 } _SEH_END;
182 }
183
184 /* Return status */
185 return Status;
186 }
187
188
189 NTSTATUS
190 STDCALL
191 NtSetHighEventPair(IN HANDLE EventPairHandle)
192 {
193 PKEVENT_PAIR EventPair;
194 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
195 NTSTATUS Status;
196
197 PAGED_CODE();
198 DPRINT("NtSetHighEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
199
200 /* Open the Object */
201 Status = ObReferenceObjectByHandle(EventPairHandle,
202 SYNCHRONIZE,
203 ExEventPairObjectType,
204 PreviousMode,
205 (PVOID*)&EventPair,
206 NULL);
207
208 /* Check for Success */
209 if(NT_SUCCESS(Status)) {
210
211 /* Set the Event */
212 KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
213
214 /* Dereference Object */
215 ObDereferenceObject(EventPair);
216 }
217
218 /* Return status */
219 return Status;
220 }
221
222 NTSTATUS
223 STDCALL
224 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
225 {
226 PKEVENT_PAIR EventPair;
227 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
228 NTSTATUS Status;
229
230 PAGED_CODE();
231 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
232
233 /* Open the Object */
234 Status = ObReferenceObjectByHandle(EventPairHandle,
235 SYNCHRONIZE,
236 ExEventPairObjectType,
237 PreviousMode,
238 (PVOID*)&EventPair,
239 NULL);
240
241 /* Check for Success */
242 if(NT_SUCCESS(Status)) {
243
244 /* Set the Event */
245 KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
246
247 /* Wait for the Other one */
248 KeWaitForSingleObject(&EventPair->LowEvent,
249 WrEventPair,
250 PreviousMode,
251 FALSE,
252 NULL);
253
254 /* Dereference Object */
255 ObDereferenceObject(EventPair);
256 }
257
258 /* Return status */
259 return Status;
260 }
261
262 NTSTATUS
263 STDCALL
264 NtSetLowEventPair(IN HANDLE EventPairHandle)
265 {
266 PKEVENT_PAIR EventPair;
267 KPROCESSOR_MODE PreviousMode;
268 NTSTATUS Status;
269
270 PAGED_CODE();
271
272 PreviousMode = ExGetPreviousMode();
273
274 DPRINT1("NtSetHighEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
275
276 /* Open the Object */
277 Status = ObReferenceObjectByHandle(EventPairHandle,
278 SYNCHRONIZE,
279 ExEventPairObjectType,
280 PreviousMode,
281 (PVOID*)&EventPair,
282 NULL);
283
284 /* Check for Success */
285 if(NT_SUCCESS(Status)) {
286
287 /* Set the Event */
288 KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
289
290 /* Dereference Object */
291 ObDereferenceObject(EventPair);
292 }
293
294 /* Return status */
295 return Status;
296 }
297
298
299 NTSTATUS STDCALL
300 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
301 {
302 PKEVENT_PAIR EventPair;
303 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
304 NTSTATUS Status;
305
306 PAGED_CODE();
307 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle 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 STDCALL
341 NtWaitLowEventPair(IN HANDLE EventPairHandle)
342 {
343 PKEVENT_PAIR EventPair;
344 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
345 NTSTATUS Status;
346
347 PAGED_CODE();
348 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
349
350 /* Open the Object */
351 Status = ObReferenceObjectByHandle(EventPairHandle,
352 SYNCHRONIZE,
353 ExEventPairObjectType,
354 PreviousMode,
355 (PVOID*)&EventPair,
356 NULL);
357
358 /* Check for Success */
359 if(NT_SUCCESS(Status)) {
360
361 /* Wait for the Event */
362 KeWaitForSingleObject(&EventPair->LowEvent,
363 WrEventPair,
364 PreviousMode,
365 FALSE,
366 NULL);
367
368 /* Dereference Object */
369 ObDereferenceObject(EventPair);
370 }
371
372 /* Return status */
373 return Status;
374 }
375
376 NTSTATUS
377 STDCALL
378 NtWaitHighEventPair(IN HANDLE EventPairHandle)
379 {
380 PKEVENT_PAIR EventPair;
381 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
382 NTSTATUS Status;
383
384 PAGED_CODE();
385 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
386
387 /* Open the Object */
388 Status = ObReferenceObjectByHandle(EventPairHandle,
389 SYNCHRONIZE,
390 ExEventPairObjectType,
391 PreviousMode,
392 (PVOID*)&EventPair,
393 NULL);
394
395 /* Check for Success */
396 if(NT_SUCCESS(Status)) {
397
398 /* Wait for the Event */
399 KeWaitForSingleObject(&EventPair->HighEvent,
400 WrEventPair,
401 PreviousMode,
402 FALSE,
403 NULL);
404
405 /* Dereference Object */
406 ObDereferenceObject(EventPair);
407 }
408
409 /* Return status */
410 return Status;
411 }
412
413 /* EOF */