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