- Store KSPROPERTY_SET in Irp when using KsPropertyHandler
[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 @unimplemented
289 */
290 KSDDKAPI
291 NTSTATUS
292 NTAPI
293 KsGenerateEvent(
294 IN PKSEVENT_ENTRY EntryEvent)
295 {
296 UNIMPLEMENTED;
297 return STATUS_UNSUCCESSFUL;
298 }
299
300 /*
301 @unimplemented
302 */
303 KSDDKAPI
304 NTSTATUS
305 NTAPI
306 KsGenerateDataEvent(
307 IN PKSEVENT_ENTRY EventEntry,
308 IN ULONG DataSize,
309 IN PVOID Data)
310 {
311 UNIMPLEMENTED;
312 return STATUS_UNSUCCESSFUL;
313 }
314
315 /*
316 @unimplemented
317 */
318 KSDDKAPI
319 VOID
320 NTAPI
321 KsGenerateEventList(
322 IN GUID* Set OPTIONAL,
323 IN ULONG EventId,
324 IN PLIST_ENTRY EventsList,
325 IN KSEVENTS_LOCKTYPE EventsFlags,
326 IN PVOID EventsLock)
327 {
328 UNIMPLEMENTED
329 }
330
331 /*
332 @implemented
333 */
334 KSDDKAPI
335 VOID
336 NTAPI
337 KsAddEvent(
338 IN PVOID Object,
339 IN PKSEVENT_ENTRY EventEntry)
340 {
341 PKSBASIC_HEADER Header = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
342
343 ExInterlockedInsertTailList(&Header->EventList, &EventEntry->ListEntry, &Header->EventListLock);
344 }
345
346 /*
347 @implemented
348 */
349 NTSTATUS
350 NTAPI
351 KsDefaultAddEventHandler(
352 IN PIRP Irp,
353 IN PKSEVENTDATA EventData,
354 IN OUT PKSEVENT_ENTRY EventEntry)
355 {
356 PIO_STACK_LOCATION IoStack;
357 PKSIOBJECT_HEADER ObjectHeader;
358 PKSBASIC_HEADER Header;
359
360 /* first get the io stack location */
361 IoStack = IoGetCurrentIrpStackLocation(Irp);
362
363 /* now get the object header */
364 ObjectHeader =(PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
365
366 /* sanity check */
367 ASSERT(ObjectHeader->ObjectType);
368
369 /* obtain basic header */
370 Header = (PKSBASIC_HEADER)((ULONG_PTR)ObjectHeader->ObjectType - sizeof(KSBASIC_HEADER));
371
372 /* now insert the event entry */
373 ExInterlockedInsertTailList(&Header->EventList, &EventEntry->ListEntry, &Header->EventListLock);
374
375 /* done */
376 return STATUS_SUCCESS;
377 }
378
379
380
381 /*
382 @unimplemented
383 */
384 KSDDKAPI
385 void
386 NTAPI
387 KsGenerateEvents(
388 IN PVOID Object,
389 IN const GUID* EventSet OPTIONAL,
390 IN ULONG EventId,
391 IN ULONG DataSize,
392 IN PVOID Data OPTIONAL,
393 IN PFNKSGENERATEEVENTCALLBACK CallBack OPTIONAL,
394 IN PVOID CallBackContext OPTIONAL)
395 {
396 UNIMPLEMENTED
397 }