- Fixed the freeing of memory from boot load drivers.
[reactos.git] / reactos / ntoskrnl / nt / ntevent.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 <limits.h>
31 #define NTOS_MODE_KERNEL
32 #include <ntos.h>
33 #include <internal/id.h>
34 #include <internal/ob.h>
35 #include <ntos/synch.h>
36 #include <internal/pool.h>
37 #include <internal/safe.h>
38
39 #define NDEBUG
40 #include <internal/debug.h>
41
42 /* GLOBALS *******************************************************************/
43
44 POBJECT_TYPE EXPORTED ExEventObjectType = NULL;
45
46 static GENERIC_MAPPING ExpEventMapping = {
47 STANDARD_RIGHTS_READ | SYNCHRONIZE | EVENT_QUERY_STATE,
48 STANDARD_RIGHTS_WRITE | SYNCHRONIZE | EVENT_MODIFY_STATE,
49 STANDARD_RIGHTS_EXECUTE | SYNCHRONIZE | EVENT_QUERY_STATE,
50 EVENT_ALL_ACCESS};
51
52
53 /* FUNCTIONS *****************************************************************/
54
55 NTSTATUS STDCALL
56 NtpCreateEvent(PVOID ObjectBody,
57 PVOID Parent,
58 PWSTR RemainingPath,
59 POBJECT_ATTRIBUTES ObjectAttributes)
60 {
61 DPRINT("NtpCreateEvent(ObjectBody %x, Parent %x, RemainingPath %S)\n",
62 ObjectBody, Parent, RemainingPath);
63
64 if (RemainingPath != NULL && wcschr(RemainingPath+1, '\\') != NULL)
65 {
66 return(STATUS_UNSUCCESSFUL);
67 }
68
69 return(STATUS_SUCCESS);
70 }
71
72
73 VOID INIT_FUNCTION
74 NtInitializeEventImplementation(VOID)
75 {
76 ExEventObjectType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
77
78 RtlCreateUnicodeString(&ExEventObjectType->TypeName, L"Event");
79
80 ExEventObjectType->Tag = TAG('E', 'V', 'T', 'T');
81 ExEventObjectType->MaxObjects = ULONG_MAX;
82 ExEventObjectType->MaxHandles = ULONG_MAX;
83 ExEventObjectType->TotalObjects = 0;
84 ExEventObjectType->TotalHandles = 0;
85 ExEventObjectType->PagedPoolCharge = 0;
86 ExEventObjectType->NonpagedPoolCharge = sizeof(KEVENT);
87 ExEventObjectType->Mapping = &ExpEventMapping;
88 ExEventObjectType->Dump = NULL;
89 ExEventObjectType->Open = NULL;
90 ExEventObjectType->Close = NULL;
91 ExEventObjectType->Delete = NULL;
92 ExEventObjectType->Parse = NULL;
93 ExEventObjectType->Security = NULL;
94 ExEventObjectType->QueryName = NULL;
95 ExEventObjectType->OkayToClose = NULL;
96 ExEventObjectType->Create = NtpCreateEvent;
97 ExEventObjectType->DuplicationNotify = NULL;
98
99 ObpCreateTypeObject(ExEventObjectType);
100 }
101
102
103 NTSTATUS STDCALL
104 NtClearEvent(IN HANDLE EventHandle)
105 {
106 PKEVENT Event;
107 NTSTATUS Status;
108
109 Status = ObReferenceObjectByHandle(EventHandle,
110 EVENT_MODIFY_STATE,
111 ExEventObjectType,
112 UserMode,
113 (PVOID*)&Event,
114 NULL);
115 if (!NT_SUCCESS(Status))
116 {
117 return(Status);
118 }
119 KeClearEvent(Event);
120 ObDereferenceObject(Event);
121 return(STATUS_SUCCESS);
122 }
123
124
125 /*
126 * @implemented
127 */
128 NTSTATUS STDCALL
129 NtCreateEvent(OUT PHANDLE UnsafeEventHandle,
130 IN ACCESS_MASK DesiredAccess,
131 IN POBJECT_ATTRIBUTES UnsafeObjectAttributes,
132 IN BOOLEAN ManualReset,
133 IN BOOLEAN InitialState)
134 {
135 PKEVENT Event;
136 HANDLE EventHandle;
137 NTSTATUS Status;
138 OBJECT_ATTRIBUTES SafeObjectAttributes;
139 POBJECT_ATTRIBUTES ObjectAttributes;
140
141 if (UnsafeObjectAttributes != NULL)
142 {
143 Status = MmCopyFromCaller(&SafeObjectAttributes, UnsafeObjectAttributes,
144 sizeof(OBJECT_ATTRIBUTES));
145 if (!NT_SUCCESS(Status))
146 {
147 return(Status);
148 }
149 ObjectAttributes = &SafeObjectAttributes;
150 }
151 else
152 {
153 ObjectAttributes = NULL;
154 }
155
156 Status = ObCreateObject(ExGetPreviousMode(),
157 ExEventObjectType,
158 ObjectAttributes,
159 ExGetPreviousMode(),
160 NULL,
161 sizeof(KEVENT),
162 0,
163 0,
164 (PVOID*)&Event);
165 if (!NT_SUCCESS(Status))
166 {
167 return(Status);
168 }
169 KeInitializeEvent(Event,
170 ManualReset ? NotificationEvent : SynchronizationEvent,
171 InitialState);
172
173 Status = ObInsertObject ((PVOID)Event,
174 NULL,
175 DesiredAccess,
176 0,
177 NULL,
178 &EventHandle);
179 ObDereferenceObject(Event);
180 if (!NT_SUCCESS(Status))
181 {
182 return Status;
183 }
184
185 Status = MmCopyToCaller(UnsafeEventHandle, &EventHandle, sizeof(HANDLE));
186 if (!NT_SUCCESS(Status))
187 {
188 ZwClose(EventHandle);
189 return(Status);
190 }
191 return(STATUS_SUCCESS);
192 }
193
194
195 NTSTATUS STDCALL
196 NtOpenEvent(OUT PHANDLE UnsafeEventHandle,
197 IN ACCESS_MASK DesiredAccess,
198 IN POBJECT_ATTRIBUTES ObjectAttributes)
199 {
200 NTSTATUS Status;
201 HANDLE EventHandle;
202
203 DPRINT("ObjectName '%wZ'\n", ObjectAttributes->ObjectName);
204
205 Status = ObOpenObjectByName(ObjectAttributes,
206 ExEventObjectType,
207 NULL,
208 UserMode,
209 DesiredAccess,
210 NULL,
211 &EventHandle);
212
213 Status = MmCopyToCaller(UnsafeEventHandle, &EventHandle, sizeof(HANDLE));
214 if (!NT_SUCCESS(Status))
215 {
216 ZwClose(EventHandle);
217 return(Status);
218 }
219
220 return(Status);
221 }
222
223
224 NTSTATUS STDCALL
225 NtPulseEvent(IN HANDLE EventHandle,
226 IN PULONG UnsafePulseCount OPTIONAL)
227 {
228 PKEVENT Event;
229 NTSTATUS Status;
230
231 DPRINT("NtPulseEvent(EventHandle %x UnsafePulseCount %x)\n",
232 EventHandle, UnsafePulseCount);
233
234 Status = ObReferenceObjectByHandle(EventHandle,
235 EVENT_MODIFY_STATE,
236 ExEventObjectType,
237 UserMode,
238 (PVOID*)&Event,
239 NULL);
240 if (!NT_SUCCESS(Status))
241 {
242 return(Status);
243 }
244
245 KePulseEvent(Event, EVENT_INCREMENT, FALSE);
246
247 ObDereferenceObject(Event);
248 return(STATUS_SUCCESS);
249 }
250
251
252 NTSTATUS STDCALL
253 NtQueryEvent(IN HANDLE EventHandle,
254 IN EVENT_INFORMATION_CLASS EventInformationClass,
255 OUT PVOID UnsafeEventInformation,
256 IN ULONG EventInformationLength,
257 OUT PULONG UnsafeReturnLength)
258 {
259 EVENT_BASIC_INFORMATION Info;
260 PKEVENT Event;
261 NTSTATUS Status;
262 ULONG ReturnLength;
263
264 if (EventInformationClass > EventBasicInformation)
265 return STATUS_INVALID_INFO_CLASS;
266
267 if (EventInformationLength < sizeof(EVENT_BASIC_INFORMATION))
268 return STATUS_INFO_LENGTH_MISMATCH;
269
270 Status = ObReferenceObjectByHandle(EventHandle,
271 EVENT_QUERY_STATE,
272 ExEventObjectType,
273 UserMode,
274 (PVOID*)&Event,
275 NULL);
276 if (!NT_SUCCESS(Status))
277 return Status;
278
279 if (Event->Header.Type == InternalNotificationEvent)
280 Info.EventType = NotificationEvent;
281 else
282 Info.EventType = SynchronizationEvent;
283 Info.EventState = KeReadStateEvent(Event);
284
285 Status = MmCopyToCaller(UnsafeEventInformation, &Event,
286 sizeof(EVENT_BASIC_INFORMATION));
287 if (!NT_SUCCESS(Status))
288 {
289 ObDereferenceObject(Event);
290 return(Status);
291 }
292
293 ReturnLength = sizeof(EVENT_BASIC_INFORMATION);
294 Status = MmCopyToCaller(UnsafeReturnLength, &ReturnLength, sizeof(ULONG));
295 if (!NT_SUCCESS(Status))
296 {
297 ObDereferenceObject(Event);
298 return(Status);
299 }
300
301 ObDereferenceObject(Event);
302
303 return(STATUS_SUCCESS);
304 }
305
306
307 NTSTATUS STDCALL
308 NtResetEvent(IN HANDLE EventHandle,
309 OUT PULONG UnsafeNumberOfWaitingThreads OPTIONAL)
310 {
311 PKEVENT Event;
312 NTSTATUS Status;
313
314 DPRINT("NtResetEvent(EventHandle %x)\n", EventHandle);
315
316 Status = ObReferenceObjectByHandle(EventHandle,
317 EVENT_MODIFY_STATE,
318 ExEventObjectType,
319 UserMode,
320 (PVOID*)&Event,
321 NULL);
322 if (!NT_SUCCESS(Status))
323 {
324 return(Status);
325 }
326 KeResetEvent(Event);
327 ObDereferenceObject(Event);
328 return(STATUS_SUCCESS);
329 }
330
331
332 /*
333 * @implemented
334 */
335 NTSTATUS STDCALL
336 NtSetEvent(IN HANDLE EventHandle,
337 OUT PULONG UnsafeNumberOfThreadsReleased)
338 {
339 PKEVENT Event;
340 NTSTATUS Status;
341
342 DPRINT("NtSetEvent(EventHandle %x)\n", EventHandle);
343
344 Status = ObReferenceObjectByHandle(EventHandle,
345 EVENT_MODIFY_STATE,
346 ExEventObjectType,
347 UserMode,
348 (PVOID*)&Event,
349 NULL);
350 if (!NT_SUCCESS(Status))
351 {
352 return(Status);
353 }
354 KeSetEvent(Event,EVENT_INCREMENT,FALSE);
355 ObDereferenceObject(Event);
356 return(STATUS_SUCCESS);
357 }
358
359 /* EOF */