23786103bfe825170551234a51988d7520bd283d
[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 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 * Thomas Weidenmueller
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/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,
27 STANDARD_RIGHTS_WRITE,
28 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
29 EVENT_PAIR_ALL_ACCESS
30 };
31
32 /* FUNCTIONS *****************************************************************/
33
34 VOID
35 INIT_FUNCTION
36 NTAPI
37 ExpInitializeEventPairImplementation(VOID)
38 {
39 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
40 UNICODE_STRING Name;
41 DPRINT("Creating Event Pair Object Type\n");
42
43 /* Create the Event Pair Object Type */
44 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
45 RtlInitUnicodeString(&Name, L"EventPair");
46 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
47 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KEVENT_PAIR);
48 ObjectTypeInitializer.GenericMapping = ExEventPairMapping;
49 ObjectTypeInitializer.PoolType = NonPagedPool;
50 ObjectTypeInitializer.ValidAccessMask = EVENT_PAIR_ALL_ACCESS;
51 ObjectTypeInitializer.UseDefaultObject = TRUE;
52 ObpCreateTypeObject(&ObjectTypeInitializer, &Name, &ExEventPairObjectType);
53 }
54
55 NTSTATUS
56 NTAPI
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 = STATUS_SUCCESS;
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 _SEH_TRY
73 {
74 /* Check handle pointer */
75 ProbeForWriteHandle(EventPairHandle);
76 }
77 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
78 {
79 Status = _SEH_GetExceptionCode();
80 }
81 _SEH_END;
82
83 /* Bail out if pointer was invalid */
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 NTAPI
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 PAGED_CODE();
144
145 /* Check if we were called from user-mode */
146 if(PreviousMode != KernelMode)
147 {
148 /* Enter SEH Block */
149 _SEH_TRY
150 {
151 /* Check handle pointer */
152 ProbeForWriteHandle(EventPairHandle);
153 }
154 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
155 {
156 Status = _SEH_GetExceptionCode();
157 }
158 _SEH_END;
159
160 /* Bail out if pointer was invalid */
161 if(!NT_SUCCESS(Status)) return Status;
162 }
163
164 /* Open the Object */
165 Status = ObOpenObjectByName(ObjectAttributes,
166 ExEventPairObjectType,
167 NULL,
168 PreviousMode,
169 DesiredAccess,
170 NULL,
171 &hEventPair);
172
173 /* Check for success and return handle */
174 if(NT_SUCCESS(Status))
175 {
176 _SEH_TRY
177 {
178 *EventPairHandle = hEventPair;
179 }
180 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
181 {
182 Status = _SEH_GetExceptionCode();
183 }
184 _SEH_END;
185 }
186
187 /* Return status */
188 return Status;
189 }
190
191 NTSTATUS
192 NTAPI
193 NtSetHighEventPair(IN HANDLE EventPairHandle)
194 {
195 PKEVENT_PAIR EventPair;
196 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
197 NTSTATUS Status;
198 PAGED_CODE();
199 DPRINT("NtSetHighEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
200
201 /* Open the Object */
202 Status = ObReferenceObjectByHandle(EventPairHandle,
203 SYNCHRONIZE,
204 ExEventPairObjectType,
205 PreviousMode,
206 (PVOID*)&EventPair,
207 NULL);
208
209 /* Check for Success */
210 if(NT_SUCCESS(Status))
211 {
212 /* Set the Event */
213 KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
214
215 /* Dereference Object */
216 ObDereferenceObject(EventPair);
217 }
218
219 /* Return status */
220 return Status;
221 }
222
223 NTSTATUS
224 NTAPI
225 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
226 {
227 PKEVENT_PAIR EventPair;
228 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
229 NTSTATUS Status;
230 PAGED_CODE();
231 DPRINT("NtSetHighWaitLowEventPair(Handle 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 NTAPI
264 NtSetLowEventPair(IN HANDLE EventPairHandle)
265 {
266 PKEVENT_PAIR EventPair;
267 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
268 NTSTATUS Status;
269 PAGED_CODE();
270 DPRINT1("NtSetHighEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
271
272 /* Open the Object */
273 Status = ObReferenceObjectByHandle(EventPairHandle,
274 SYNCHRONIZE,
275 ExEventPairObjectType,
276 PreviousMode,
277 (PVOID*)&EventPair,
278 NULL);
279
280 /* Check for Success */
281 if(NT_SUCCESS(Status))
282 {
283 /* Set the Event */
284 KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
285
286 /* Dereference Object */
287 ObDereferenceObject(EventPair);
288 }
289
290 /* Return status */
291 return Status;
292 }
293
294 NTSTATUS
295 NTAPI
296 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
297 {
298 PKEVENT_PAIR EventPair;
299 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
300 NTSTATUS Status;
301 PAGED_CODE();
302 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
303
304 /* Open the Object */
305 Status = ObReferenceObjectByHandle(EventPairHandle,
306 SYNCHRONIZE,
307 ExEventPairObjectType,
308 PreviousMode,
309 (PVOID*)&EventPair,
310 NULL);
311
312 /* Check for Success */
313 if(NT_SUCCESS(Status))
314 {
315 /* Set the Event */
316 KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
317
318 /* Wait for the Other one */
319 KeWaitForSingleObject(&EventPair->HighEvent,
320 WrEventPair,
321 PreviousMode,
322 FALSE,
323 NULL);
324
325 /* Dereference Object */
326 ObDereferenceObject(EventPair);
327 }
328
329 /* Return status */
330 return Status;
331 }
332
333
334 NTSTATUS
335 NTAPI
336 NtWaitLowEventPair(IN HANDLE EventPairHandle)
337 {
338 PKEVENT_PAIR EventPair;
339 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
340 NTSTATUS Status;
341 PAGED_CODE();
342 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
343
344 /* Open the Object */
345 Status = ObReferenceObjectByHandle(EventPairHandle,
346 SYNCHRONIZE,
347 ExEventPairObjectType,
348 PreviousMode,
349 (PVOID*)&EventPair,
350 NULL);
351
352 /* Check for Success */
353 if(NT_SUCCESS(Status))
354 {
355 /* Wait for the Event */
356 KeWaitForSingleObject(&EventPair->LowEvent,
357 WrEventPair,
358 PreviousMode,
359 FALSE,
360 NULL);
361
362 /* Dereference Object */
363 ObDereferenceObject(EventPair);
364 }
365
366 /* Return status */
367 return Status;
368 }
369
370 NTSTATUS
371 NTAPI
372 NtWaitHighEventPair(IN HANDLE EventPairHandle)
373 {
374 PKEVENT_PAIR EventPair;
375 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
376 NTSTATUS Status;
377
378 PAGED_CODE();
379 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
380
381 /* Open the Object */
382 Status = ObReferenceObjectByHandle(EventPairHandle,
383 SYNCHRONIZE,
384 ExEventPairObjectType,
385 PreviousMode,
386 (PVOID*)&EventPair,
387 NULL);
388
389 /* Check for Success */
390 if(NT_SUCCESS(Status))
391 {
392 /* Wait for the Event */
393 KeWaitForSingleObject(&EventPair->HighEvent,
394 WrEventPair,
395 PreviousMode,
396 FALSE,
397 NULL);
398
399 /* Dereference Object */
400 ObDereferenceObject(EventPair);
401 }
402
403 /* Return status */
404 return Status;
405 }
406
407 /* EOF */