[SHELL-EXPERIMENTS]
[reactos.git] / 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 <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 BOOLEAN
35 INIT_FUNCTION
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 */