xref: /reactos/drivers/ksfilter/ks/filter.c (revision 7f26a396)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
466 IKsFilter_fnDoAllNecessaryPinsExist(
467     IKsFilter * iface)
468 {
469     UNIMPLEMENTED;
470     return FALSE;
471 }
472 
473 NTSTATUS
474 NTAPI
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
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
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
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
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
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
605 IKsFilter_fnDeliverResetState(
606     IKsFilter * iface,
607     IN struct KSPROCESSPIPESECTION *PipeSection,
608     IN KSRESET ResetState)
609 {
610     UNIMPLEMENTED;
611 }
612 
613 BOOL
614 NTAPI
615 IKsFilter_fnIsFrameHolding(
616     IKsFilter * iface)
617 {
618     UNIMPLEMENTED;
619     return FALSE;
620 }
621 
622 VOID
623 NTAPI
624 IKsFilter_fnRegisterForCopyCallbacks(
625     IKsFilter * iface,
626     IKsQueue *Queue,
627     BOOL Register)
628 {
629     UNIMPLEMENTED;
630 }
631 
632 PKSPROCESSPIN_INDEXENTRY
633 NTAPI
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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