xref: /reactos/drivers/ksfilter/ks/filter.c (revision f5e54015)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/ksfilter/ks/filter.c
5  * PURPOSE:         KS IKsFilter interface functions
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 #include "precomp.h"
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 typedef struct
15 {
16     KSBASIC_HEADER Header;
17     KSFILTER Filter;
18 
19     IKsControlVtbl *lpVtblKsControl;
20     IKsFilterFactory * FilterFactory;
21     IKsProcessingObjectVtbl * lpVtblKsProcessingObject;
22     LONG ref;
23 
24     PKSIOBJECT_HEADER ObjectHeader;
25     KSTOPOLOGY Topology;
26     PKSFILTERFACTORY Factory;
27     PFILE_OBJECT FileObject;
28     KMUTEX ControlMutex;
29     KMUTEX ProcessingMutex;
30 
31     PKSWORKER Worker;
32     WORK_QUEUE_ITEM WorkItem;
33     KSGATE Gate;
34 
35     PFNKSFILTERPOWER Sleep;
36     PFNKSFILTERPOWER Wake;
37 
38     ULONG *PinInstanceCount;
39     PKSPIN * FirstPin;
40     PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
41 
42 }IKsFilterImpl;
43 
44 const GUID IID_IKsControl = {0x28F54685L, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
45 const GUID IID_IKsFilter  = {0x3ef6ee44L, 0x0D41, 0x11d2, {0xbe, 0xDA, 0x00, 0xc0, 0x4f, 0x8e, 0xF4, 0x57}};
46 const GUID KSPROPSETID_Topology                = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
47 const GUID KSPROPSETID_Pin                     = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
48 const GUID KSPROPSETID_General =                 {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
49 
50 VOID
51 IKsFilter_RemoveFilterFromFilterFactory(
52     IKsFilterImpl * This,
53     PKSFILTERFACTORY FilterFactory);
54 
55 NTSTATUS NTAPI FilterTopologyPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER  Request, IN OUT PVOID  Data);
56 NTSTATUS NTAPI FilterPinPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER  Request, IN OUT PVOID  Data);
57 NTSTATUS NTAPI FilterGeneralComponentIdHandler(IN PIRP Irp, IN PKSIDENTIFIER  Request, IN OUT PVOID  Data);
58 
59 DEFINE_KSPROPERTY_TOPOLOGYSET(IKsFilterTopologySet, FilterTopologyPropertyHandler);
60 DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(IKsFilterPinSet, FilterPinPropertyHandler, FilterPinPropertyHandler, FilterPinPropertyHandler);
61 DEFINE_KSPROPERTY_GENEREAL_COMPONENTID(IKsFilterGeneralSet, FilterGeneralComponentIdHandler);
62 
63 KSPROPERTY_SET FilterPropertySet[] =
64 {
65     {
66         &KSPROPSETID_Topology,
67         sizeof(IKsFilterTopologySet) / sizeof(KSPROPERTY_ITEM),
68         (const KSPROPERTY_ITEM*)&IKsFilterTopologySet,
69         0,
70         NULL
71     },
72     {
73         &KSPROPSETID_Pin,
74         sizeof(IKsFilterPinSet) / sizeof(KSPROPERTY_ITEM),
75         (const KSPROPERTY_ITEM*)&IKsFilterPinSet,
76         0,
77         NULL
78     },
79     {
80         &KSPROPSETID_General,
81         sizeof(IKsFilterGeneralSet) / sizeof(KSPROPERTY_ITEM),
82         (const KSPROPERTY_ITEM*)&IKsFilterGeneralSet,
83         0,
84         NULL
85     }
86 };
87 
88 NTSTATUS
89 NTAPI
IKsProcessingObject_fnQueryInterface(IKsProcessingObject * iface,IN REFIID refiid,OUT PVOID * Output)90 IKsProcessingObject_fnQueryInterface(
91     IKsProcessingObject * iface,
92     IN  REFIID refiid,
93     OUT PVOID* Output)
94 {
95     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
96 
97     if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
98     {
99         *Output = &This->Header.OuterUnknown;
100         _InterlockedIncrement(&This->ref);
101         return STATUS_SUCCESS;
102     }
103     return STATUS_UNSUCCESSFUL;
104 }
105 
106 ULONG
107 NTAPI
IKsProcessingObject_fnAddRef(IKsProcessingObject * iface)108 IKsProcessingObject_fnAddRef(
109     IKsProcessingObject * iface)
110 {
111     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
112 
113     return InterlockedIncrement(&This->ref);
114 }
115 
116 ULONG
117 NTAPI
IKsProcessingObject_fnRelease(IKsProcessingObject * iface)118 IKsProcessingObject_fnRelease(
119     IKsProcessingObject * iface)
120 {
121     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
122 
123     InterlockedDecrement(&This->ref);
124 
125     /* Return new reference count */
126     return This->ref;
127 }
128 
129 VOID
130 NTAPI
IKsProcessingObject_fnProcessingObjectWork(IKsProcessingObject * iface)131 IKsProcessingObject_fnProcessingObjectWork(
132     IKsProcessingObject * iface)
133 {
134     NTSTATUS Status;
135     LARGE_INTEGER TimeOut;
136     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
137 
138     DPRINT1("processing object\n");
139     /* first check if running at passive level */
140     if (KeGetCurrentIrql() == PASSIVE_LEVEL)
141     {
142         /* acquire processing mutex */
143         KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, NULL);
144     }
145     else
146     {
147         /* dispatch level processing */
148         if (KeReadStateMutex(&This->ControlMutex) == 0)
149         {
150             /* some thread was faster */
151             DPRINT1("processing object too slow\n");
152             return;
153         }
154 
155         /* acquire processing mutex */
156         TimeOut.QuadPart = 0LL;
157         Status = KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, &TimeOut);
158 
159         if (Status == STATUS_TIMEOUT)
160         {
161             /* some thread was faster */
162             DPRINT1("processing object too slow\n");
163             return;
164         }
165     }
166 
167     do
168     {
169 
170         /* check if the and-gate has been enabled again */
171         if (This->Gate.Count != 0)
172         {
173             /* gate is open */
174             DPRINT1("processing object gate open\n");
175             break;
176         }
177 
178         DPRINT1("IKsProcessingObject_fnProcessingObjectWork not implemented\n");
179         ASSERT(0);
180 
181     }while(TRUE);
182 
183     /* release process mutex */
184     KeReleaseMutex(&This->ProcessingMutex, FALSE);
185 }
186 
187 PKSGATE
188 NTAPI
IKsProcessingObject_fnGetAndGate(IKsProcessingObject * iface)189 IKsProcessingObject_fnGetAndGate(
190     IKsProcessingObject * iface)
191 {
192     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
193 
194     /* return and gate */
195     return &This->Gate;
196 }
197 
198 VOID
199 NTAPI
IKsProcessingObject_fnProcess(IKsProcessingObject * iface,IN BOOLEAN Asynchronous)200 IKsProcessingObject_fnProcess(
201     IKsProcessingObject * iface,
202     IN BOOLEAN Asynchronous)
203 {
204     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
205 
206     /* should the action be asynchronous */
207     if (Asynchronous)
208     {
209         /* queue work item */
210         KsQueueWorkItem(This->Worker, &This->WorkItem);
211 DPRINT1("queueing\n");
212         /* done */
213         return;
214     }
215 
216     /* does the filter require explicit deferred processing */
217     if ((This->Filter.Descriptor->Flags & (KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING | KSFILTER_FLAG_CRITICAL_PROCESSING | KSFILTER_FLAG_HYPERCRITICAL_PROCESSING)) &&
218          KeGetCurrentIrql() > PASSIVE_LEVEL)
219     {
220         /* queue work item */
221         KsQueueWorkItem(This->Worker, &This->WorkItem);
222 DPRINT1("queueing\n");
223         /* done */
224         return;
225     }
226 DPRINT1("invoke\n");
227     /* call worker routine directly */
228     iface->lpVtbl->ProcessingObjectWork(iface);
229 }
230 
231 VOID
232 NTAPI
IKsProcessingObject_fnReset(IKsProcessingObject * iface)233 IKsProcessingObject_fnReset(
234     IKsProcessingObject * iface)
235 {
236     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
237 
238     /* acquire processing mutex */
239     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
240 
241     /* check if the filter supports dispatch routines */
242     if (This->Filter.Descriptor->Dispatch)
243     {
244         /* has the filter a reset routine */
245         if (This->Filter.Descriptor->Dispatch->Reset)
246         {
247             /* reset filter */
248             This->Filter.Descriptor->Dispatch->Reset(&This->Filter);
249         }
250     }
251 
252     /* release process mutex */
253     KeReleaseMutex(&This->ProcessingMutex, FALSE);
254 }
255 
256 VOID
257 NTAPI
IKsProcessingObject_fnTriggerNotification(IKsProcessingObject * iface)258 IKsProcessingObject_fnTriggerNotification(
259     IKsProcessingObject * iface)
260 {
261 
262 }
263 
264 static IKsProcessingObjectVtbl vt_IKsProcessingObject =
265 {
266     IKsProcessingObject_fnQueryInterface,
267     IKsProcessingObject_fnAddRef,
268     IKsProcessingObject_fnRelease,
269     IKsProcessingObject_fnProcessingObjectWork,
270     IKsProcessingObject_fnGetAndGate,
271     IKsProcessingObject_fnProcess,
272     IKsProcessingObject_fnReset,
273     IKsProcessingObject_fnTriggerNotification
274 };
275 
276 
277 //---------------------------------------------------------------------------------------------------------
278 NTSTATUS
279 NTAPI
IKsControl_fnQueryInterface(IKsControl * iface,IN REFIID refiid,OUT PVOID * Output)280 IKsControl_fnQueryInterface(
281     IKsControl * iface,
282     IN  REFIID refiid,
283     OUT PVOID* Output)
284 {
285     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
286 
287     if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
288     {
289         *Output = &This->Header.OuterUnknown;
290         _InterlockedIncrement(&This->ref);
291         return STATUS_SUCCESS;
292     }
293     return STATUS_UNSUCCESSFUL;
294 }
295 
296 ULONG
297 NTAPI
IKsControl_fnAddRef(IKsControl * iface)298 IKsControl_fnAddRef(
299     IKsControl * iface)
300 {
301     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
302 
303     return InterlockedIncrement(&This->ref);
304 }
305 
306 ULONG
307 NTAPI
IKsControl_fnRelease(IKsControl * iface)308 IKsControl_fnRelease(
309     IKsControl * iface)
310 {
311     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
312 
313     InterlockedDecrement(&This->ref);
314 
315     /* Return new reference count */
316     return This->ref;
317 }
318 
319 NTSTATUS
320 NTAPI
IKsControl_fnKsProperty(IKsControl * iface,IN PKSPROPERTY Property,IN ULONG PropertyLength,IN OUT PVOID PropertyData,IN ULONG DataLength,OUT ULONG * BytesReturned)321 IKsControl_fnKsProperty(
322     IKsControl * iface,
323     IN PKSPROPERTY Property,
324     IN ULONG PropertyLength,
325     IN OUT PVOID PropertyData,
326     IN ULONG DataLength,
327     OUT ULONG* BytesReturned)
328 {
329     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
330 
331     return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_PROPERTY, Property, PropertyLength, PropertyData, DataLength, BytesReturned);
332 }
333 
334 
335 NTSTATUS
336 NTAPI
IKsControl_fnKsMethod(IKsControl * iface,IN PKSMETHOD Method,IN ULONG MethodLength,IN OUT PVOID MethodData,IN ULONG DataLength,OUT ULONG * BytesReturned)337 IKsControl_fnKsMethod(
338     IKsControl * iface,
339     IN PKSMETHOD Method,
340     IN ULONG MethodLength,
341     IN OUT PVOID MethodData,
342     IN ULONG DataLength,
343     OUT ULONG* BytesReturned)
344 {
345     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
346 
347     return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_METHOD, Method, MethodLength, MethodData, DataLength, BytesReturned);
348 }
349 
350 
351 NTSTATUS
352 NTAPI
IKsControl_fnKsEvent(IKsControl * iface,IN PKSEVENT Event OPTIONAL,IN ULONG EventLength,IN OUT PVOID EventData,IN ULONG DataLength,OUT ULONG * BytesReturned)353 IKsControl_fnKsEvent(
354     IKsControl * iface,
355     IN PKSEVENT Event OPTIONAL,
356     IN ULONG EventLength,
357     IN OUT PVOID EventData,
358     IN ULONG DataLength,
359     OUT ULONG* BytesReturned)
360 {
361     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsControl);
362 
363     if (Event)
364     {
365        return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_ENABLE_EVENT, Event, EventLength, EventData, DataLength, BytesReturned);
366     }
367     else
368     {
369        return KsSynchronousIoControlDevice(This->FileObject, KernelMode, IOCTL_KS_DISABLE_EVENT, EventData, DataLength, NULL, 0, BytesReturned);
370     }
371 
372 }
373 
374 static IKsControlVtbl vt_IKsControl =
375 {
376     IKsControl_fnQueryInterface,
377     IKsControl_fnAddRef,
378     IKsControl_fnRelease,
379     IKsControl_fnKsProperty,
380     IKsControl_fnKsMethod,
381     IKsControl_fnKsEvent
382 };
383 
384 
385 NTSTATUS
386 NTAPI
IKsFilter_fnQueryInterface(IKsFilter * iface,IN REFIID refiid,OUT PVOID * Output)387 IKsFilter_fnQueryInterface(
388     IKsFilter * iface,
389     IN  REFIID refiid,
390     OUT PVOID* Output)
391 {
392     NTSTATUS Status;
393     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
394 
395     if (IsEqualGUIDAligned(refiid, &IID_IUnknown) ||
396         IsEqualGUIDAligned(refiid, &IID_IKsFilter))
397     {
398         *Output = &This->Header.OuterUnknown;
399         _InterlockedIncrement(&This->ref);
400         return STATUS_SUCCESS;
401     }
402     else if (IsEqualGUIDAligned(refiid, &IID_IKsControl))
403     {
404         *Output = &This->lpVtblKsControl;
405         _InterlockedIncrement(&This->ref);
406         return STATUS_SUCCESS;
407     }
408 
409     if (This->Header.ClientAggregate)
410     {
411          /* using client aggregate */
412          Status = This->Header.ClientAggregate->lpVtbl->QueryInterface(This->Header.ClientAggregate, refiid, Output);
413 
414          if (NT_SUCCESS(Status))
415          {
416              /* client aggregate supports interface */
417              return Status;
418          }
419     }
420 
421     DPRINT("IKsFilter_fnQueryInterface no interface\n");
422     return STATUS_NOT_SUPPORTED;
423 }
424 
425 ULONG
426 NTAPI
IKsFilter_fnAddRef(IKsFilter * iface)427 IKsFilter_fnAddRef(
428     IKsFilter * iface)
429 {
430     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
431 
432     return InterlockedIncrement(&This->ref);
433 }
434 
435 ULONG
436 NTAPI
IKsFilter_fnRelease(IKsFilter * iface)437 IKsFilter_fnRelease(
438     IKsFilter * iface)
439 {
440     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
441 
442     InterlockedDecrement(&This->ref);
443 
444     if (This->ref == 0)
445     {
446         FreeItem(This);
447         return 0;
448     }
449     /* Return new reference count */
450     return This->ref;
451 
452 }
453 
454 PKSFILTER
455 NTAPI
IKsFilter_fnGetStruct(IKsFilter * iface)456 IKsFilter_fnGetStruct(
457     IKsFilter * iface)
458 {
459     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
460 
461     return &This->Filter;
462 }
463 
464 BOOL
465 NTAPI
IKsFilter_fnDoAllNecessaryPinsExist(IKsFilter * iface)466 IKsFilter_fnDoAllNecessaryPinsExist(
467     IKsFilter * iface)
468 {
469     UNIMPLEMENTED;
470     return FALSE;
471 }
472 
473 NTSTATUS
474 NTAPI
IKsFilter_fnCreateNode(IKsFilter * iface,IN PIRP Irp,IN IKsPin * Pin,IN PLIST_ENTRY ListEntry)475 IKsFilter_fnCreateNode(
476     IKsFilter * iface,
477     IN PIRP Irp,
478     IN IKsPin * Pin,
479     IN PLIST_ENTRY ListEntry)
480 {
481     UNIMPLEMENTED;
482     return STATUS_NOT_IMPLEMENTED;
483 }
484 
485 NTSTATUS
486 NTAPI
IKsFilter_fnBindProcessPinsToPipeSection(IKsFilter * iface,IN struct KSPROCESSPIPESECTION * Section,IN PVOID Create,IN PKSPIN KsPin,OUT IKsPin ** Pin,OUT PKSGATE * OutGate)487 IKsFilter_fnBindProcessPinsToPipeSection(
488     IKsFilter * iface,
489     IN struct KSPROCESSPIPESECTION *Section,
490     IN PVOID Create,
491     IN PKSPIN KsPin,
492     OUT IKsPin **Pin,
493     OUT PKSGATE *OutGate)
494 {
495     UNIMPLEMENTED;
496     return STATUS_NOT_IMPLEMENTED;
497 }
498 
499 NTSTATUS
500 NTAPI
IKsFilter_fnUnbindProcessPinsFromPipeSection(IKsFilter * iface,IN struct KSPROCESSPIPESECTION * Section)501 IKsFilter_fnUnbindProcessPinsFromPipeSection(
502     IKsFilter * iface,
503     IN struct KSPROCESSPIPESECTION *Section)
504 {
505     UNIMPLEMENTED;
506     return STATUS_NOT_IMPLEMENTED;
507 }
508 
509 NTSTATUS
510 NTAPI
IKsFilter_fnAddProcessPin(IKsFilter * iface,IN PKSPROCESSPIN ProcessPin)511 IKsFilter_fnAddProcessPin(
512     IKsFilter * iface,
513     IN PKSPROCESSPIN ProcessPin)
514 {
515     NTSTATUS Status;
516     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
517 
518     /* first acquire processing mutex */
519     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
520 
521     /* sanity check */
522     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > ProcessPin->Pin->Id);
523 
524     /* allocate new process pin array */
525     Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex[ProcessPin->Pin->Id].Pins,
526                      (This->Filter.Descriptor->PinDescriptorsCount + 1) * sizeof(PVOID),
527                      This->Filter.Descriptor->PinDescriptorsCount * sizeof(PVOID),
528                      0);
529 
530     if (NT_SUCCESS(Status))
531     {
532         /* store process pin */
533         This->ProcessPinIndex[ProcessPin->Pin->Id].Pins[This->ProcessPinIndex[ProcessPin->Pin->Id].Count] = ProcessPin;
534         This->ProcessPinIndex[ProcessPin->Pin->Id].Count++;
535     }
536 
537     /* release process mutex */
538     KeReleaseMutex(&This->ProcessingMutex, FALSE);
539 
540     return Status;
541 }
542 
543 NTSTATUS
544 NTAPI
IKsFilter_fnRemoveProcessPin(IKsFilter * iface,IN PKSPROCESSPIN ProcessPin)545 IKsFilter_fnRemoveProcessPin(
546     IKsFilter * iface,
547     IN PKSPROCESSPIN ProcessPin)
548 {
549     ULONG Index;
550     ULONG Count;
551     PKSPROCESSPIN * Pins;
552 
553     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
554 
555     /* first acquire processing mutex */
556     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
557 
558     /* sanity check */
559     ASSERT(ProcessPin->Pin);
560     ASSERT(ProcessPin->Pin->Id);
561 
562     Count = This->ProcessPinIndex[ProcessPin->Pin->Id].Count;
563     Pins =  This->ProcessPinIndex[ProcessPin->Pin->Id].Pins;
564 
565     /* search for current process pin */
566     for(Index = 0; Index < Count; Index++)
567     {
568         if (Pins[Index] == ProcessPin)
569         {
570             RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PVOID));
571             break;
572         }
573 
574     }
575 
576     /* decrement pin count */
577     This->ProcessPinIndex[ProcessPin->Pin->Id].Count--;
578 
579     if (!This->ProcessPinIndex[ProcessPin->Pin->Id].Count)
580     {
581         /* clear entry object bag will delete it */
582        This->ProcessPinIndex[ProcessPin->Pin->Id].Pins = NULL;
583     }
584 
585     /* release process mutex */
586     KeReleaseMutex(&This->ProcessingMutex, FALSE);
587 
588     /* done */
589     return STATUS_SUCCESS;
590 }
591 
592 BOOL
593 NTAPI
IKsFilter_fnReprepareProcessPipeSection(IKsFilter * iface,IN struct KSPROCESSPIPESECTION * PipeSection,IN PULONG Data)594 IKsFilter_fnReprepareProcessPipeSection(
595     IKsFilter * iface,
596     IN struct KSPROCESSPIPESECTION *PipeSection,
597     IN PULONG Data)
598 {
599     UNIMPLEMENTED;
600     return FALSE;
601 }
602 
603 VOID
604 NTAPI
IKsFilter_fnDeliverResetState(IKsFilter * iface,IN struct KSPROCESSPIPESECTION * PipeSection,IN KSRESET ResetState)605 IKsFilter_fnDeliverResetState(
606     IKsFilter * iface,
607     IN struct KSPROCESSPIPESECTION *PipeSection,
608     IN KSRESET ResetState)
609 {
610     UNIMPLEMENTED;
611 }
612 
613 BOOL
614 NTAPI
IKsFilter_fnIsFrameHolding(IKsFilter * iface)615 IKsFilter_fnIsFrameHolding(
616     IKsFilter * iface)
617 {
618     UNIMPLEMENTED;
619     return FALSE;
620 }
621 
622 VOID
623 NTAPI
IKsFilter_fnRegisterForCopyCallbacks(IKsFilter * iface,IKsQueue * Queue,BOOL Register)624 IKsFilter_fnRegisterForCopyCallbacks(
625     IKsFilter * iface,
626     IKsQueue *Queue,
627     BOOL Register)
628 {
629     UNIMPLEMENTED;
630 }
631 
632 PKSPROCESSPIN_INDEXENTRY
633 NTAPI
IKsFilter_fnGetProcessDispatch(IKsFilter * iface)634 IKsFilter_fnGetProcessDispatch(
635     IKsFilter * iface)
636 {
637     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, Header.OuterUnknown);
638 
639     return This->ProcessPinIndex;
640 }
641 
642 static IKsFilterVtbl vt_IKsFilter =
643 {
644     IKsFilter_fnQueryInterface,
645     IKsFilter_fnAddRef,
646     IKsFilter_fnRelease,
647     IKsFilter_fnGetStruct,
648     IKsFilter_fnDoAllNecessaryPinsExist,
649     IKsFilter_fnCreateNode,
650     IKsFilter_fnBindProcessPinsToPipeSection,
651     IKsFilter_fnUnbindProcessPinsFromPipeSection,
652     IKsFilter_fnAddProcessPin,
653     IKsFilter_fnRemoveProcessPin,
654     IKsFilter_fnReprepareProcessPipeSection,
655     IKsFilter_fnDeliverResetState,
656     IKsFilter_fnIsFrameHolding,
657     IKsFilter_fnRegisterForCopyCallbacks,
658     IKsFilter_fnGetProcessDispatch
659 };
660 
661 NTSTATUS
IKsFilter_GetFilterFromIrp(IN PIRP Irp,OUT IKsFilter ** Filter)662 IKsFilter_GetFilterFromIrp(
663     IN PIRP Irp,
664     OUT IKsFilter **Filter)
665 {
666     PIO_STACK_LOCATION IoStack;
667     PKSIOBJECT_HEADER ObjectHeader;
668     NTSTATUS Status;
669 
670     /* get current irp stack */
671     IoStack = IoGetCurrentIrpStackLocation(Irp);
672 
673     /* sanity check */
674     ASSERT(IoStack->FileObject != NULL);
675 
676     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
677 
678     /* sanity is important */
679     ASSERT(ObjectHeader != NULL);
680     ASSERT(ObjectHeader->Type == KsObjectTypeFilter);
681     ASSERT(ObjectHeader->Unknown != NULL);
682 
683     /* get our private interface */
684     Status = ObjectHeader->Unknown->lpVtbl->QueryInterface(ObjectHeader->Unknown, &IID_IKsFilter, (PVOID*)Filter);
685 
686     if (!NT_SUCCESS(Status))
687     {
688         /* something is wrong here */
689         DPRINT1("KS: Misbehaving filter %p\n", ObjectHeader->Unknown);
690         Irp->IoStatus.Status = Status;
691 
692         /* complete and forget irp */
693         CompleteRequest(Irp, IO_NO_INCREMENT);
694         return Status;
695     }
696     return Status;
697 }
698 
699 
700 NTSTATUS
701 NTAPI
IKsFilter_DispatchClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)702 IKsFilter_DispatchClose(
703     IN PDEVICE_OBJECT DeviceObject,
704     IN PIRP Irp)
705 {
706     IKsFilter * Filter;
707     IKsFilterImpl * This;
708     NTSTATUS Status;
709 
710     /* obtain filter from object header */
711     Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
712     if (!NT_SUCCESS(Status))
713         return Status;
714 
715     /* get our real implementation */
716     This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
717 
718     /* does the driver support notifications */
719     if (This->Filter.Descriptor && This->Filter.Descriptor->Dispatch && This->Filter.Descriptor->Dispatch->Close)
720     {
721         /* call driver's filter close function */
722         Status = This->Filter.Descriptor->Dispatch->Close(&This->Filter, Irp);
723     }
724 
725     if (NT_SUCCESS(Status) && Status != STATUS_PENDING)
726     {
727         /* save the result */
728         Irp->IoStatus.Status = Status;
729         /* complete irp */
730         CompleteRequest(Irp, IO_NO_INCREMENT);
731 
732         /* remove our instance from the filter factory */
733         IKsFilter_RemoveFilterFromFilterFactory(This, This->Factory);
734 
735         /* free object header */
736         KsFreeObjectHeader(This->ObjectHeader);
737     }
738     else
739     {
740         /* complete and forget */
741         Irp->IoStatus.Status = Status;
742         /* complete irp */
743         CompleteRequest(Irp, IO_NO_INCREMENT);
744     }
745 
746     /* done */
747     return Status;
748 }
749 
750 NTSTATUS
KspHandlePropertyInstances(IN PIO_STATUS_BLOCK IoStatus,IN PKSIDENTIFIER Request,IN OUT PVOID Data,IN IKsFilterImpl * This,IN BOOL Global)751 KspHandlePropertyInstances(
752     IN PIO_STATUS_BLOCK IoStatus,
753     IN PKSIDENTIFIER  Request,
754     IN OUT PVOID  Data,
755     IN IKsFilterImpl * This,
756     IN BOOL Global)
757 {
758     KSPIN_CINSTANCES * Instances;
759     KSP_PIN * Pin = (KSP_PIN*)Request;
760 
761     if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
762     {
763         /* no filter / pin descriptor */
764         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
765         return STATUS_NOT_IMPLEMENTED;
766     }
767 
768     /* ignore custom structs for now */
769     ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
770     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
771 
772     Instances = (KSPIN_CINSTANCES*)Data;
773     /* max instance count */
774     Instances->PossibleCount = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesPossible;
775     /* current instance count */
776     Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
777 
778     IoStatus->Information = sizeof(KSPIN_CINSTANCES);
779     IoStatus->Status = STATUS_SUCCESS;
780     return STATUS_SUCCESS;
781 }
782 
783 NTSTATUS
KspHandleNecessaryPropertyInstances(IN PIO_STATUS_BLOCK IoStatus,IN PKSIDENTIFIER Request,IN OUT PVOID Data,IN IKsFilterImpl * This)784 KspHandleNecessaryPropertyInstances(
785     IN PIO_STATUS_BLOCK IoStatus,
786     IN PKSIDENTIFIER  Request,
787     IN OUT PVOID  Data,
788     IN IKsFilterImpl * This)
789 {
790     PULONG Result;
791     KSP_PIN * Pin = (KSP_PIN*)Request;
792 
793     if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
794     {
795         /* no filter / pin descriptor */
796         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
797         return STATUS_NOT_IMPLEMENTED;
798     }
799 
800     /* ignore custom structs for now */
801     ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
802     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
803 
804     Result = (PULONG)Data;
805     *Result = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
806 
807     IoStatus->Information = sizeof(ULONG);
808     IoStatus->Status = STATUS_SUCCESS;
809     return STATUS_SUCCESS;
810 }
811 
812 NTSTATUS
KspHandleDataIntersection(IN PIRP Irp,IN PIO_STATUS_BLOCK IoStatus,IN PKSIDENTIFIER Request,IN OUT PVOID Data,IN ULONG DataLength,IN IKsFilterImpl * This)813 KspHandleDataIntersection(
814     IN PIRP Irp,
815     IN PIO_STATUS_BLOCK IoStatus,
816     IN PKSIDENTIFIER Request,
817     IN OUT PVOID  Data,
818     IN ULONG DataLength,
819     IN IKsFilterImpl * This)
820 {
821     PKSMULTIPLE_ITEM MultipleItem;
822     PKSDATARANGE DataRange;
823     NTSTATUS Status = STATUS_NO_MATCH;
824     ULONG Index, Length;
825     PIO_STACK_LOCATION IoStack;
826     KSP_PIN * Pin = (KSP_PIN*)Request;
827 
828     /* get stack location */
829     IoStack = IoGetCurrentIrpStackLocation(Irp);
830 
831     /* sanity check */
832     ASSERT(DataLength == IoStack->Parameters.DeviceIoControl.OutputBufferLength);
833 
834     /* Access parameters */
835     MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
836     DataRange = (PKSDATARANGE)(MultipleItem + 1);
837 
838     /* FIXME make sure its 64 bit aligned */
839     ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
840 
841     if (!This->Filter.Descriptor || !This->Filter.Descriptor->PinDescriptorsCount)
842     {
843         /* no filter / pin descriptor */
844         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
845         return STATUS_NOT_IMPLEMENTED;
846     }
847 
848     /* ignore custom structs for now */
849     ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
850     ASSERT(This->Filter.Descriptor->PinDescriptorsCount > Pin->PinId);
851 
852     if (This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
853         This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
854         This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0)
855     {
856         /* no driver supported intersect handler / no provided data ranges */
857         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
858         return STATUS_NOT_IMPLEMENTED;
859     }
860 
861     for(Index = 0; Index < MultipleItem->Count; Index++)
862     {
863         UNICODE_STRING MajorFormat, SubFormat, Specifier;
864         /* convert the guid to string */
865         RtlStringFromGUID(&DataRange->MajorFormat, &MajorFormat);
866         RtlStringFromGUID(&DataRange->SubFormat, &SubFormat);
867         RtlStringFromGUID(&DataRange->Specifier, &Specifier);
868 
869         DPRINT("KspHandleDataIntersection Index %lu PinId %lu MajorFormat %S SubFormat %S Specifier %S FormatSize %lu SampleSize %lu Align %lu Flags %lx Reserved %lx DataLength %lu\n", Index, Pin->PinId, MajorFormat.Buffer, SubFormat.Buffer, Specifier.Buffer,
870                DataRange->FormatSize, DataRange->SampleSize, DataRange->Alignment, DataRange->Flags, DataRange->Reserved, DataLength);
871 
872         /* FIXME implement KsPinDataIntersectionEx */
873         /* Call miniport's proprietary handler */
874         Status = This->Filter.Descriptor->PinDescriptors[Pin->PinId].IntersectHandler(&This->Filter,
875                                                                                       Irp,
876                                                                                       Pin,
877                                                                                       DataRange,
878                                                                                       This->Filter.Descriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges[0], /* HACK */
879                                                                                       DataLength,
880                                                                                       Data,
881                                                                                       &Length);
882         DPRINT("KspHandleDataIntersection Status %lx\n", Status);
883 
884         if (Status == STATUS_SUCCESS || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
885         {
886             ASSERT(Length);
887             IoStatus->Information = Length;
888             break;
889         }
890 
891         DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize);
892         /* FIXME make sure its 64 bit aligned */
893         ASSERT(((ULONG_PTR)DataRange & 0x7) == 0);
894     }
895     IoStatus->Status = Status;
896     return Status;
897 }
898 
899 NTSTATUS
900 NTAPI
FilterTopologyPropertyHandler(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)901 FilterTopologyPropertyHandler(
902     IN PIRP Irp,
903     IN PKSIDENTIFIER  Request,
904     IN OUT PVOID  Data)
905 {
906     IKsFilterImpl * This;
907 
908     /* get filter implementation */
909     This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
910 
911     /* sanity check */
912     ASSERT(This);
913 
914     return KsTopologyPropertyHandler(Irp, Request, Data, &This->Topology);
915 
916 }
917 
918 NTSTATUS
919 NTAPI
FilterGeneralComponentIdHandler(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)920 FilterGeneralComponentIdHandler(
921     IN PIRP Irp,
922     IN PKSIDENTIFIER  Request,
923     IN OUT PVOID  Data)
924 {
925     PIO_STACK_LOCATION IoStack;
926     IKsFilterImpl * This;
927 
928     /* get filter implementation */
929     This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
930 
931     /* sanity check */
932     ASSERT(This);
933 
934     /* get current stack location */
935     IoStack = IoGetCurrentIrpStackLocation(Irp);
936     ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSCOMPONENTID));
937 
938     if (This->Filter.Descriptor->ComponentId != NULL)
939     {
940         RtlMoveMemory(Data, This->Filter.Descriptor->ComponentId, sizeof(KSCOMPONENTID));
941         Irp->IoStatus.Information = sizeof(KSCOMPONENTID);
942         return STATUS_SUCCESS;
943     }
944     else
945     {
946         /* not valid */
947         return STATUS_NOT_FOUND;
948     }
949 
950 }
951 
952 NTSTATUS
953 NTAPI
FilterPinPropertyHandler(IN PIRP Irp,IN PKSIDENTIFIER Request,IN OUT PVOID Data)954 FilterPinPropertyHandler(
955     IN PIRP Irp,
956     IN PKSIDENTIFIER  Request,
957     IN OUT PVOID  Data)
958 {
959     PIO_STACK_LOCATION IoStack;
960     IKsFilterImpl * This;
961     NTSTATUS Status = STATUS_UNSUCCESSFUL;
962 
963     /* get filter implementation */
964     This = (IKsFilterImpl*)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
965 
966     /* sanity check */
967     ASSERT(This);
968 
969     /* get current stack location */
970     IoStack = IoGetCurrentIrpStackLocation(Irp);
971 
972     switch(Request->Id)
973     {
974         case KSPROPERTY_PIN_CTYPES:
975         case KSPROPERTY_PIN_DATAFLOW:
976         case KSPROPERTY_PIN_DATARANGES:
977         case KSPROPERTY_PIN_INTERFACES:
978         case KSPROPERTY_PIN_MEDIUMS:
979         case KSPROPERTY_PIN_COMMUNICATION:
980         case KSPROPERTY_PIN_CATEGORY:
981         case KSPROPERTY_PIN_NAME:
982         case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
983             Status = KspPinPropertyHandler(Irp, Request, Data, This->Filter.Descriptor->PinDescriptorsCount, (const KSPIN_DESCRIPTOR*)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize);
984             break;
985         case KSPROPERTY_PIN_GLOBALCINSTANCES:
986             Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, TRUE);
987             break;
988         case KSPROPERTY_PIN_CINSTANCES:
989             Status = KspHandlePropertyInstances(&Irp->IoStatus, Request, Data, This, FALSE);
990             break;
991         case KSPROPERTY_PIN_NECESSARYINSTANCES:
992             Status = KspHandleNecessaryPropertyInstances(&Irp->IoStatus, Request, Data, This);
993             break;
994 
995         case KSPROPERTY_PIN_DATAINTERSECTION:
996             Status = KspHandleDataIntersection(Irp, &Irp->IoStatus, Request, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This);
997             break;
998         default:
999             UNIMPLEMENTED;
1000             Status = STATUS_NOT_FOUND;
1001     }
1002     DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->Filter.Descriptor->PinDescriptorsCount, Request->Id, Status);
1003 
1004 
1005     return Status;
1006 }
1007 
1008 NTSTATUS
1009 NTAPI
IKsFilter_DispatchDeviceIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1010 IKsFilter_DispatchDeviceIoControl(
1011     IN PDEVICE_OBJECT DeviceObject,
1012     IN PIRP Irp)
1013 {
1014     PIO_STACK_LOCATION IoStack;
1015     IKsFilter * Filter;
1016     IKsFilterImpl * This;
1017     NTSTATUS Status;
1018     PKSFILTER FilterInstance;
1019     UNICODE_STRING GuidString;
1020     PKSPROPERTY Property;
1021     ULONG SetCount = 0;
1022     PKSP_NODE NodeProperty;
1023     PKSNODE_DESCRIPTOR NodeDescriptor;
1024 
1025     /* obtain filter from object header */
1026     Status = IKsFilter_GetFilterFromIrp(Irp, &Filter);
1027     if (!NT_SUCCESS(Status))
1028         return Status;
1029 
1030     /* get our real implementation */
1031     This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Header.OuterUnknown);
1032 
1033     /* current irp stack */
1034     IoStack = IoGetCurrentIrpStackLocation(Irp);
1035 
1036     /* get property from input buffer */
1037     Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
1038 
1039     /* get filter instance */
1040     FilterInstance = Filter->lpVtbl->GetStruct(Filter);
1041 
1042     /* sanity check */
1043     ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSIDENTIFIER));
1044     ASSERT(FilterInstance);
1045     ASSERT(FilterInstance->Descriptor);
1046     ASSERT(FilterInstance->Descriptor->AutomationTable);
1047 
1048     /* acquire control mutex */
1049     KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
1050 
1051     if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_METHOD)
1052     {
1053         const KSMETHOD_SET *MethodSet = NULL;
1054         ULONG MethodItemSize = 0;
1055 
1056         /* check if the driver supports method sets */
1057         if (FilterInstance->Descriptor->AutomationTable->MethodSetsCount)
1058         {
1059             SetCount = FilterInstance->Descriptor->AutomationTable->MethodSetsCount;
1060             MethodSet = FilterInstance->Descriptor->AutomationTable->MethodSets;
1061             MethodItemSize = FilterInstance->Descriptor->AutomationTable->MethodItemSize;
1062         }
1063 
1064         /* call method set handler */
1065         Status = KspMethodHandlerWithAllocator(Irp, SetCount, MethodSet, NULL, MethodItemSize);
1066     }
1067     else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
1068     {
1069         const KSPROPERTY_SET *PropertySet = NULL;
1070         ULONG PropertyItemSize = 0;
1071 
1072         /* check if the driver supports method sets */
1073         if (Property->Flags & KSPROPERTY_TYPE_TOPOLOGY)
1074         {
1075             ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSP_NODE));
1076             NodeProperty = (PKSP_NODE)Property;
1077             NodeDescriptor = (PKSNODE_DESCRIPTOR)((ULONG_PTR)FilterInstance->Descriptor->NodeDescriptors + FilterInstance->Descriptor->NodeDescriptorSize * NodeProperty->NodeId);
1078             if (NodeDescriptor->AutomationTable != NULL)
1079             {
1080                 SetCount = NodeDescriptor->AutomationTable->PropertySetsCount;
1081                 PropertySet = NodeDescriptor->AutomationTable->PropertySets;
1082                 PropertyItemSize = 0;
1083             }
1084         }
1085         else if (FilterInstance->Descriptor->AutomationTable->PropertySetsCount)
1086         {
1087             SetCount = FilterInstance->Descriptor->AutomationTable->PropertySetsCount;
1088             PropertySet = FilterInstance->Descriptor->AutomationTable->PropertySets;
1089             PropertyItemSize = FilterInstance->Descriptor->AutomationTable->PropertyItemSize;
1090             // FIXME: handle variable sized property items
1091             ASSERT(PropertyItemSize == sizeof(KSPROPERTY_ITEM));
1092             PropertyItemSize = 0;
1093         }
1094 
1095         /* needed for our property handlers */
1096         KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
1097 
1098         /* call property handler */
1099         Status = KspPropertyHandler(Irp, SetCount, PropertySet, NULL, PropertyItemSize);
1100     }
1101     else
1102     {
1103         /* sanity check */
1104         ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT ||
1105                IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT);
1106 
1107         if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
1108         {
1109             /* call enable event handlers */
1110             Status = KspEnableEvent(Irp,
1111                                     FilterInstance->Descriptor->AutomationTable->EventSetsCount,
1112                                     (PKSEVENT_SET)FilterInstance->Descriptor->AutomationTable->EventSets,
1113                                     &This->Header.EventList,
1114                                     KSEVENTS_SPINLOCK,
1115                                     (PVOID)&This->Header.EventListLock,
1116                                     NULL,
1117                                     FilterInstance->Descriptor->AutomationTable->EventItemSize);
1118         }
1119         else
1120         {
1121             /* disable event handler */
1122             Status = KsDisableEvent(Irp, &This->Header.EventList, KSEVENTS_SPINLOCK, &This->Header.EventListLock);
1123         }
1124     }
1125 
1126     RtlStringFromGUID(&Property->Set, &GuidString);
1127     DPRINT("IKsFilter_DispatchDeviceIoControl property PinCount %x\n", FilterInstance->Descriptor->PinDescriptorsCount);
1128     DPRINT("IKsFilter_DispatchDeviceIoControl property Set |%S| Id %u Flags %x Status %lx ResultLength %lu\n", GuidString.Buffer, Property->Id, Property->Flags, Status, Irp->IoStatus.Information);
1129     RtlFreeUnicodeString(&GuidString);
1130 
1131     /* release filter */
1132     Filter->lpVtbl->Release(Filter);
1133 
1134     /* release control mutex */
1135     KeReleaseMutex(This->Header.ControlMutex, FALSE);
1136 
1137     if (Status != STATUS_PENDING)
1138     {
1139         Irp->IoStatus.Status = Status;
1140         CompleteRequest(Irp, IO_NO_INCREMENT);
1141     }
1142 
1143     /* done */
1144     return Status;
1145 }
1146 
1147 static KSDISPATCH_TABLE DispatchTable =
1148 {
1149     IKsFilter_DispatchDeviceIoControl,
1150     KsDispatchInvalidDeviceRequest,
1151     KsDispatchInvalidDeviceRequest,
1152     KsDispatchInvalidDeviceRequest,
1153     IKsFilter_DispatchClose,
1154     KsDispatchQuerySecurity,
1155     KsDispatchSetSecurity,
1156     KsDispatchFastIoDeviceControlFailure,
1157     KsDispatchFastReadFailure,
1158     KsDispatchFastReadFailure,
1159 };
1160 
1161 
1162 NTSTATUS
IKsFilter_CreateDescriptors(IKsFilterImpl * This,KSFILTER_DESCRIPTOR * FilterDescriptor)1163 IKsFilter_CreateDescriptors(
1164     IKsFilterImpl * This,
1165     KSFILTER_DESCRIPTOR* FilterDescriptor)
1166 {
1167     ULONG Index = 0;
1168     NTSTATUS Status;
1169     PKSNODE_DESCRIPTOR NodeDescriptor;
1170 
1171     /* initialize pin descriptors */
1172     This->FirstPin = NULL;
1173     This->PinInstanceCount = NULL;
1174     This->ProcessPinIndex = NULL;
1175 
1176     /* initialize topology descriptor */
1177     This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
1178     This->Topology.Categories = FilterDescriptor->Categories;
1179     This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
1180     This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
1181     This->Topology.TopologyConnections = FilterDescriptor->Connections;
1182 
1183     /* are there any templates */
1184     if (FilterDescriptor->PinDescriptorsCount)
1185     {
1186         /* sanity check */
1187         ASSERT(FilterDescriptor->PinDescriptors);
1188 
1189         /* FIXME handle variable sized pin descriptors */
1190         ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
1191 
1192         /* store pin descriptors ex */
1193         Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount,
1194                          FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount, 0);
1195 
1196         if (!NT_SUCCESS(Status))
1197         {
1198             DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1199             return Status;
1200         }
1201 
1202         /* store pin instance count */
1203         Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount,
1204                          sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0);
1205 
1206         if (!NT_SUCCESS(Status))
1207         {
1208             DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1209             return Status;
1210         }
1211 
1212         /* store instantiated pin arrays */
1213         Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount,
1214                          sizeof(PVOID) * FilterDescriptor->PinDescriptorsCount, 0);
1215 
1216         if (!NT_SUCCESS(Status))
1217         {
1218             DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1219             return Status;
1220         }
1221 
1222         /* add new pin factory */
1223         RtlMoveMemory((PVOID)This->Filter.Descriptor->PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount);
1224 
1225         /* allocate process pin index */
1226         Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount,
1227                          sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, 0);
1228 
1229         if (!NT_SUCCESS(Status))
1230         {
1231             DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
1232             return Status;
1233         }
1234 
1235     }
1236 
1237 
1238     if (FilterDescriptor->ConnectionsCount)
1239     {
1240         /* modify connections array */
1241         Status = _KsEdit(This->Filter.Bag,
1242                         (PVOID*)&This->Filter.Descriptor->Connections,
1243                          FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1244                          FilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1245                          0);
1246 
1247        This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
1248        This->Topology.TopologyConnectionsCount = ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount = FilterDescriptor->ConnectionsCount;
1249     }
1250 
1251     if (FilterDescriptor->NodeDescriptorsCount)
1252     {
1253         /* sanity check */
1254         ASSERT(FilterDescriptor->NodeDescriptors);
1255 
1256         /* sanity check */
1257         ASSERT(FilterDescriptor->NodeDescriptorSize >= sizeof(KSNODE_DESCRIPTOR));
1258 
1259         This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
1260         /* allocate topology node types array */
1261         if (!This->Topology.TopologyNodes)
1262         {
1263             DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1264             return STATUS_INSUFFICIENT_RESOURCES;
1265         }
1266 
1267         This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount);
1268         /* allocate topology names array */
1269         if (!This->Topology.TopologyNodesNames)
1270         {
1271             FreeItem((PVOID)This->Topology.TopologyNodes);
1272             DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1273             return STATUS_INSUFFICIENT_RESOURCES;
1274         }
1275 
1276         DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount);
1277         NodeDescriptor = (PKSNODE_DESCRIPTOR)FilterDescriptor->NodeDescriptors;
1278         for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++)
1279         {
1280             DPRINT("Index %lu Type %p Name %p\n", Index, NodeDescriptor->Type, NodeDescriptor->Name);
1281 
1282             /* copy topology type */
1283             if (NodeDescriptor->Type)
1284                 RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
1285 
1286             /* copy topology name */
1287             if (NodeDescriptor->Name)
1288                 RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
1289 
1290             // next node descriptor
1291             NodeDescriptor = (PKSNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescriptor->NodeDescriptorSize);
1292         }
1293     }
1294     /* done! */
1295     return STATUS_SUCCESS;
1296 }
1297 
1298 NTSTATUS
IKsFilter_CopyFilterDescriptor(IKsFilterImpl * This,const KSFILTER_DESCRIPTOR * FilterDescriptor)1299 IKsFilter_CopyFilterDescriptor(
1300     IKsFilterImpl * This,
1301     const KSFILTER_DESCRIPTOR* FilterDescriptor)
1302 {
1303     NTSTATUS Status;
1304     KSAUTOMATION_TABLE AutomationTable;
1305 
1306     This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
1307     if (!This->Filter.Descriptor)
1308         return STATUS_INSUFFICIENT_RESOURCES;
1309 
1310     Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
1311     if (!NT_SUCCESS(Status))
1312     {
1313         FreeItem((PVOID)This->Filter.Descriptor);
1314         This->Filter.Descriptor = NULL;
1315         return STATUS_INSUFFICIENT_RESOURCES;
1316     }
1317 
1318     /* copy filter descriptor fields */
1319     RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
1320 
1321     /* zero automation table */
1322     RtlZeroMemory(&AutomationTable, sizeof(KSAUTOMATION_TABLE));
1323 
1324     /* setup filter property sets */
1325     AutomationTable.PropertyItemSize = sizeof(KSPROPERTY_ITEM);
1326     AutomationTable.PropertySetsCount = 3;
1327     AutomationTable.PropertySets = FilterPropertySet;
1328 
1329     /* merge filter automation table */
1330     Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&This->Filter.Descriptor->AutomationTable, (PKSAUTOMATION_TABLE)FilterDescriptor->AutomationTable, &AutomationTable, This->Filter.Bag);
1331 
1332     return Status;
1333 }
1334 
1335 
1336 VOID
IKsFilter_AddPin(PKSFILTER Filter,PKSPIN Pin)1337 IKsFilter_AddPin(
1338     PKSFILTER Filter,
1339     PKSPIN Pin)
1340 {
1341     PKSPIN NextPin, CurPin;
1342     PKSBASIC_HEADER BasicHeader;
1343     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1344 
1345     /* sanity check */
1346     ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
1347 
1348     if (This->FirstPin[Pin->Id] == NULL)
1349     {
1350         /* welcome first pin */
1351         This->FirstPin[Pin->Id] = Pin;
1352         This->PinInstanceCount[Pin->Id]++;
1353         return;
1354     }
1355 
1356     /* get first pin */
1357     CurPin = This->FirstPin[Pin->Id];
1358 
1359     do
1360     {
1361         /* get next instantiated pin */
1362         NextPin = KsPinGetNextSiblingPin(CurPin);
1363         if (!NextPin)
1364             break;
1365 
1366         NextPin = CurPin;
1367 
1368     }while(NextPin != NULL);
1369 
1370     /* get basic header */
1371     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)CurPin - sizeof(KSBASIC_HEADER));
1372 
1373     /* store pin */
1374     BasicHeader->Next.Pin = Pin;
1375 }
1376 
1377 VOID
IKsFilter_RemovePin(PKSFILTER Filter,PKSPIN Pin)1378 IKsFilter_RemovePin(
1379     PKSFILTER Filter,
1380     PKSPIN Pin)
1381 {
1382     PKSPIN NextPin, CurPin, LastPin;
1383     PKSBASIC_HEADER BasicHeader;
1384     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1385 
1386     /* sanity check */
1387     ASSERT(Pin->Id < This->Filter.Descriptor->PinDescriptorsCount);
1388 
1389     /* get first pin */
1390     CurPin = This->FirstPin[Pin->Id];
1391 
1392     LastPin = NULL;
1393     do
1394     {
1395         /* get next instantiated pin */
1396         NextPin = KsPinGetNextSiblingPin(CurPin);
1397 
1398         if (CurPin == Pin)
1399         {
1400             if (LastPin)
1401             {
1402                 /* get basic header of last pin */
1403                 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastPin - sizeof(KSBASIC_HEADER));
1404 
1405                 BasicHeader->Next.Pin = NextPin;
1406             }
1407             else
1408             {
1409                 /* erase last pin */
1410                 This->FirstPin[Pin->Id] = NextPin;
1411             }
1412             /* decrement pin instance count */
1413             This->PinInstanceCount[Pin->Id]--;
1414             return;
1415         }
1416 
1417         if (!NextPin)
1418             break;
1419 
1420         LastPin = CurPin;
1421         NextPin = CurPin;
1422 
1423     }while(NextPin != NULL);
1424 
1425     /* pin not found */
1426     ASSERT(0);
1427 }
1428 
1429 
1430 NTSTATUS
1431 NTAPI
IKsFilter_DispatchCreatePin(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1432 IKsFilter_DispatchCreatePin(
1433     IN PDEVICE_OBJECT DeviceObject,
1434     IN PIRP Irp)
1435 {
1436     IKsFilterImpl * This;
1437     PKSOBJECT_CREATE_ITEM CreateItem;
1438     PKSPIN_CONNECT Connect;
1439     NTSTATUS Status;
1440 
1441     DPRINT("IKsFilter_DispatchCreatePin\n");
1442 
1443     /* get the create item */
1444     CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
1445 
1446     /* get the filter object */
1447     This = (IKsFilterImpl*)CreateItem->Context;
1448 
1449     /* sanity check */
1450     ASSERT(This->Header.Type == KsObjectTypeFilter);
1451 
1452     /* acquire control mutex */
1453     KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
1454 
1455     /* now validate the connect request */
1456     Status = KspValidateConnectRequest(Irp, This->Filter.Descriptor->PinDescriptorsCount, (PVOID)This->Filter.Descriptor->PinDescriptors, This->Filter.Descriptor->PinDescriptorSize, &Connect);
1457 
1458     DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status);
1459 
1460     if (NT_SUCCESS(Status))
1461     {
1462         /* sanity check */
1463         ASSERT(Connect->PinId < This->Filter.Descriptor->PinDescriptorsCount);
1464 
1465         DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId,
1466                This->PinInstanceCount[Connect->PinId],
1467                This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible);
1468 
1469         if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible)
1470         {
1471             /* create the pin */
1472             Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->Header.OuterUnknown, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]);
1473 
1474             DPRINT("IKsFilter_DispatchCreatePin  KspCreatePin %lx\n", Status);
1475         }
1476         else
1477         {
1478             /* maximum instance count reached, bye-bye */
1479             Status = STATUS_UNSUCCESSFUL;
1480             DPRINT("IKsFilter_DispatchCreatePin  MaxInstance %lu CurInstance %lu %lx\n", This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]);
1481         }
1482     }
1483 
1484     /* release control mutex */
1485     KeReleaseMutex(This->Header.ControlMutex, FALSE);
1486 
1487     if (Status != STATUS_PENDING)
1488     {
1489         /* complete request */
1490         Irp->IoStatus.Status = Status;
1491         CompleteRequest(Irp, IO_NO_INCREMENT);
1492     }
1493 
1494     /* done */
1495     DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
1496     return Status;
1497 }
1498 
1499 NTSTATUS
1500 NTAPI
IKsFilter_DispatchCreateNode(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)1501 IKsFilter_DispatchCreateNode(
1502     IN PDEVICE_OBJECT DeviceObject,
1503     IN PIRP Irp)
1504 {
1505     UNIMPLEMENTED;
1506     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1507     CompleteRequest(Irp, IO_NO_INCREMENT);
1508     return STATUS_UNSUCCESSFUL;
1509 }
1510 
1511 
1512 VOID
IKsFilter_AttachFilterToFilterFactory(IKsFilterImpl * This,PKSFILTERFACTORY FilterFactory)1513 IKsFilter_AttachFilterToFilterFactory(
1514     IKsFilterImpl * This,
1515     PKSFILTERFACTORY FilterFactory)
1516 {
1517     PKSBASIC_HEADER BasicHeader;
1518     PKSFILTER Filter;
1519 
1520 
1521     /* get filter factory basic header */
1522     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1523 
1524     /* sanity check */
1525     ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1526 
1527     if (BasicHeader->FirstChild.FilterFactory == NULL)
1528     {
1529         /* welcome first instantiated filter */
1530         BasicHeader->FirstChild.Filter = &This->Filter;
1531         return;
1532     }
1533 
1534     /* set to first entry */
1535     Filter = BasicHeader->FirstChild.Filter;
1536 
1537     do
1538     {
1539         /* get basic header */
1540         BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1541         /* sanity check */
1542         ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1543 
1544         if (BasicHeader->Next.Filter)
1545         {
1546             /* iterate to next filter factory */
1547             Filter = BasicHeader->Next.Filter;
1548         }
1549         else
1550         {
1551             /* found last entry */
1552             break;
1553         }
1554     }while(TRUE);
1555 
1556     /* attach filter factory */
1557     BasicHeader->Next.Filter = &This->Filter;
1558 }
1559 
1560 VOID
IKsFilter_RemoveFilterFromFilterFactory(IKsFilterImpl * This,PKSFILTERFACTORY FilterFactory)1561 IKsFilter_RemoveFilterFromFilterFactory(
1562     IKsFilterImpl * This,
1563     PKSFILTERFACTORY FilterFactory)
1564 {
1565     PKSBASIC_HEADER BasicHeader;
1566     PKSFILTER Filter, LastFilter;
1567 
1568     /* get filter factory basic header */
1569     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
1570 
1571     /* sanity check */
1572     ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
1573     ASSERT(BasicHeader->FirstChild.Filter != NULL);
1574 
1575 
1576     /* set to first entry */
1577     Filter = BasicHeader->FirstChild.Filter;
1578     LastFilter = NULL;
1579 
1580     do
1581     {
1582          if (Filter == &This->Filter)
1583          {
1584              if (LastFilter)
1585              {
1586                  /* get basic header */
1587                  BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)LastFilter - sizeof(KSBASIC_HEADER));
1588                  /* remove filter instance */
1589                  BasicHeader->Next.Filter = This->Header.Next.Filter;
1590                  break;
1591              }
1592              else
1593              {
1594                  /* remove filter instance */
1595                  BasicHeader->FirstChild.Filter = This->Header.Next.Filter;
1596                  break;
1597              }
1598          }
1599 
1600         /* get basic header */
1601         BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Filter - sizeof(KSBASIC_HEADER));
1602         /* sanity check */
1603         ASSERT(BasicHeader->Type == KsObjectTypeFilter);
1604 
1605         LastFilter = Filter;
1606         if (BasicHeader->Next.Filter)
1607         {
1608             /* iterate to next filter factory */
1609             Filter = BasicHeader->Next.Filter;
1610         }
1611         else
1612         {
1613             /* filter is not in list */
1614             ASSERT(0);
1615             break;
1616         }
1617     }while(TRUE);
1618 }
1619 
1620 VOID
1621 NTAPI
IKsFilter_FilterCentricWorker(IN PVOID Ctx)1622 IKsFilter_FilterCentricWorker(
1623     IN PVOID Ctx)
1624 {
1625     IKsProcessingObject * Object = (IKsProcessingObject*)Ctx;
1626 
1627     /* sanity check */
1628     ASSERT(Object);
1629 
1630     /* perform work */
1631     Object->lpVtbl->ProcessingObjectWork(Object);
1632 }
1633 
1634 NTSTATUS
1635 NTAPI
KspCreateFilter(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN IKsFilterFactory * iface)1636 KspCreateFilter(
1637     IN PDEVICE_OBJECT DeviceObject,
1638     IN PIRP Irp,
1639     IN IKsFilterFactory *iface)
1640 {
1641     IKsFilterImpl * This;
1642     IKsDevice *KsDevice;
1643     PKSFILTERFACTORY Factory;
1644     PIO_STACK_LOCATION IoStack;
1645     PDEVICE_EXTENSION DeviceExtension;
1646     NTSTATUS Status;
1647     PKSOBJECT_CREATE_ITEM CreateItem;
1648 
1649     /* get device extension */
1650     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
1651 
1652     /* get the filter factory */
1653     Factory = iface->lpVtbl->GetStruct(iface);
1654 
1655     if (!Factory || !Factory->FilterDescriptor)
1656     {
1657         /* Sorry it just will not work */
1658         return STATUS_UNSUCCESSFUL;
1659     }
1660 
1661     if (Factory->FilterDescriptor->Flags & KSFILTER_FLAG_DENY_USERMODE_ACCESS)
1662     {
1663         if (Irp->RequestorMode == UserMode)
1664         {
1665             /* filter not accessible from user mode */
1666             DPRINT1("Access denied\n");
1667             return STATUS_UNSUCCESSFUL;
1668         }
1669     }
1670 
1671     /* allocate filter instance */
1672     This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
1673     if (!This)
1674     {
1675         DPRINT1("KspCreateFilter OutOfMemory\n");
1676         return STATUS_INSUFFICIENT_RESOURCES;
1677     }
1678 
1679     /* initialize object bag */
1680     This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
1681     if (!This->Filter.Bag)
1682     {
1683         /* no memory */
1684         FreeItem(This);
1685         DPRINT1("KspCreateFilter OutOfMemory\n");
1686         return STATUS_INSUFFICIENT_RESOURCES;
1687     }
1688     KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
1689     KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
1690 
1691     /* copy filter descriptor */
1692     Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor);
1693     if (!NT_SUCCESS(Status))
1694     {
1695         /* not enough memory */
1696         FreeItem(This->Filter.Bag);
1697         FreeItem(This);
1698         DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status);
1699         return STATUS_INSUFFICIENT_RESOURCES;
1700     }
1701 
1702     /* get current irp stack */
1703     IoStack = IoGetCurrentIrpStackLocation(Irp);
1704 
1705     /* allocate create items */
1706     CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2);
1707     if (!CreateItem)
1708     {
1709         /* no memory */
1710         FreeItem(This->Filter.Bag);
1711         FreeItem(This);
1712         DPRINT1("KspCreateFilter OutOfMemory\n");
1713         return STATUS_INSUFFICIENT_RESOURCES;
1714     }
1715 
1716     /* initialize pin create item */
1717     CreateItem[0].Create = IKsFilter_DispatchCreatePin;
1718     CreateItem[0].Context = (PVOID)This;
1719     CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
1720     RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Pin);
1721     /* initialize node create item */
1722     CreateItem[1].Create = IKsFilter_DispatchCreateNode;
1723     CreateItem[1].Context = (PVOID)This;
1724     CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
1725     RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
1726 
1727 
1728     /* initialize filter instance */
1729     This->ref = 1;
1730     This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter;
1731     This->lpVtblKsControl = &vt_IKsControl;
1732     This->lpVtblKsProcessingObject = &vt_IKsProcessingObject;
1733 
1734     This->Factory = Factory;
1735     This->FilterFactory = iface;
1736     This->FileObject = IoStack->FileObject;
1737     KeInitializeMutex(&This->ProcessingMutex, 0);
1738 
1739     /* initialize basic header */
1740     This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
1741     This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
1742     This->Header.Type = KsObjectTypeFilter;
1743     This->Header.ControlMutex = &This->ControlMutex;
1744     KeInitializeMutex(This->Header.ControlMutex, 0);
1745     InitializeListHead(&This->Header.EventList);
1746     KeInitializeSpinLock(&This->Header.EventListLock);
1747 
1748     /* initialize and gate */
1749     KsGateInitializeAnd(&This->Gate, NULL);
1750 
1751     /* FIXME initialize and gate based on pin flags */
1752 
1753     /* initialize work item */
1754     ExInitializeWorkItem(&This->WorkItem, IKsFilter_FilterCentricWorker, (PVOID)This->lpVtblKsProcessingObject);
1755 
1756     /* allocate counted work item */
1757     Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->WorkItem, &This->Worker);
1758     if (!NT_SUCCESS(Status))
1759     {
1760         /* what can go wrong, goes wrong */
1761         DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status);
1762         FreeItem(This);
1763         FreeItem(CreateItem);
1764         return Status;
1765     }
1766 
1767     /* allocate the stream descriptors */
1768     Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
1769     if (!NT_SUCCESS(Status))
1770     {
1771         /* what can go wrong, goes wrong */
1772         DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status);
1773         KsUnregisterWorker(This->Worker);
1774         FreeItem(This);
1775         FreeItem(CreateItem);
1776         return Status;
1777     }
1778 
1779 
1780 
1781     /* does the filter have a filter dispatch */
1782     if (Factory->FilterDescriptor->Dispatch)
1783     {
1784         /* does it have a create routine */
1785         if (Factory->FilterDescriptor->Dispatch->Create)
1786         {
1787             /* now let driver initialize the filter instance */
1788 
1789             ASSERT(This->Header.KsDevice);
1790             ASSERT(This->Header.KsDevice->Started);
1791             Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
1792 
1793             if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
1794             {
1795                 /* driver failed to initialize */
1796                 DPRINT1("Driver: Status %x\n", Status);
1797 
1798                 /* free filter instance */
1799                 KsUnregisterWorker(This->Worker);
1800                 FreeItem(This);
1801                 FreeItem(CreateItem);
1802                 return Status;
1803             }
1804         }
1805     }
1806 
1807     /* now allocate the object header */
1808     Status = KsAllocateObjectHeader((PVOID*)&This->ObjectHeader, 2, CreateItem, Irp, &DispatchTable);
1809     if (!NT_SUCCESS(Status))
1810     {
1811         /* failed to allocate object header */
1812         DPRINT1("Failed to allocate object header %x\n", Status);
1813 
1814         return Status;
1815     }
1816 
1817     /* initialize object header extra fields */
1818     This->ObjectHeader->Type = KsObjectTypeFilter;
1819     This->ObjectHeader->Unknown = (PUNKNOWN)&This->Header.OuterUnknown;
1820     This->ObjectHeader->ObjectType = (PVOID)&This->Filter;
1821 
1822     /* attach filter to filter factory */
1823     IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
1824 
1825     /* completed initialization */
1826     DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
1827     return Status;
1828 }
1829 
1830 /*
1831     @implemented
1832 */
1833 KSDDKAPI
1834 VOID
1835 NTAPI
KsFilterAcquireProcessingMutex(IN PKSFILTER Filter)1836 KsFilterAcquireProcessingMutex(
1837     IN PKSFILTER Filter)
1838 {
1839     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1840 
1841     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
1842 }
1843 
1844 /*
1845     @implemented
1846 */
1847 KSDDKAPI
1848 VOID
1849 NTAPI
KsFilterReleaseProcessingMutex(IN PKSFILTER Filter)1850 KsFilterReleaseProcessingMutex(
1851     IN PKSFILTER Filter)
1852 {
1853     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1854 
1855     KeReleaseMutex(&This->ProcessingMutex, FALSE);
1856 }
1857 
1858 
1859 /*
1860     @implemented
1861 */
1862 KSDDKAPI
1863 NTSTATUS
1864 NTAPI
KsFilterAddTopologyConnections(IN PKSFILTER Filter,IN ULONG NewConnectionsCount,IN const KSTOPOLOGY_CONNECTION * const NewTopologyConnections)1865 KsFilterAddTopologyConnections (
1866     IN PKSFILTER Filter,
1867     IN ULONG NewConnectionsCount,
1868     IN const KSTOPOLOGY_CONNECTION *const NewTopologyConnections)
1869 {
1870     ULONG Count;
1871     NTSTATUS Status;
1872     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1873 
1874     DPRINT("KsFilterAddTopologyConnections\n");
1875 
1876     ASSERT(This->Filter.Descriptor);
1877     Count = This->Filter.Descriptor->ConnectionsCount + NewConnectionsCount;
1878 
1879 
1880     /* modify connections array */
1881     Status = _KsEdit(This->Filter.Bag,
1882                     (PVOID*)&This->Filter.Descriptor->Connections,
1883                      Count * sizeof(KSTOPOLOGY_CONNECTION),
1884                      This->Filter.Descriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION),
1885                      0);
1886 
1887     if (!NT_SUCCESS(Status))
1888     {
1889         /* failed */
1890         DPRINT("KsFilterAddTopologyConnections KsEdit failed with %lx\n", Status);
1891         return Status;
1892     }
1893 
1894     /* FIXME verify connections */
1895 
1896     /* copy new connections */
1897     RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections[This->Filter.Descriptor->ConnectionsCount],
1898                   NewTopologyConnections,
1899                   NewConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION));
1900 
1901     /* update topology */
1902     This->Topology.TopologyConnectionsCount += NewConnectionsCount;
1903     ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->ConnectionsCount += NewConnectionsCount;
1904     This->Topology.TopologyConnections = This->Filter.Descriptor->Connections;
1905 
1906     return Status;
1907 }
1908 
1909 /*
1910     @implemented
1911 */
1912 KSDDKAPI
1913 VOID
1914 NTAPI
KsFilterAttemptProcessing(IN PKSFILTER Filter,IN BOOLEAN Asynchronous)1915 KsFilterAttemptProcessing(
1916     IN PKSFILTER Filter,
1917     IN BOOLEAN Asynchronous)
1918 {
1919     PKSGATE Gate;
1920     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1921 
1922     /* get gate */
1923     Gate = This->lpVtblKsProcessingObject->GetAndGate((IKsProcessingObject*)This->lpVtblKsProcessingObject);
1924 
1925     if (!KsGateCaptureThreshold(Gate))
1926     {
1927         /* filter control gate is closed */
1928         return;
1929     }
1930 DPRINT1("processing\n");
1931     /* try initiate processing */
1932     This->lpVtblKsProcessingObject->Process((IKsProcessingObject*)This->lpVtblKsProcessingObject, Asynchronous);
1933 }
1934 
1935 /*
1936     @unimplemented
1937 */
1938 KSDDKAPI
1939 NTSTATUS
1940 NTAPI
KsFilterCreateNode(IN PKSFILTER Filter,IN const KSNODE_DESCRIPTOR * const NodeDescriptor,OUT PULONG NodeID)1941 KsFilterCreateNode (
1942     IN PKSFILTER Filter,
1943     IN const KSNODE_DESCRIPTOR *const NodeDescriptor,
1944     OUT PULONG NodeID)
1945 {
1946     UNIMPLEMENTED;
1947     return STATUS_NOT_IMPLEMENTED;
1948 }
1949 
1950 /*
1951     @implemented
1952 */
1953 KSDDKAPI
1954 NTSTATUS
1955 NTAPI
KsFilterCreatePinFactory(IN PKSFILTER Filter,IN const KSPIN_DESCRIPTOR_EX * const InPinDescriptor,OUT PULONG PinID)1956 KsFilterCreatePinFactory (
1957     IN PKSFILTER Filter,
1958     IN const KSPIN_DESCRIPTOR_EX *const InPinDescriptor,
1959     OUT PULONG PinID)
1960 {
1961     ULONG Count;
1962     NTSTATUS Status;
1963     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
1964 
1965     DPRINT("KsFilterCreatePinFactory\n");
1966 
1967     /* calculate new count */
1968     Count = This->Filter.Descriptor->PinDescriptorsCount + 1;
1969 
1970     /* sanity check */
1971     ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
1972 
1973     /* modify pin descriptors ex array */
1974     Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->Filter.Descriptor->PinDescriptors, Count * This->Filter.Descriptor->PinDescriptorSize, This->Filter.Descriptor->PinDescriptorsCount * This->Filter.Descriptor->PinDescriptorSize, 0);
1975     if (!NT_SUCCESS(Status))
1976     {
1977         /* failed */
1978         DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1979         return Status;
1980     }
1981 
1982     /* modify pin instance count array */
1983     Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->Filter.Descriptor->PinDescriptorsCount, 0);
1984     if (!NT_SUCCESS(Status))
1985     {
1986         /* failed */
1987         DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1988         return Status;
1989     }
1990 
1991     /* modify first pin array */
1992     Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PVOID) * Count, sizeof(PVOID) * This->Filter.Descriptor->PinDescriptorsCount, 0);
1993     if (!NT_SUCCESS(Status))
1994     {
1995         /* failed */
1996         DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
1997         return Status;
1998     }
1999 
2000     /* add new pin factory */
2001     RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors[This->Filter.Descriptor->PinDescriptorsCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
2002 
2003     /* allocate process pin index */
2004     Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count,
2005                      sizeof(KSPROCESSPIN_INDEXENTRY) * This->Filter.Descriptor->PinDescriptorsCount, 0);
2006 
2007     if (!NT_SUCCESS(Status))
2008     {
2009         DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status);
2010         return Status;
2011     }
2012 
2013     /* store new pin id */
2014     *PinID = This->Filter.Descriptor->PinDescriptorsCount;
2015 
2016     /* increment pin descriptor count */
2017     ((PKSFILTER_DESCRIPTOR)This->Filter.Descriptor)->PinDescriptorsCount++;
2018 
2019 
2020     DPRINT("KsFilterCreatePinFactory done\n");
2021     return STATUS_SUCCESS;
2022 
2023 }
2024 
2025 /*
2026     @unimplemented
2027 */
2028 KSDDKAPI
2029 PKSGATE
2030 NTAPI
KsFilterGetAndGate(IN PKSFILTER Filter)2031 KsFilterGetAndGate(
2032     IN PKSFILTER Filter)
2033 {
2034     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2035 
2036     /* return and-gate */
2037     return &This->Gate;
2038 }
2039 
2040 /*
2041     @implemented
2042 */
2043 KSDDKAPI
2044 ULONG
2045 NTAPI
KsFilterGetChildPinCount(IN PKSFILTER Filter,IN ULONG PinId)2046 KsFilterGetChildPinCount(
2047     IN PKSFILTER Filter,
2048     IN ULONG PinId)
2049 {
2050     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2051 
2052     if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
2053     {
2054         /* index is out of bounds */
2055         return 0;
2056     }
2057     /* return pin instance count */
2058     return This->PinInstanceCount[PinId];
2059 }
2060 
2061 /*
2062     @implemented
2063 */
2064 KSDDKAPI
2065 PKSPIN
2066 NTAPI
KsFilterGetFirstChildPin(IN PKSFILTER Filter,IN ULONG PinId)2067 KsFilterGetFirstChildPin(
2068     IN PKSFILTER Filter,
2069     IN ULONG PinId)
2070 {
2071     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2072 
2073     if (PinId >= This->Filter.Descriptor->PinDescriptorsCount)
2074     {
2075         /* index is out of bounds */
2076         return NULL;
2077     }
2078 
2079     /* return first pin index */
2080     return This->FirstPin[PinId];
2081 }
2082 
2083 /*
2084     @implemented
2085 */
2086 KSDDKAPI
2087 VOID
2088 NTAPI
KsFilterRegisterPowerCallbacks(IN PKSFILTER Filter,IN PFNKSFILTERPOWER Sleep OPTIONAL,IN PFNKSFILTERPOWER Wake OPTIONAL)2089 KsFilterRegisterPowerCallbacks(
2090     IN PKSFILTER Filter,
2091     IN PFNKSFILTERPOWER Sleep OPTIONAL,
2092     IN PFNKSFILTERPOWER Wake OPTIONAL)
2093 {
2094     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
2095 
2096     This->Sleep = Sleep;
2097     This->Wake = Wake;
2098 }
2099 
2100 /*
2101     @implemented
2102 */
2103 KSDDKAPI
2104 PKSFILTER
2105 NTAPI
KsGetFilterFromIrp(IN PIRP Irp)2106 KsGetFilterFromIrp(
2107     IN PIRP Irp)
2108 {
2109     PIO_STACK_LOCATION IoStack;
2110     PKSIOBJECT_HEADER ObjectHeader;
2111 
2112     DPRINT("KsGetFilterFromIrp\n");
2113 
2114     /* get current irp stack location */
2115     IoStack = IoGetCurrentIrpStackLocation(Irp);
2116 
2117     /* sanity check */
2118     ASSERT(IoStack->FileObject);
2119 
2120     /* get object header */
2121     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
2122 
2123     if (ObjectHeader->Type == KsObjectTypeFilter)
2124     {
2125         /* irp is targeted at the filter */
2126         return (PKSFILTER)ObjectHeader->ObjectType;
2127     }
2128     else if (ObjectHeader->Type == KsObjectTypePin)
2129     {
2130         /* irp is for a pin */
2131         return KsPinGetParentFilter((PKSPIN)ObjectHeader->ObjectType);
2132     }
2133     else
2134     {
2135         /* irp is unappropiate to retrieve a filter */
2136         return NULL;
2137     }
2138 }
2139