Merge 25584, 25588.
[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 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &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
114 /* Check for success and return handle */
115 if(NT_SUCCESS(Status))
116 {
117 _SEH_TRY
118 {
119 *EventPairHandle = hEventPair;
120 }
121 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
122 {
123 Status = _SEH_GetExceptionCode();
124 }
125 _SEH_END;
126 }
127 }
128
129 /* Return Status */
130 return Status;
131 }
132
133 NTSTATUS
134 NTAPI
135 NtOpenEventPair(OUT PHANDLE EventPairHandle,
136 IN ACCESS_MASK DesiredAccess,
137 IN POBJECT_ATTRIBUTES ObjectAttributes)
138 {
139 HANDLE hEventPair;
140 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
141 NTSTATUS Status = STATUS_SUCCESS;
142 PAGED_CODE();
143
144 /* Check if we were called from user-mode */
145 if(PreviousMode != KernelMode)
146 {
147 /* Enter SEH Block */
148 _SEH_TRY
149 {
150 /* Check handle pointer */
151 ProbeForWriteHandle(EventPairHandle);
152 }
153 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
154 {
155 Status = _SEH_GetExceptionCode();
156 }
157 _SEH_END;
158
159 /* Bail out if pointer was invalid */
160 if(!NT_SUCCESS(Status)) return Status;
161 }
162
163 /* Open the Object */
164 Status = ObOpenObjectByName(ObjectAttributes,
165 ExEventPairObjectType,
166 PreviousMode,
167 NULL,
168 DesiredAccess,
169 NULL,
170 &hEventPair);
171
172 /* Check for success and return handle */
173 if(NT_SUCCESS(Status))
174 {
175 _SEH_TRY
176 {
177 *EventPairHandle = hEventPair;
178 }
179 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
180 {
181 Status = _SEH_GetExceptionCode();
182 }
183 _SEH_END;
184 }
185
186 /* Return status */
187 return Status;
188 }
189
190 NTSTATUS
191 NTAPI
192 NtSetHighEventPair(IN HANDLE EventPairHandle)
193 {
194 PKEVENT_PAIR EventPair;
195 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
196 NTSTATUS Status;
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 NTAPI
224 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
225 {
226 PKEVENT_PAIR EventPair;
227 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
228 NTSTATUS Status;
229 PAGED_CODE();
230 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
231
232 /* Open the Object */
233 Status = ObReferenceObjectByHandle(EventPairHandle,
234 SYNCHRONIZE,
235 ExEventPairObjectType,
236 PreviousMode,
237 (PVOID*)&EventPair,
238 NULL);
239
240 /* Check for Success */
241 if(NT_SUCCESS(Status))
242 {
243 /* Set the Event */
244 KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
245
246 /* Wait for the Other one */
247 KeWaitForSingleObject(&EventPair->LowEvent,
248 WrEventPair,
249 PreviousMode,
250 FALSE,
251 NULL);
252
253 /* Dereference Object */
254 ObDereferenceObject(EventPair);
255 }
256
257 /* Return status */
258 return Status;
259 }
260
261 NTSTATUS
262 NTAPI
263 NtSetLowEventPair(IN HANDLE EventPairHandle)
264 {
265 PKEVENT_PAIR EventPair;
266 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
267 NTSTATUS Status;
268 PAGED_CODE();
269 DPRINT1("NtSetHighEventPair(EventPairHandle 0x%p)\n", EventPairHandle);
270
271 /* Open the Object */
272 Status = ObReferenceObjectByHandle(EventPairHandle,
273 SYNCHRONIZE,
274 ExEventPairObjectType,
275 PreviousMode,
276 (PVOID*)&EventPair,
277 NULL);
278
279 /* Check for Success */
280 if(NT_SUCCESS(Status))
281 {
282 /* Set the Event */
283 KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
284
285 /* Dereference Object */
286 ObDereferenceObject(EventPair);
287 }
288
289 /* Return status */
290 return Status;
291 }
292
293 NTSTATUS
294 NTAPI
295 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
296 {
297 PKEVENT_PAIR EventPair;
298 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
299 NTSTATUS Status;
300 PAGED_CODE();
301 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
302
303 /* Open the Object */
304 Status = ObReferenceObjectByHandle(EventPairHandle,
305 SYNCHRONIZE,
306 ExEventPairObjectType,
307 PreviousMode,
308 (PVOID*)&EventPair,
309 NULL);
310
311 /* Check for Success */
312 if(NT_SUCCESS(Status))
313 {
314 /* Set the Event */
315 KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
316
317 /* Wait for the Other one */
318 KeWaitForSingleObject(&EventPair->HighEvent,
319 WrEventPair,
320 PreviousMode,
321 FALSE,
322 NULL);
323
324 /* Dereference Object */
325 ObDereferenceObject(EventPair);
326 }
327
328 /* Return status */
329 return Status;
330 }
331
332
333 NTSTATUS
334 NTAPI
335 NtWaitLowEventPair(IN HANDLE EventPairHandle)
336 {
337 PKEVENT_PAIR EventPair;
338 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
339 NTSTATUS Status;
340 PAGED_CODE();
341 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
342
343 /* Open the Object */
344 Status = ObReferenceObjectByHandle(EventPairHandle,
345 SYNCHRONIZE,
346 ExEventPairObjectType,
347 PreviousMode,
348 (PVOID*)&EventPair,
349 NULL);
350
351 /* Check for Success */
352 if(NT_SUCCESS(Status))
353 {
354 /* Wait for the Event */
355 KeWaitForSingleObject(&EventPair->LowEvent,
356 WrEventPair,
357 PreviousMode,
358 FALSE,
359 NULL);
360
361 /* Dereference Object */
362 ObDereferenceObject(EventPair);
363 }
364
365 /* Return status */
366 return Status;
367 }
368
369 NTSTATUS
370 NTAPI
371 NtWaitHighEventPair(IN HANDLE EventPairHandle)
372 {
373 PKEVENT_PAIR EventPair;
374 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
375 NTSTATUS Status;
376
377 PAGED_CODE();
378 DPRINT("NtSetHighWaitLowEventPair(Handle 0x%p)\n", EventPairHandle);
379
380 /* Open the Object */
381 Status = ObReferenceObjectByHandle(EventPairHandle,
382 SYNCHRONIZE,
383 ExEventPairObjectType,
384 PreviousMode,
385 (PVOID*)&EventPair,
386 NULL);
387
388 /* Check for Success */
389 if(NT_SUCCESS(Status))
390 {
391 /* Wait for the Event */
392 KeWaitForSingleObject(&EventPair->HighEvent,
393 WrEventPair,
394 PreviousMode,
395 FALSE,
396 NULL);
397
398 /* Dereference Object */
399 ObDereferenceObject(EventPair);
400 }
401
402 /* Return status */
403 return Status;
404 }
405
406 /* EOF */