Continue of MSVC-compiling changes....
[reactos.git] / reactos / ntoskrnl / nt / evtpair.c
1 /* $Id: evtpair.c,v 1.20 2003/12/30 18:52:05 fireball Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/nt/evtpair.c
6 * PURPOSE: Support for event pairs
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 * Updated 09/08/2003 by Skywing (skywing@valhallalegends.com)
11 * to correctly maintain ownership of the dispatcher lock
12 * between KeSetEvent and KeWaitForSingleObject calls.
13 * Additionally, implemented the thread-eventpair routines.
14 */
15
16 /* INCLUDES *****************************************************************/
17
18 #define NTOS_MODE_KERNEL
19 #include <ntos.h>
20 #include <ntos/synch.h>
21 #include <internal/ob.h>
22 #include <internal/ps.h>
23 #include <limits.h>
24
25 #define NDEBUG
26 #include <internal/debug.h>
27
28 #ifndef NTSYSAPI
29 #define NTSYSAPI
30 #endif
31
32 #ifndef NTAPI
33 #define NTAPI STDCALL
34 #endif
35
36
37 /* GLOBALS *******************************************************************/
38
39 POBJECT_TYPE EXPORTED ExEventPairObjectType = NULL;
40
41 static GENERIC_MAPPING ExEventPairMapping = {
42 STANDARD_RIGHTS_READ,
43 STANDARD_RIGHTS_WRITE,
44 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE,
45 EVENT_PAIR_ALL_ACCESS};
46
47 static KSPIN_LOCK ExThreadEventPairSpinLock;
48
49 /* FUNCTIONS *****************************************************************/
50
51 NTSTATUS STDCALL
52 NtpCreateEventPair(PVOID ObjectBody,
53 PVOID Parent,
54 PWSTR RemainingPath,
55 POBJECT_ATTRIBUTES ObjectAttributes)
56 {
57 DPRINT("NtpCreateEventPair(ObjectBody %x, Parent %x, RemainingPath %S)\n",
58 ObjectBody, Parent, RemainingPath);
59
60 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
61 {
62 return(STATUS_UNSUCCESSFUL);
63 }
64
65 return(STATUS_SUCCESS);
66 }
67
68 VOID INIT_FUNCTION
69 NtInitializeEventPairImplementation(VOID)
70 {
71 ExEventPairObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
72
73 RtlCreateUnicodeString(&ExEventPairObjectType->TypeName, L"EventPair");
74
75 ExEventPairObjectType->MaxObjects = ULONG_MAX;
76 ExEventPairObjectType->MaxHandles = ULONG_MAX;
77 ExEventPairObjectType->TotalObjects = 0;
78 ExEventPairObjectType->TotalHandles = 0;
79 ExEventPairObjectType->PagedPoolCharge = 0;
80 ExEventPairObjectType->NonpagedPoolCharge = sizeof(KEVENT_PAIR);
81 ExEventPairObjectType->Mapping = &ExEventPairMapping;
82 ExEventPairObjectType->Dump = NULL;
83 ExEventPairObjectType->Open = NULL;
84 ExEventPairObjectType->Close = NULL;
85 ExEventPairObjectType->Delete = NULL;
86 ExEventPairObjectType->Parse = NULL;
87 ExEventPairObjectType->Security = NULL;
88 ExEventPairObjectType->QueryName = NULL;
89 ExEventPairObjectType->OkayToClose = NULL;
90 ExEventPairObjectType->Create = NtpCreateEventPair;
91 ExEventPairObjectType->DuplicationNotify = NULL;
92
93 KeInitializeSpinLock(&ExThreadEventPairSpinLock);
94 ObpCreateTypeObject(ExEventPairObjectType);
95 }
96
97
98 NTSTATUS STDCALL
99 NtCreateEventPair(OUT PHANDLE EventPairHandle,
100 IN ACCESS_MASK DesiredAccess,
101 IN POBJECT_ATTRIBUTES ObjectAttributes)
102 {
103 PKEVENT_PAIR EventPair;
104 NTSTATUS Status;
105
106 DPRINT("NtCreateEventPair()\n");
107 Status = ObCreateObject(ExGetPreviousMode(),
108 ExEventPairObjectType,
109 ObjectAttributes,
110 ExGetPreviousMode(),
111 NULL,
112 sizeof(KEVENT_PAIR),
113 0,
114 0,
115 (PVOID*)&EventPair);
116 if (!NT_SUCCESS(Status))
117 {
118 return(Status);
119 }
120
121 KeInitializeEvent(&EventPair->LowEvent,
122 SynchronizationEvent,
123 FALSE);
124 KeInitializeEvent(&EventPair->HighEvent,
125 SynchronizationEvent,
126 FALSE);
127
128 Status = ObInsertObject ((PVOID)EventPair,
129 NULL,
130 DesiredAccess,
131 0,
132 NULL,
133 EventPairHandle);
134
135 ObDereferenceObject(EventPair);
136
137 return Status;
138 }
139
140
141 NTSTATUS STDCALL
142 NtOpenEventPair(OUT PHANDLE EventPairHandle,
143 IN ACCESS_MASK DesiredAccess,
144 IN POBJECT_ATTRIBUTES ObjectAttributes)
145 {
146 NTSTATUS Status;
147
148 DPRINT("NtOpenEventPair()\n");
149
150 Status = ObOpenObjectByName(ObjectAttributes,
151 ExEventPairObjectType,
152 NULL,
153 UserMode,
154 DesiredAccess,
155 NULL,
156 EventPairHandle);
157
158 return Status;
159 }
160
161
162 NTSTATUS STDCALL
163 NtSetHighEventPair(IN HANDLE EventPairHandle)
164 {
165 PKEVENT_PAIR EventPair;
166 NTSTATUS Status;
167
168 DPRINT("NtSetHighEventPair(EventPairHandle %x)\n",
169 EventPairHandle);
170
171 Status = ObReferenceObjectByHandle(EventPairHandle,
172 EVENT_PAIR_ALL_ACCESS,
173 ExEventPairObjectType,
174 UserMode,
175 (PVOID*)&EventPair,
176 NULL);
177 if (!NT_SUCCESS(Status))
178 return(Status);
179
180 KeSetEvent(&EventPair->HighEvent,
181 EVENT_INCREMENT,
182 FALSE);
183
184 ObDereferenceObject(EventPair);
185 return(STATUS_SUCCESS);
186 }
187
188
189 NTSTATUS STDCALL
190 NtSetHighWaitLowEventPair(IN HANDLE EventPairHandle)
191 {
192 PKEVENT_PAIR EventPair;
193 NTSTATUS Status;
194
195 DPRINT("NtSetHighWaitLowEventPair(EventPairHandle %x)\n",
196 EventPairHandle);
197
198 Status = ObReferenceObjectByHandle(EventPairHandle,
199 EVENT_PAIR_ALL_ACCESS,
200 ExEventPairObjectType,
201 UserMode,
202 (PVOID*)&EventPair,
203 NULL);
204 if (!NT_SUCCESS(Status))
205 return(Status);
206
207 KeSetEvent(&EventPair->HighEvent,
208 EVENT_INCREMENT,
209 TRUE);
210
211 KeWaitForSingleObject(&EventPair->LowEvent,
212 WrEventPair,
213 UserMode,
214 FALSE,
215 NULL);
216
217 ObDereferenceObject(EventPair);
218 return(STATUS_SUCCESS);
219 }
220
221
222 NTSTATUS STDCALL
223 NtSetLowEventPair(IN HANDLE EventPairHandle)
224 {
225 PKEVENT_PAIR EventPair;
226 NTSTATUS Status;
227
228 DPRINT("NtSetLowEventPair(EventPairHandle %x)\n",
229 EventPairHandle);
230
231 Status = ObReferenceObjectByHandle(EventPairHandle,
232 EVENT_PAIR_ALL_ACCESS,
233 ExEventPairObjectType,
234 UserMode,
235 (PVOID*)&EventPair,
236 NULL);
237 if (!NT_SUCCESS(Status))
238 return(Status);
239
240 KeSetEvent(&EventPair->LowEvent,
241 EVENT_INCREMENT,
242 FALSE);
243
244 ObDereferenceObject(EventPair);
245 return(STATUS_SUCCESS);
246 }
247
248
249 NTSTATUS STDCALL
250 NtSetLowWaitHighEventPair(IN HANDLE EventPairHandle)
251 {
252 PKEVENT_PAIR EventPair;
253 NTSTATUS Status;
254
255 DPRINT("NtSetLowWaitHighEventPair(EventPairHandle %x)\n",
256 EventPairHandle);
257
258 Status = ObReferenceObjectByHandle(EventPairHandle,
259 EVENT_PAIR_ALL_ACCESS,
260 ExEventPairObjectType,
261 UserMode,
262 (PVOID*)&EventPair,
263 NULL);
264 if (!NT_SUCCESS(Status))
265 return(Status);
266
267 KeSetEvent(&EventPair->LowEvent,
268 EVENT_INCREMENT,
269 TRUE);
270
271 KeWaitForSingleObject(&EventPair->HighEvent,
272 WrEventPair,
273 UserMode,
274 FALSE,
275 NULL);
276
277 ObDereferenceObject(EventPair);
278 return(STATUS_SUCCESS);
279 }
280
281
282 NTSTATUS STDCALL
283 NtWaitLowEventPair(IN HANDLE EventPairHandle)
284 {
285 PKEVENT_PAIR EventPair;
286 NTSTATUS Status;
287
288 DPRINT("NtWaitLowEventPair(EventPairHandle %x)\n",
289 EventPairHandle);
290
291 Status = ObReferenceObjectByHandle(EventPairHandle,
292 EVENT_PAIR_ALL_ACCESS,
293 ExEventPairObjectType,
294 UserMode,
295 (PVOID*)&EventPair,
296 NULL);
297 if (!NT_SUCCESS(Status))
298 return(Status);
299
300 KeWaitForSingleObject(&EventPair->LowEvent,
301 WrEventPair,
302 UserMode,
303 FALSE,
304 NULL);
305
306 ObDereferenceObject(EventPair);
307 return(STATUS_SUCCESS);
308 }
309
310
311 NTSTATUS STDCALL
312 NtWaitHighEventPair(IN HANDLE EventPairHandle)
313 {
314 PKEVENT_PAIR EventPair;
315 NTSTATUS Status;
316
317 DPRINT("NtWaitHighEventPair(EventPairHandle %x)\n",
318 EventPairHandle);
319
320 Status = ObReferenceObjectByHandle(EventPairHandle,
321 EVENT_PAIR_ALL_ACCESS,
322 ExEventPairObjectType,
323 UserMode,
324 (PVOID*)&EventPair,
325 NULL);
326 if (!NT_SUCCESS(Status))
327 return(Status);
328
329 KeWaitForSingleObject(&EventPair->HighEvent,
330 WrEventPair,
331 UserMode,
332 FALSE,
333 NULL);
334
335 ObDereferenceObject(EventPair);
336 return(STATUS_SUCCESS);
337 }
338
339 /*
340 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
341 * Note that the eventpair spinlock must be acquired when setting the thread
342 * eventpair via NtSetInformationThread.
343 * @implemented
344 */
345 NTSTATUS
346 NTSYSAPI
347 NTAPI
348 NtSetLowWaitHighThread(
349 VOID
350 )
351 {
352 PETHREAD Thread;
353 PKEVENT_PAIR EventPair;
354 NTSTATUS Status;
355 KIRQL Irql;
356
357 Thread = PsGetCurrentThread();
358
359 if(!Thread->EventPair)
360 return STATUS_NO_EVENT_PAIR;
361
362 KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
363
364 EventPair = Thread->EventPair;
365
366 if(EventPair)
367 ObReferenceObjectByPointer(EventPair,
368 EVENT_PAIR_ALL_ACCESS,
369 ExEventPairObjectType,
370 UserMode);
371
372 KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
373
374 if(EventPair == NULL)
375 return STATUS_NO_EVENT_PAIR;
376
377 KeSetEvent(&EventPair->LowEvent,
378 EVENT_INCREMENT,
379 TRUE);
380
381 Status = KeWaitForSingleObject(&EventPair->HighEvent,
382 WrEventPair,
383 UserMode,
384 FALSE,
385 NULL);
386
387 ObDereferenceObject(EventPair);
388
389 return Status;
390 }
391
392
393 /*
394 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
395 * Note that the eventpair spinlock must be acquired when setting the thread
396 * eventpair via NtSetInformationThread.
397 * @implemented
398 */
399 NTSTATUS
400 NTSYSAPI
401 NTAPI
402 NtSetHighWaitLowThread(
403 VOID
404 )
405 {
406 PETHREAD Thread;
407 PKEVENT_PAIR EventPair;
408 NTSTATUS Status;
409 KIRQL Irql;
410
411 Thread = PsGetCurrentThread();
412
413 if(!Thread->EventPair)
414 return STATUS_NO_EVENT_PAIR;
415
416 KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
417
418 EventPair = PsGetCurrentThread()->EventPair;
419
420 if(EventPair)
421 ObReferenceObjectByPointer(EventPair,
422 EVENT_PAIR_ALL_ACCESS,
423 ExEventPairObjectType,
424 UserMode);
425
426 KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
427
428 if(EventPair == NULL)
429 return STATUS_NO_EVENT_PAIR;
430
431 KeSetEvent(&EventPair->HighEvent,
432 EVENT_INCREMENT,
433 TRUE);
434
435 Status = KeWaitForSingleObject(&EventPair->LowEvent,
436 WrEventPair,
437 UserMode,
438 FALSE,
439 NULL);
440
441 ObDereferenceObject(EventPair);
442
443 return Status;
444 }
445
446 /*
447 * Author: Skywing (skywing@valhallalegends.com), 09/08/2003
448 * Note that the eventpair spinlock must be acquired when waiting on the
449 * eventpair via NtSetLow/HighWaitHigh/LowThread. Additionally, when
450 * deleting a thread object, NtpSwapThreadEventPair(Thread, NULL) should
451 * be called to release any preexisting eventpair object associated with
452 * the thread. The Microsoft name for this function is not known.
453 */
454 VOID
455 ExpSwapThreadEventPair(
456 IN PETHREAD Thread,
457 IN PKEVENT_PAIR EventPair
458 )
459 {
460 PKEVENT_PAIR OriginalEventPair;
461 KIRQL Irql;
462
463 KeAcquireSpinLock(&ExThreadEventPairSpinLock, &Irql);
464
465 OriginalEventPair = Thread->EventPair;
466 Thread->EventPair = EventPair;
467
468 if(OriginalEventPair)
469 ObDereferenceObject(OriginalEventPair);
470
471 KeReleaseSpinLock(&ExThreadEventPairSpinLock, Irql);
472 }
473
474 /* EOF */