First patch to fix seriously broken ROS (thank Thomas). Work in progress, will be...
[reactos.git] / reactos / ntoskrnl / ex / event.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/nt/event.c
22 * PURPOSE: Named event support
23 * PROGRAMMER: Philip Susi and David Welch
24 * UPDATE HISTORY:
25 * Created 22/05/98
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ntoskrnl.h>
31 #define NDEBUG
32 #include <internal/debug.h>
33
34 /* GLOBALS *******************************************************************/
35
36 POBJECT_TYPE EXPORTED ExEventObjectType = NULL;
37
38 static GENERIC_MAPPING ExpEventMapping = {
39 STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
40 STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
41 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
42 EVENT_ALL_ACCESS};
43
44
45 /* FUNCTIONS *****************************************************************/
46
47 NTSTATUS STDCALL
48 NtpCreateEvent(PVOID ObjectBody,
49 PVOID Parent,
50 PWSTR RemainingPath,
51 POBJECT_ATTRIBUTES ObjectAttributes)
52 {
53 DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n",
54 ObjectBody, Parent, RemainingPath);
55
56 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
57 {
58 return(STATUS_UNSUCCESSFUL);
59 }
60
61 return(STATUS_SUCCESS);
62 }
63
64
65 VOID INIT_FUNCTION
66 ExpInitializeEventImplementation(VOID)
67 {
68 ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
69
70 RtlCreateUnicodeString(&ExEventObjectType->TypeName, L"Event");
71
72 ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
73 ExEventObjectType->PeakObjects = 0;
74 ExEventObjectType->PeakHandles = 0;
75 ExEventObjectType->TotalObjects = 0;
76 ExEventObjectType->TotalHandles = 0;
77 ExEventObjectType->PagedPoolCharge = 0;
78 ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT);
79 ExEventObjectType->Mapping = &ExpEventMapping;
80 ExEventObjectType->Dump = NULL;
81 ExEventObjectType->Open = NULL;
82 ExEventObjectType->Close = NULL;
83 ExEventObjectType->Delete = NULL;
84 ExEventObjectType->Parse = NULL;
85 ExEventObjectType->Security = NULL;
86 ExEventObjectType->QueryName = NULL;
87 ExEventObjectType->OkayToClose = NULL;
88 ExEventObjectType->Create = NtpCreateEvent;
89 ExEventObjectType->DuplicationNotify = NULL;
90
91 ObpCreateTypeObject(ExEventObjectType);
92 }
93
94
95 NTSTATUS STDCALL
96 NtClearEvent(IN HANDLE EventHandle)
97 {
98 PKEVENT Event;
99 NTSTATUS Status;
100
101 Status = ObReferenceObjectByHandle(EventHandle,
102 EVENT_MODIFY_STATE,
103 ExEventObjectType,
104 UserMode,
105 (PVOID*)&Event,
106 NULL);
107 if (!NT_SUCCESS(Status))
108 {
109 return(Status);
110 }
111 KeClearEvent(Event);
112 ObDereferenceObject(Event);
113 return(STATUS_SUCCESS);
114 }
115
116
117 /*
118 * @implemented
119 */
120 NTSTATUS STDCALL
121 NtCreateEvent(OUT PHANDLE EventHandle,
122 IN ACCESS_MASK DesiredAccess,
123 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
124 IN EVENT_TYPE EventType,
125 IN BOOLEAN InitialState)
126 {
127 /*
128 * @implemented
129 */
130 NTSTATUS STDCALL
131 NtCreateEvent(OUT PHANDLE EventHandle,
132 IN ACCESS_MASK DesiredAccess,
133 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
134 IN EVENT_TYPE EventType,
135 IN BOOLEAN InitialState)
136 {
137 KPROCESSOR_MODE PreviousMode;
138 PKEVENT Event;
139 HANDLE hEvent;
140 NTSTATUS Status = STATUS_SUCCESS;
141
142 PreviousMode = ExGetPreviousMode();
143
144 if(PreviousMode == UserMode)
145 {
146 _SEH_TRY
147 {
148 ProbeForWrite(EventHandle,
149 sizeof(HANDLE),
150 sizeof(ULONG));
151 }
152 _SEH_HANDLE
153 {
154 Status = _SEH_GetExceptionCode();
155 }
156 _SEH_END;
157 }
158
159 Status = ObCreateObject(PreviousMode,
160 ExEventObjectType,
161 ObjectAttributes,
162 PreviousMode,
163 NULL,
164 sizeof(KEVENT),
165 0,
166 0,
167 (PVOID*)&Event);
168 if(NT_SUCCESS(Status))
169 {
170 KeInitializeEvent(Event,
171 EventType,
172 InitialState);
173
174
175 Status = ObInsertObject((PVOID)Event,
176 NULL,
177 DesiredAccess,
178 0,
179 NULL,
180 &hEvent);
181 ObDereferenceObject(Event);
182
183 if(NT_SUCCESS(Status))
184 {
185 _SEH_TRY
186 {
187 *EventHandle = hEvent;
188 }
189 _SEH_HANDLE
190 {
191 Status = _SEH_GetExceptionCode();
192 }
193 _SEH_END;
194 }
195 }
196
197 return Status;
198 }
199
200
201 NTSTATUS STDCALL
202 NtOpenEvent(OUT PHANDLE EventHandle,
203 IN ACCESS_MASK DesiredAccess,
204 IN POBJECT_ATTRIBUTES ObjectAttributes)
205 {
206 NTSTATUS Status;
207 HANDLE hEvent;
208
209 DPRINT("ObjectName '%wZ'\n", ObjectAttributes->ObjectName);
210
211 Status = ObOpenObjectByName(ObjectAttributes,
212 ExEventObjectType,
213 NULL,
214 UserMode,
215 DesiredAccess,
216 NULL,
217 &hEvent);
218
219 if (!NT_SUCCESS(Status))
220 {
221 return(Status);
222 }
223
224 Status = MmCopyToCaller(EventHandle, &hEvent, sizeof(HANDLE));
225 if (!NT_SUCCESS(Status))
226 {
227 ZwClose(EventHandle);
228 return(Status);
229 }
230
231 return(Status);
232 }
233
234
235 NTSTATUS STDCALL
236 NtPulseEvent(IN HANDLE EventHandle,
237 OUT PLONG PreviousState OPTIONAL)
238 {
239 PKEVENT Event;
240 NTSTATUS Status;
241
242 DPRINT("NtPulseEvent(EventHandle %x PreviousState %x)\n",
243 EventHandle, PreviousState);
244
245 Status = ObReferenceObjectByHandle(EventHandle,
246 EVENT_MODIFY_STATE,
247 ExEventObjectType,
248 UserMode,
249 (PVOID*)&Event,
250 NULL);
251 if (!NT_SUCCESS(Status))
252 {
253 return(Status);
254 }
255
256 KePulseEvent(Event, EVENT_INCREMENT, FALSE);
257
258 ObDereferenceObject(Event);
259 return(STATUS_SUCCESS);
260 }
261
262
263 NTSTATUS STDCALL
264 NtQueryEvent(IN HANDLE EventHandle,
265 IN EVENT_INFORMATION_CLASS EventInformationClass,
266 OUT PVOID EventInformation,
267 IN ULONG EventInformationLength,
268 OUT PULONG ReturnLength OPTIONAL)
269 {
270 EVENT_BASIC_INFORMATION Info;
271 PKEVENT Event;
272 NTSTATUS Status;
273 ULONG RetLen;
274
275 if (EventInformationClass > EventBasicInformation)
276 return STATUS_INVALID_INFO_CLASS;
277
278 if (EventInformationLength < sizeof(EVENT_BASIC_INFORMATION))
279 return STATUS_INFO_LENGTH_MISMATCH;
280
281 Status = ObReferenceObjectByHandle(EventHandle,
282 EVENT_QUERY_STATE,
283 ExEventObjectType,
284 UserMode,
285 (PVOID*)&Event,
286 NULL);
287 if (!NT_SUCCESS(Status))
288 return Status;
289
290 if (Event->Header.Type == InternalNotificationEvent)
291 Info.EventType = NotificationEvent;
292 else
293 Info.EventType = SynchronizationEvent;
294 Info.EventState = KeReadStateEvent(Event);
295
296 Status = MmCopyToCaller(EventInformation, &Event,
297 sizeof(EVENT_BASIC_INFORMATION));
298 if (!NT_SUCCESS(Status))
299 {
300 ObDereferenceObject(Event);
301 return(Status);
302 }
303
304 if (ReturnLength != NULL)
305 {
306 RetLen = sizeof(EVENT_BASIC_INFORMATION);
307 Status = MmCopyToCaller(ReturnLength, &RetLen, sizeof(ULONG));
308 if (!NT_SUCCESS(Status))
309 {
310 ObDereferenceObject(Event);
311 return(Status);
312 }
313 }
314
315 ObDereferenceObject(Event);
316 return(STATUS_SUCCESS);
317 }
318
319
320 NTSTATUS STDCALL
321 NtResetEvent(IN HANDLE EventHandle,
322 OUT PLONG PreviousState OPTIONAL)
323 {
324 PKEVENT Event;
325 NTSTATUS Status;
326
327 DPRINT("NtResetEvent(EventHandle %x)\n", EventHandle);
328
329 Status = ObReferenceObjectByHandle(EventHandle,
330 EVENT_MODIFY_STATE,
331 ExEventObjectType,
332 UserMode,
333 (PVOID*)&Event,
334 NULL);
335 if (!NT_SUCCESS(Status))
336 {
337 return(Status);
338 }
339 KeResetEvent(Event);
340 ObDereferenceObject(Event);
341 return(STATUS_SUCCESS);
342 }
343
344
345 /*
346 * @implemented
347 */
348 NTSTATUS STDCALL
349 NtSetEvent(IN HANDLE EventHandle,
350 OUT PLONG PreviousState OPTIONAL)
351 {
352 PKEVENT Event;
353 NTSTATUS Status;
354
355 DPRINT("NtSetEvent(EventHandle %x)\n", EventHandle);
356
357 Status = ObReferenceObjectByHandle(EventHandle,
358 EVENT_MODIFY_STATE,
359 ExEventObjectType,
360 UserMode,
361 (PVOID*)&Event,
362 NULL);
363 if (!NT_SUCCESS(Status))
364 {
365 return(Status);
366 }
367 KeSetEvent(Event,EVENT_INCREMENT,FALSE);
368 ObDereferenceObject(Event);
369 return(STATUS_SUCCESS);
370 }
371
372 /*
373 * @unimplemented
374 */
375 NTSTATUS
376 STDCALL
377 NtTraceEvent(
378 IN ULONG TraceHandle,
379 IN ULONG Flags,
380 IN ULONG TraceHeaderLength,
381 IN struct _EVENT_TRACE_HEADER* TraceHeader
382 )
383 {
384 UNIMPLEMENTED;
385 return STATUS_NOT_IMPLEMENTED;
386 }
387
388
389 /* EOF */