Removed incorrect Create/DuplicationNotify callbacks and replaced by a more correct...
[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 /* GLOBALS *******************************************************************/
20
21 POBJECT_TYPE EXPORTED ExEventPairObjectType = NULL;
22
23 static GENERIC_MAPPING ExEventPairMapping = {
24 STANDARD_RIGHTS_READ,
25 STANDARD_RIGHTS_WRITE,
26 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
27 EVENT_PAIR_ALL_ACCESS};
28
29
30 /* FUNCTIONS *****************************************************************/
31
32 VOID
33 INIT_FUNCTION
34 ExpInitializeEventPairImplementation(VOID)
35 {
36 /* Create the Event Pair Object Type */
37 ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
38 RtlInitUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair");
39 ExEventPairObjectType->Tag = TAG('E', 'v', 'P', 'a');
40 ExEventPairObjectType->PeakObjects = 0;
41 ExEventPairObjectType->PeakHandles = 0;
42 ExEventPairObjectType->TotalObjects = 0;
43 ExEventPairObjectType->TotalHandles = 0;
44 ExEventPairObjectType->PagedPoolCharge = 0;
45 ExEventPairObjectType->NonpagedPoolCharge = sizeof(KEVENT_PAIR);
46 ExEventPairObjectType->Mapping = &ExEventPairMapping;
47 ExEventPairObjectType->Dump = NULL;
48 ExEventPairObjectType->Open = NULL;
49 ExEventPairObjectType->Close = NULL;
50 ExEventPairObjectType->Delete = NULL;
51 ExEventPairObjectType->Parse = NULL;
52 ExEventPairObjectType->Security = NULL;
53 ExEventPairObjectType->QueryName = NULL;
54 ExEventPairObjectType->OkayToClose = NULL;
55 ObpCreateTypeObject(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: %x\n", EventPairHandle);
71
72 /* Check Output Safety */
73 if(PreviousMode == UserMode) {
74
75 _SEH_TRY {
76
77 ProbeForWrite(EventPairHandle,
78 sizeof(HANDLE),
79 sizeof(ULONG));
80 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
81
82 Status = _SEH_GetExceptionCode();
83
84 } _SEH_END;
85
86 if(!NT_SUCCESS(Status)) return Status;
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 /* Initalize 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 ObDereferenceObject(EventPair);
116
117 /* Check for success and return handle */
118 if(NT_SUCCESS(Status)) {
119
120 _SEH_TRY {
121
122 *EventPairHandle = hEventPair;
123
124 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
125
126 Status = _SEH_GetExceptionCode();
127
128 } _SEH_END;
129 }
130 }
131
132 /* Return Status */
133 return Status;
134 }
135
136 NTSTATUS
137 STDCALL
138 NtOpenEventPair(OUT PHANDLE EventPairHandle,
139 IN ACCESS_MASK DesiredAccess,
140 IN POBJECT_ATTRIBUTES ObjectAttributes)
141 {
142 HANDLE hEventPair;
143 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
144 NTSTATUS Status = STATUS_SUCCESS;
145
146 PAGED_CODE();
147
148 /* Check Output Safety */
149 if(PreviousMode == UserMode) {
150
151 _SEH_TRY {
152
153 ProbeForWrite(EventPairHandle,
154 sizeof(HANDLE),
155 sizeof(ULONG));
156 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
157
158 Status = _SEH_GetExceptionCode();
159
160 } _SEH_END;
161
162 if(!NT_SUCCESS(Status)) return Status;
163 }
164
165 /* Open the Object */
166 Status = ObOpenObjectByName(ObjectAttributes,
167 ExEventPairObjectType,
168 NULL,
169 PreviousMode,
170 DesiredAccess,
171 NULL,
172 &hEventPair);
173
174 /* Check for success and return handle */
175 if(NT_SUCCESS(Status)) {
176
177 _SEH_TRY {
178
179 *EventPairHandle = hEventPair;
180
181 } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) {
182
183 Status = _SEH_GetExceptionCode();
184
185 } _SEH_END;
186 }
187
188 /* Return status */
189 return Status;
190 }
191
192
193 NTSTATUS
194 STDCALL
195 NtSetHighEventPair(IN HANDLE EventPairHandle)
196 {
197 PKEVENT_PAIR EventPair;
198 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
199 NTSTATUS Status;
200
201 PAGED_CODE();
202 DPRINT("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
203
204 /* Open the Object */
205 Status = ObReferenceObjectByHandle(EventPairHandle,
206 SYNCHRONIZE,
207 ExEventPairObjectType,
208 PreviousMode,
209 (PVOID*)&EventPair,
210 NULL);
211
212 /* Check for Success */
213 if(NT_SUCCESS(Status)) {
214
215 /* Set the Event */
216 KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
217
218 /* Dereference Object */
219 ObDereferenceObject(EventPair);
220 }
221
222 /* Return status */
223 return Status;
224 }
225
226 NTSTATUS
227 STDCALL
228 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
229 {
230 PKEVENT_PAIR EventPair;
231 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
232 NTSTATUS Status;
233
234 PAGED_CODE();
235 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
236
237 /* Open the Object */
238 Status = ObReferenceObjectByHandle(EventPairHandle,
239 SYNCHRONIZE,
240 ExEventPairObjectType,
241 PreviousMode,
242 (PVOID*)&EventPair,
243 NULL);
244
245 /* Check for Success */
246 if(NT_SUCCESS(Status)) {
247
248 /* Set the Event */
249 KeSetEvent(&EventPair->HighEvent, EVENT_INCREMENT, FALSE);
250
251 /* Wait for the Other one */
252 KeWaitForSingleObject(&EventPair->LowEvent,
253 WrEventPair,
254 PreviousMode,
255 FALSE,
256 NULL);
257
258 /* Dereference Object */
259 ObDereferenceObject(EventPair);
260 }
261
262 /* Return status */
263 return Status;
264 }
265
266 NTSTATUS
267 STDCALL
268 NtSetLowEventPair(IN HANDLE EventPairHandle)
269 {
270 PKEVENT_PAIR EventPair;
271 KPROCESSOR_MODE PreviousMode;
272 NTSTATUS Status;
273
274 PAGED_CODE();
275
276 PreviousMode = ExGetPreviousMode();
277
278 DPRINT1("NtSetHighEventPair(EventPairHandle %x)\n", EventPairHandle);
279
280 /* Open the Object */
281 Status = ObReferenceObjectByHandle(EventPairHandle,
282 SYNCHRONIZE,
283 ExEventPairObjectType,
284 PreviousMode,
285 (PVOID*)&EventPair,
286 NULL);
287
288 /* Check for Success */
289 if(NT_SUCCESS(Status)) {
290
291 /* Set the Event */
292 KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
293
294 /* Dereference Object */
295 ObDereferenceObject(EventPair);
296 }
297
298 /* Return status */
299 return Status;
300 }
301
302
303 NTSTATUS STDCALL
304 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
305 {
306 PKEVENT_PAIR EventPair;
307 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
308 NTSTATUS Status;
309
310 PAGED_CODE();
311 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
312
313 /* Open the Object */
314 Status = ObReferenceObjectByHandle(EventPairHandle,
315 SYNCHRONIZE,
316 ExEventPairObjectType,
317 PreviousMode,
318 (PVOID*)&EventPair,
319 NULL);
320
321 /* Check for Success */
322 if(NT_SUCCESS(Status)) {
323
324 /* Set the Event */
325 KeSetEvent(&EventPair->LowEvent, EVENT_INCREMENT, FALSE);
326
327 /* Wait for the Other one */
328 KeWaitForSingleObject(&EventPair->HighEvent,
329 WrEventPair,
330 PreviousMode,
331 FALSE,
332 NULL);
333
334 /* Dereference Object */
335 ObDereferenceObject(EventPair);
336 }
337
338 /* Return status */
339 return Status;
340 }
341
342
343 NTSTATUS
344 STDCALL
345 NtWaitLowEventPair(IN HANDLE EventPairHandle)
346 {
347 PKEVENT_PAIR EventPair;
348 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
349 NTSTATUS Status;
350
351 PAGED_CODE();
352 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
353
354 /* Open the Object */
355 Status = ObReferenceObjectByHandle(EventPairHandle,
356 SYNCHRONIZE,
357 ExEventPairObjectType,
358 PreviousMode,
359 (PVOID*)&EventPair,
360 NULL);
361
362 /* Check for Success */
363 if(NT_SUCCESS(Status)) {
364
365 /* Wait for the Event */
366 KeWaitForSingleObject(&EventPair->LowEvent,
367 WrEventPair,
368 PreviousMode,
369 FALSE,
370 NULL);
371
372 /* Dereference Object */
373 ObDereferenceObject(EventPair);
374 }
375
376 /* Return status */
377 return Status;
378 }
379
380 NTSTATUS
381 STDCALL
382 NtWaitHighEventPair(IN HANDLE EventPairHandle)
383 {
384 PKEVENT_PAIR EventPair;
385 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
386 NTSTATUS Status;
387
388 PAGED_CODE();
389 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n", EventPairHandle);
390
391 /* Open the Object */
392 Status = ObReferenceObjectByHandle(EventPairHandle,
393 SYNCHRONIZE,
394 ExEventPairObjectType,
395 PreviousMode,
396 (PVOID*)&EventPair,
397 NULL);
398
399 /* Check for Success */
400 if(NT_SUCCESS(Status)) {
401
402 /* Wait for the Event */
403 KeWaitForSingleObject(&EventPair->HighEvent,
404 WrEventPair,
405 PreviousMode,
406 FALSE,
407 NULL);
408
409 /* Dereference Object */
410 ObDereferenceObject(EventPair);
411 }
412
413 /* Return status */
414 return Status;
415 }
416
417 /* EOF */