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