fedb507a9b947bd6a44f2ef3b4b4f56ef17a63ab
[reactos.git] / reactos / drivers / ksfilter / ks / event.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/event.c
5 * PURPOSE: KS Event functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "priv.h"
10
11 BOOLEAN
12 KspSynchronizedEventRoutine(
13 IN KSEVENTS_LOCKTYPE EventsFlags,
14 IN PVOID EventsLock,
15 IN PKSEVENT_SYNCHRONIZED_ROUTINE SynchronizedRoutine,
16 IN PKSEVENT_CTX Ctx)
17 {
18 BOOLEAN Result = FALSE;
19 KIRQL OldLevel;
20
21 if (EventsFlags == KSEVENTS_NONE)
22 {
23 /* no synchronization required */
24 Result = SynchronizedRoutine(Ctx);
25 }
26 else if (EventsFlags == KSEVENTS_SPINLOCK)
27 {
28 /* use spin lock */
29 KeAcquireSpinLock((PKSPIN_LOCK)EventsLock, &OldLevel);
30 Result = SynchronizedRoutine(Ctx);
31 KeReleaseSpinLock((PKSPIN_LOCK)EventsLock, OldLevel);
32 }
33 else if (EventsFlags == KSEVENTS_MUTEX)
34 {
35 /* use a mutex */
36 KeWaitForSingleObject(EventsLock, Executive, KernelMode, FALSE, NULL);
37 Result = SynchronizedRoutine(Ctx);
38 KeReleaseMutex((PRKMUTEX)EventsLock, FALSE);
39 }
40 else if (EventsFlags == KSEVENTS_FMUTEX)
41 {
42 /* use a fast mutex */
43 ExAcquireFastMutex((PFAST_MUTEX)EventsLock);
44 Result = SynchronizedRoutine(Ctx);
45 ExReleaseFastMutex((PFAST_MUTEX)EventsLock);
46 }
47 else if (EventsFlags == KSEVENTS_FMUTEXUNSAFE)
48 {
49 /* acquire fast mutex unsafe */
50 KeEnterCriticalRegion();
51 ExAcquireFastMutexUnsafe((PFAST_MUTEX)EventsLock);
52 Result = SynchronizedRoutine(Ctx);
53 ExReleaseFastMutexUnsafe((PFAST_MUTEX)EventsLock);
54 KeLeaveCriticalRegion();
55 }
56 else if (EventsFlags == KSEVENTS_INTERRUPT)
57 {
58 /* use interrupt for locking */
59 Result = KeSynchronizeExecution((PKINTERRUPT)EventsLock, (PKSYNCHRONIZE_ROUTINE)SynchronizedRoutine, (PVOID)Ctx);
60 }
61 else if (EventsFlags == KSEVENTS_ERESOURCE)
62 {
63 /* use an eresource */
64 KeEnterCriticalRegion();
65 ExAcquireResourceExclusiveLite((PERESOURCE)EventsLock, TRUE);
66 Result = SynchronizedRoutine(Ctx);
67 ExReleaseResourceLite((PERESOURCE)EventsLock);
68 KeLeaveCriticalRegion();
69 }
70
71 return Result;
72 }
73
74
75 /*
76 @unimplemented
77 */
78 KSDDKAPI
79 NTSTATUS
80 NTAPI
81 KsEnableEvent(
82 IN PIRP Irp,
83 IN ULONG EventSetsCount,
84 IN KSEVENT_SET* EventSet,
85 IN OUT PLIST_ENTRY EventsList OPTIONAL,
86 IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
87 IN PVOID EventsLock OPTIONAL)
88 {
89 UNIMPLEMENTED;
90 return STATUS_SUCCESS;
91 }
92
93 /*
94 @unimplemented
95 */
96 KSDDKAPI
97 NTSTATUS
98 NTAPI
99 KsEnableEventWithAllocator(
100 IN PIRP Irp,
101 IN ULONG EventSetsCount,
102 IN PKSEVENT_SET EventSet,
103 IN OUT PLIST_ENTRY EventsList OPTIONAL,
104 IN KSEVENTS_LOCKTYPE EventsFlags OPTIONAL,
105 IN PVOID EventsLock OPTIONAL,
106 IN PFNKSALLOCATOR Allocator OPTIONAL,
107 IN ULONG EventItemSize OPTIONAL)
108 {
109 UNIMPLEMENTED;
110 return STATUS_UNSUCCESSFUL;
111 }
112
113 BOOLEAN
114 NTAPI
115 KspDisableEvent(
116 IN PKSEVENT_CTX Ctx)
117 {
118 PIO_STACK_LOCATION IoStack;
119 PKSEVENTDATA EventData;
120 PKSEVENT_ENTRY EventEntry;
121 PLIST_ENTRY Entry;
122
123 /* get current irp stack location */
124 IoStack = IoGetCurrentIrpStackLocation(Ctx->Irp);
125
126 /* get event data */
127 EventData = (PKSEVENTDATA)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
128
129 if (!Ctx || !Ctx->List || !Ctx->FileObject || !Ctx->Irp)
130 {
131 /* invalid parameter */
132 return FALSE;
133 }
134
135 /* point to first entry */
136 Entry = Ctx->List->Flink;
137
138 while(Entry != Ctx->List)
139 {
140 /* get event entry */
141 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
142
143 if (EventEntry->EventData == EventData && EventEntry->FileObject == Ctx->FileObject)
144 {
145 /* found the entry */
146 RemoveEntryList(&EventEntry->ListEntry);
147 Ctx->EventEntry = EventEntry;
148 return TRUE;
149 }
150
151 /* move to next item */
152 Entry = Entry->Flink;
153 }
154 /* entry not found */
155 return TRUE;
156 }
157
158 /*
159 @implemented
160 */
161 KSDDKAPI
162 NTSTATUS
163 NTAPI
164 KsDisableEvent(
165 IN PIRP Irp,
166 IN OUT PLIST_ENTRY EventsList,
167 IN KSEVENTS_LOCKTYPE EventsFlags,
168 IN PVOID EventsLock)
169 {
170 PIO_STACK_LOCATION IoStack;
171 KSEVENT_CTX Ctx;
172
173 /* get current irp stack location */
174 IoStack = IoGetCurrentIrpStackLocation(Irp);
175
176 /* is there a event entry */
177 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSEVENTDATA))
178 {
179 if (IoStack->Parameters.DeviceIoControl.InputBufferLength == 0)
180 {
181 /* caller wants to free event items */
182 KsFreeEventList(IoStack->FileObject, EventsList, EventsFlags, EventsLock);
183 return STATUS_SUCCESS;
184 }
185 /* invalid parameter */
186 return STATUS_INVALID_BUFFER_SIZE;
187 }
188
189 /* setup event ctx */
190 Ctx.List = EventsList;
191 Ctx.FileObject = IoStack->FileObject;
192 Ctx.Irp = Irp;
193 Ctx.EventEntry = NULL;
194
195 if (KspSynchronizedEventRoutine(EventsFlags, EventsLock, KspDisableEvent, &Ctx))
196 {
197 /* was the event entry found */
198 if (Ctx.EventEntry)
199 {
200 /* discard event */
201 KsDiscardEvent(Ctx.EventEntry);
202 return STATUS_SUCCESS;
203 }
204 /* event was not found */
205 return STATUS_UNSUCCESSFUL;
206 }
207
208 /* invalid parameters */
209 return STATUS_INVALID_PARAMETER;
210 }
211
212 /*
213 @unimplemented
214 */
215 KSDDKAPI
216 VOID
217 NTAPI
218 KsDiscardEvent(
219 IN PKSEVENT_ENTRY EventEntry)
220 {
221 //UNIMPLEMENTED;
222 }
223
224
225 BOOLEAN
226 NTAPI
227 KspFreeEventList(
228 IN PKSEVENT_CTX Ctx)
229 {
230 PLIST_ENTRY Entry;
231 PKSEVENT_ENTRY EventEntry;
232
233 /* check valid input */
234 if (!Ctx || !Ctx->List)
235 return FALSE;
236
237 if (IsListEmpty(Ctx->List))
238 return FALSE;
239
240 /* remove first entry */
241 Entry = RemoveHeadList(Ctx->List);
242 if (!Entry)
243 {
244 /* list is empty, bye-bye */
245 return FALSE;
246 }
247
248 /* get event entry */
249 EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(Entry, KSEVENT_ENTRY, ListEntry);
250
251 /* store event entry */
252 Ctx->EventEntry = EventEntry;
253 /* return success */
254 return TRUE;
255 }
256
257
258 /*
259 @implemented
260 */
261 KSDDKAPI
262 VOID
263 NTAPI
264 KsFreeEventList(
265 IN PFILE_OBJECT FileObject,
266 IN OUT PLIST_ENTRY EventsList,
267 IN KSEVENTS_LOCKTYPE EventsFlags,
268 IN PVOID EventsLock)
269 {
270 KSEVENT_CTX Ctx;
271
272 /* setup event ctx */
273 Ctx.List = EventsList;
274 Ctx.FileObject = FileObject;
275 Ctx.EventEntry = NULL;
276
277 while(KspSynchronizedEventRoutine(EventsFlags, EventsLock, KspFreeEventList, &Ctx))
278 {
279 if (Ctx.EventEntry)
280 {
281 KsDiscardEvent(Ctx.EventEntry);
282 }
283 }
284 }
285
286
287 /*
288 @implemented
289 */
290 KSDDKAPI
291 NTSTATUS
292 NTAPI
293 KsGenerateEvent(
294 IN PKSEVENT_ENTRY EntryEvent)
295 {
296 if (EntryEvent->NotificationType == KSEVENTF_EVENT_HANDLE || EntryEvent->NotificationType == KSEVENTF_EVENT_OBJECT)
297 {
298 // signal event
299 KeSetEvent(EntryEvent->Object, 0, FALSE);
300 }
301 else if (EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_HANDLE || EntryEvent->NotificationType == KSEVENTF_SEMAPHORE_OBJECT)
302 {
303 // release semaphore
304 KeReleaseSemaphore(EntryEvent->Object, 0, EntryEvent->SemaphoreAdjustment, FALSE);
305 }
306 else if (EntryEvent->NotificationType == KSEVENTF_DPC)
307 {
308 // queue dpc
309 KeInsertQueueDpc((PRKDPC)EntryEvent->Object, NULL, NULL);
310 }
311 else if (EntryEvent->NotificationType == KSEVENTF_WORKITEM)
312 {
313 // queue work item
314 ExQueueWorkItem((PWORK_QUEUE_ITEM)EntryEvent->Object, PtrToUlong(EntryEvent->BufferItem));
315 }
316 else if (EntryEvent->NotificationType == KSEVENTF_KSWORKITEM)
317 {
318 // queue work item of ks worker
319 return KsQueueWorkItem((PKSWORKER)EntryEvent->Object, (PWORK_QUEUE_ITEM)EntryEvent->DpcItem);
320 }
321 else
322 {
323 UNIMPLEMENTED;
324 return STATUS_UNSUCCESSFUL;
325 }
326
327 return STATUS_SUCCESS;
328 }
329
330 /*
331 @unimplemented
332 */
333 KSDDKAPI
334 NTSTATUS
335 NTAPI
336 KsGenerateDataEvent(
337 IN PKSEVENT_ENTRY EventEntry,
338 IN ULONG DataSize,
339 IN PVOID Data)
340 {
341 UNIMPLEMENTED;
342 return STATUS_UNSUCCESSFUL;
343 }
344
345 /*
346 @unimplemented
347 */
348 KSDDKAPI
349 VOID
350 NTAPI
351 KsGenerateEventList(
352 IN GUID* Set OPTIONAL,
353 IN ULONG EventId,
354 IN PLIST_ENTRY EventsList,
355 IN KSEVENTS_LOCKTYPE EventsFlags,
356 IN PVOID EventsLock)
357 {
358 UNIMPLEMENTED
359 }
360
361 /*
362 @implemented
363 */
364 KSDDKAPI
365 VOID
366 NTAPI
367 KsAddEvent(
368 IN PVOID Object,
369 IN PKSEVENT_ENTRY EventEntry)
370 {
371 PKSBASIC_HEADER Header = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
372
373 ExInterlockedInsertTailList(&Header->EventList, &EventEntry->ListEntry, &Header->EventListLock);
374 }
375
376 /*
377 @implemented
378 */
379 NTSTATUS
380 NTAPI
381 KsDefaultAddEventHandler(
382 IN PIRP Irp,
383 IN PKSEVENTDATA EventData,
384 IN OUT PKSEVENT_ENTRY EventEntry)
385 {
386 PIO_STACK_LOCATION IoStack;
387 PKSIOBJECT_HEADER ObjectHeader;
388 PKSBASIC_HEADER Header;
389
390 /* first get the io stack location */
391 IoStack = IoGetCurrentIrpStackLocation(Irp);
392
393 /* now get the object header */
394 ObjectHeader =(PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
395
396 /* sanity check */
397 ASSERT(ObjectHeader->ObjectType);
398
399 /* obtain basic header */
400 Header = (PKSBASIC_HEADER)((ULONG_PTR)ObjectHeader->ObjectType - sizeof(KSBASIC_HEADER));
401
402 /* now insert the event entry */
403 ExInterlockedInsertTailList(&Header->EventList, &EventEntry->ListEntry, &Header->EventListLock);
404
405 /* done */
406 return STATUS_SUCCESS;
407 }
408
409
410
411 /*
412 @unimplemented
413 */
414 KSDDKAPI
415 void
416 NTAPI
417 KsGenerateEvents(
418 IN PVOID Object,
419 IN const GUID* EventSet OPTIONAL,
420 IN ULONG EventId,
421 IN ULONG DataSize,
422 IN PVOID Data OPTIONAL,
423 IN PFNKSGENERATEEVENTCALLBACK CallBack OPTIONAL,
424 IN PVOID CallBackContext OPTIONAL)
425 {
426 UNIMPLEMENTED
427 }