xref: /reactos/drivers/multimedia/bdasup/bdasup.c (revision 9cfd8dd9)
1 
2 #include "precomp.h"
3 
4 #define TAG_BDASUP 'SadB'
5 
6 const GUID KSPROPSETID_BdaPinControl = {0xded49d5, 0xa8b7, 0x4d5d, {0x97, 0xa1, 0x12, 0xb0, 0xc1, 0x95, 0x87, 0x4d}};
7 const GUID KSMETHODSETID_BdaDeviceConfiguration = {0x71985f45, 0x1ca1, 0x11d3, {0x9c, 0xc8, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}};
8 const GUID KSPROPSETID_BdaTopology = {0xa14ee835, 0x0a23, 0x11d3, {0x9c, 0xc7, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}};
9 
10 BDA_GLOBAL g_Settings =
11 {
12     0,
13     0,
14     {NULL, NULL}
15 };
16 
17 KSPROPERTY_ITEM FilterPropertyItem[] =
18 {
19     DEFINE_KSPROPERTY_ITEM_BDA_NODE_TYPES(BdaPropertyNodeTypes, NULL),
20     DEFINE_KSPROPERTY_ITEM_BDA_PIN_TYPES( BdaPropertyPinTypes, NULL),
21     DEFINE_KSPROPERTY_ITEM_BDA_TEMPLATE_CONNECTIONS(BdaPropertyTemplateConnections, NULL),
22     DEFINE_KSPROPERTY_ITEM_BDA_NODE_METHODS(BdaPropertyNodeMethods, NULL),
23     DEFINE_KSPROPERTY_ITEM_BDA_NODE_PROPERTIES(BdaPropertyNodeProperties, NULL),
24     DEFINE_KSPROPERTY_ITEM_BDA_NODE_EVENTS(BdaPropertyNodeEvents, NULL),
25     DEFINE_KSPROPERTY_ITEM_BDA_CONTROLLING_PIN_ID(BdaPropertyGetControllingPinId, NULL),
26     DEFINE_KSPROPERTY_ITEM_BDA_NODE_DESCRIPTORS(BdaPropertyNodeDescriptors, NULL)
27 };
28 
29 KSPROPERTY_SET FilterPropertySet =
30 {
31     &KSPROPSETID_BdaTopology,
32     8,
33     FilterPropertyItem,
34     0,
35     NULL
36 };
37 
38 KSMETHOD_ITEM FilterMethodItem[] =
39 {
40     //DEFINE_KSMETHOD_ITEM_BDA_CREATE_PIN_FACTORY(BdaMethodCreatePin, NULL),
41     DEFINE_KSMETHOD_ITEM_BDA_CREATE_TOPOLOGY(BdaMethodCreateTopology, NULL)
42 };
43 
44 KSMETHOD_SET FilterMethodSet =
45 {
46     &KSMETHODSETID_BdaDeviceConfiguration,
47     2,
48     FilterMethodItem,
49     0,
50     NULL
51 };
52 
53 KSAUTOMATION_TABLE FilterAutomationTable =
54 {
55     1,
56     sizeof(KSPROPERTY_ITEM),
57     &FilterPropertySet,
58     1,
59     sizeof(KSMETHOD_ITEM),
60     &FilterMethodSet,
61     0,
62     sizeof(KSEVENT_ITEM),
63     NULL
64 };
65 
66 KSPROPERTY_ITEM PinPropertyItem[] =
67 {
68     DEFINE_KSPROPERTY_ITEM_BDA_PIN_ID(BdaPropertyGetPinControl, NULL),
69     DEFINE_KSPROPERTY_ITEM_BDA_PIN_TYPE(BdaPropertyGetPinControl, NULL)
70 };
71 
72 KSPROPERTY_SET PinPropertySet =
73 {
74     &KSPROPSETID_BdaPinControl,
75     2,
76     PinPropertyItem,
77     0,
78     NULL
79 };
80 
81 KSAUTOMATION_TABLE PinAutomationTable =
82 {
83     1,
84     sizeof(KSPROPERTY_ITEM),
85     &PinPropertySet,
86     0,
87     sizeof(KSMETHOD_ITEM),
88     NULL,
89     0,
90     sizeof(KSEVENT_ITEM),
91     NULL
92 };
93 
94 PVOID
95 AllocateItem(
96     IN POOL_TYPE PoolType,
97     IN SIZE_T NumberOfBytes)
98 {
99     return ExAllocatePoolZero(PoolType, NumberOfBytes, TAG_BDASUP);
100 }
101 
102 VOID
103 FreeItem(
104     IN PVOID Item)
105 {
106     ExFreePoolWithTag(Item, TAG_BDASUP);
107 }
108 
109 PBDA_FILTER_INSTANCE_ENTRY
110 GetFilterInstanceEntry(
111     IN PKSFILTERFACTORY FilterFactory)
112 {
113     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry = NULL;
114     PLIST_ENTRY Entry;
115     KIRQL OldLevel;
116 
117     /* acquire list lock */
118     KeAcquireSpinLock(&g_Settings.FilterFactoryInstanceListLock, &OldLevel);
119 
120     /* point to first entry */
121     Entry = g_Settings.FilterFactoryInstanceList.Flink;
122 
123     while(Entry != &g_Settings.FilterFactoryInstanceList)
124     {
125         /* get instance entry from list entry offset */
126         InstanceEntry = (PBDA_FILTER_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BDA_FILTER_INSTANCE_ENTRY, Entry);
127 
128         /* is the instance entry the requested one */
129         if (InstanceEntry->FilterFactoryInstance == FilterFactory)
130             break;
131 
132         /* move to next entry */
133         Entry = Entry->Flink;
134         /* set to null as it has not been found */
135         InstanceEntry = NULL;
136     }
137 
138     /* release spin lock */
139     KeReleaseSpinLock(&g_Settings.FilterFactoryInstanceListLock, OldLevel);
140 
141     /* return result */
142     return InstanceEntry;
143 }
144 
145 /*
146     @implemented
147 */
148 NTSTATUS
149 NTAPI
150 DllInitialize(
151     PUNICODE_STRING  RegistryPath)
152 {
153     DPRINT("BDASUP::DllInitialize\n");
154 
155     KeInitializeSpinLock(&g_Settings.FilterFactoryInstanceListLock);
156     InitializeListHead(&g_Settings.FilterFactoryInstanceList);
157     g_Settings.Initialized = TRUE;
158 
159     return STATUS_SUCCESS;
160 }
161 
162 /*
163     @implemented
164 */
165 NTSTATUS
166 NTAPI
167 BdaCheckChanges(IN PIRP  Irp)
168 {
169     DPRINT("BdaCheckChanges\n");
170 
171     if (!Irp)
172         return STATUS_INVALID_PARAMETER;
173 
174     return STATUS_SUCCESS;
175 }
176 
177 /*
178     @implemented
179 */
180 NTSTATUS
181 NTAPI
182 BdaCommitChanges(IN PIRP  Irp)
183 {
184     DPRINT("BdaCommitChanges\n");
185 
186     if (!Irp)
187         return STATUS_INVALID_PARAMETER;
188 
189     return STATUS_SUCCESS;
190 }
191 
192 /*
193     @implemented
194 */
195 NTSTATUS
196 NTAPI
197 BdaCreateFilterFactory(
198     IN PKSDEVICE  pKSDevice,
199     IN const KSFILTER_DESCRIPTOR *pFilterDescriptor,
200     IN const BDA_FILTER_TEMPLATE *pBdaFilterTemplate)
201 {
202     return BdaCreateFilterFactoryEx(pKSDevice, pFilterDescriptor, pBdaFilterTemplate, NULL);
203 }
204 
205 VOID
206 NTAPI
207 FreeFilterInstance(
208     IN PVOID Context)
209 {
210     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry = NULL;
211     PLIST_ENTRY Entry;
212     KIRQL OldLevel;
213 
214     /* acquire list lock */
215     KeAcquireSpinLock(&g_Settings.FilterFactoryInstanceListLock, &OldLevel);
216 
217     /* point to first entry */
218     Entry = g_Settings.FilterFactoryInstanceList.Flink;
219 
220     while(Entry != &g_Settings.FilterFactoryInstanceList)
221     {
222         /* get instance entry from list entry offset */
223         InstanceEntry = (PBDA_FILTER_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BDA_FILTER_INSTANCE_ENTRY, Entry);
224 
225         /* is the instance entry the requested one */
226         if (InstanceEntry == (PBDA_FILTER_INSTANCE_ENTRY)Context)
227         {
228             RemoveEntryList(&InstanceEntry->Entry);
229             FreeItem(InstanceEntry);
230             break;
231         }
232 
233         /* move to next entry */
234         Entry = Entry->Flink;
235     }
236 
237     /* release spin lock */
238     KeReleaseSpinLock(&g_Settings.FilterFactoryInstanceListLock, OldLevel);
239 }
240 
241 /*
242     @implemented
243 */
244 NTSTATUS
245 NTAPI
246 BdaCreateFilterFactoryEx(
247     IN  PKSDEVICE pKSDevice,
248     IN  const KSFILTER_DESCRIPTOR *pFilterDescriptor,
249     IN  const BDA_FILTER_TEMPLATE *BdaFilterTemplate,
250     OUT PKSFILTERFACTORY  *ppKSFilterFactory)
251 {
252     PKSFILTERFACTORY FilterFactory;
253     PBDA_FILTER_INSTANCE_ENTRY FilterInstance;
254     KIRQL OldLevel;
255     NTSTATUS Status;
256     PKSFILTER_DESCRIPTOR FilterDescriptor;
257 
258     DPRINT("BdaCreateFilterFactoryEx\n");
259 
260     FilterDescriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
261     if (!FilterDescriptor)
262     {
263         /* no memory */
264         return STATUS_INSUFFICIENT_RESOURCES;
265     }
266 
267     /* copy filter descriptor template */
268     RtlMoveMemory(FilterDescriptor, pFilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
269 
270     /* erase pin / nodes / connections from filter descriptor */
271     FilterDescriptor->PinDescriptorsCount = 0;
272     FilterDescriptor->PinDescriptors = NULL;
273     FilterDescriptor->NodeDescriptorsCount = 0;
274     FilterDescriptor->NodeDescriptors = NULL;
275     FilterDescriptor->ConnectionsCount = 0;
276     FilterDescriptor->Connections = NULL;
277 
278     /* merge the automation tables */
279     Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&FilterDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)pFilterDescriptor->AutomationTable, &FilterAutomationTable, NULL);
280 
281     /* check for success */
282     if (!NT_SUCCESS(Status))
283     {
284         DPRINT1("KsMergeAutomationTables failed with %lx\n", Status);
285         FreeItem(FilterDescriptor);
286         return Status;
287     }
288 
289     /* allocate filter instance */
290     FilterInstance = AllocateItem(NonPagedPool, sizeof(BDA_FILTER_INSTANCE_ENTRY));
291     if (!FilterInstance)
292     {
293         /* not enough memory */
294         FreeItem(FilterDescriptor);
295         return STATUS_INSUFFICIENT_RESOURCES;
296     }
297 
298     /* create the filter factory */
299     Status = KsCreateFilterFactory(pKSDevice->FunctionalDeviceObject, FilterDescriptor, NULL, NULL, 0, NULL, NULL, &FilterFactory);
300 
301     /* check for success */
302     if (NT_SUCCESS(Status))
303     {
304         if (FilterDescriptor->AutomationTable != &FilterAutomationTable)
305         {
306             /* add the item to filter object bag */
307             KsAddItemToObjectBag(FilterFactory->Bag, (PVOID)FilterDescriptor->AutomationTable, FreeFilterInstance);
308         }
309         else
310         {
311             /* make sure the automation table is not-read only */
312             Status = _KsEdit(FilterFactory->Bag, (PVOID*)&FilterDescriptor->AutomationTable, sizeof(KSAUTOMATION_TABLE), sizeof(KSAUTOMATION_TABLE), 0);
313 
314             /* sanity check */
315             ASSERT(Status == STATUS_SUCCESS);
316 
317             /* add to object bag */
318             KsAddItemToObjectBag(FilterFactory->Bag, (PVOID)FilterDescriptor->AutomationTable, FreeFilterInstance);
319         }
320 
321         /* initialize filter instance entry */
322         FilterInstance->FilterFactoryInstance = FilterFactory;
323         FilterInstance->FilterTemplate = (BDA_FILTER_TEMPLATE *)BdaFilterTemplate;
324 
325         /* acquire list lock */
326         KeAcquireSpinLock(&g_Settings.FilterFactoryInstanceListLock, &OldLevel);
327 
328         /* insert factory at the end */
329         InsertTailList(&g_Settings.FilterFactoryInstanceList, &FilterInstance->Entry);
330 
331         /* release spin lock */
332         KeReleaseSpinLock(&g_Settings.FilterFactoryInstanceListLock, OldLevel);
333 
334         if (ppKSFilterFactory)
335         {
336             /* store result */
337             *ppKSFilterFactory = FilterFactory;
338         }
339     }
340     else
341     {
342         /* failed to create filter factory */
343         FreeItem(FilterInstance);
344         FreeItem(FilterDescriptor);
345     }
346 
347     /* done */
348     DPRINT("BdaCreateFilterFactoryEx Status %x\n", Status);
349     return Status;
350 }
351 
352 /*
353     @implemented
354 */
355 NTSTATUS
356 NTAPI
357 BdaCreatePin(
358     IN PKSFILTER pKSFilter,
359     IN ULONG ulPinType,
360     OUT ULONG *pulPinId)
361 {
362     PKSPIN_DESCRIPTOR_EX PinDescriptor;
363     PKSFILTERFACTORY FilterFactory;
364     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
365     NTSTATUS Status;
366     ULONG PinId;
367     PKSPIN_DESCRIPTOR_EX NewPinDescriptor;
368 
369     DPRINT("BdaCreatePin\n");
370 
371     if (!pulPinId || !pKSFilter)
372         return STATUS_INVALID_PARAMETER;
373 
374     /* get parent filter factory */
375     FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
376 
377     /* sanity check */
378     ASSERT(FilterFactory);
379 
380     /* find instance entry */
381     InstanceEntry = GetFilterInstanceEntry(FilterFactory);
382 
383     if (!InstanceEntry)
384     {
385         /* the filter was not initialized with BDA */
386         return STATUS_NOT_FOUND;
387     }
388 
389     /* sanity checks */
390     ASSERT(InstanceEntry->FilterTemplate);
391     ASSERT(InstanceEntry->FilterTemplate->pFilterDescriptor);
392 
393     /* does the filter support any pins */
394     if (!InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount)
395     {
396         /* no pins supported */
397         DPRINT("BdaCreatePin NoPins supported\n");
398         return STATUS_UNSUCCESSFUL;
399     }
400 
401     /* is pin factory still existing */
402     if (InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount <= ulPinType)
403     {
404         /* pin request is out of bounds */
405         DPRINT("BdaCreatePin ulPinType %lu >= PinDescriptorCount %lu\n", ulPinType, InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount);
406         return STATUS_INVALID_PARAMETER;
407     }
408 
409     /* FIXME custom pin descriptors */
410     ASSERT(InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
411 
412     /* get pin descriptor */
413     PinDescriptor = (PKSPIN_DESCRIPTOR_EX)&InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptors[ulPinType];
414 
415     /* allocate pin descriptor */
416     NewPinDescriptor = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR_EX));
417     if (!NewPinDescriptor)
418     {
419         /* no memory */
420         DPRINT("BdaCreatePin OutOfMemory\n");
421         return STATUS_INSUFFICIENT_RESOURCES;
422     }
423 
424    /* make a copy of the pin descriptor */
425    RtlMoveMemory(NewPinDescriptor, PinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
426 
427     /* merge the automation tables */
428     Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&NewPinDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)PinDescriptor->AutomationTable, &PinAutomationTable, pKSFilter->Bag);
429 
430     /* check for success */
431     if (NT_SUCCESS(Status))
432     {
433         /* create the pin factory */
434         Status = KsFilterCreatePinFactory(pKSFilter, NewPinDescriptor, &PinId);
435 
436         /* check for success */
437         if (NT_SUCCESS(Status))
438         {
439             /* store result */
440             *pulPinId = PinId;
441         }
442     }
443 
444     DPRINT("BdaCreatePin Result %x PinId %u\n", Status, PinId);
445     return Status;
446 }
447 
448 /*
449     @implemented
450 */
451 NTSTATUS
452 NTAPI
453 BdaMethodCreatePin(
454     IN PIRP Irp,
455     IN KSMETHOD *pKSMethod,
456     OUT ULONG *pulPinFactoryID)
457 {
458     PKSM_PIN Pin;
459     PKSFILTER Filter;
460 
461     DPRINT("BdaMethodCreatePin\n");
462 
463     if (!Irp)
464     {
465         /* invalid parameter */
466         return STATUS_INVALID_PARAMETER;
467     }
468 
469     /* get filter from irp */
470     Filter = KsGetFilterFromIrp(Irp);
471 
472     /* sanity check */
473     ASSERT(Filter);
474     ASSERT(pKSMethod);
475 
476     /* get method request */
477     Pin = (PKSM_PIN)pKSMethod;
478 
479     /* create the pin */
480     return BdaCreatePin(Filter, Pin->PinId, pulPinFactoryID);
481 }
482 
483 /*
484     @implemented
485 */
486 NTSTATUS
487 NTAPI
488 BdaInitFilter(
489     IN PKSFILTER pKSFilter,
490     IN const BDA_FILTER_TEMPLATE *pBdaFilterTemplate)
491 {
492     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
493     PKSFILTERFACTORY FilterFactory;
494     ULONG Index, PinId;
495     NTSTATUS Status = STATUS_SUCCESS;
496 
497     DPRINT("BdaInitFilter %p\n", pBdaFilterTemplate);
498 
499     /* check input parameters */
500     if (!pKSFilter)
501         return STATUS_INVALID_PARAMETER;
502 
503     /* get parent filter factory */
504     FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
505 
506     /* sanity check */
507     ASSERT(FilterFactory);
508 
509     /* find instance entry */
510     InstanceEntry = GetFilterInstanceEntry(FilterFactory);
511 
512     /* sanity check */
513     ASSERT(InstanceEntry);
514 
515     if (!pBdaFilterTemplate)
516     {
517         /* use template from BdaCreateFilterFactoryEx */
518         pBdaFilterTemplate = InstanceEntry->FilterTemplate;
519     }
520 
521     /* now create the pins */
522     for(Index = 0; Index < pBdaFilterTemplate->pFilterDescriptor->PinDescriptorsCount; Index++)
523     {
524         /* create the pin */
525         Status = BdaCreatePin(pKSFilter, Index, &PinId);
526 
527         /* check for success */
528         if (!NT_SUCCESS(Status))
529             break;
530     }
531 
532     /* done */
533     return Status;
534 }
535 
536 /*
537     @implemented
538 */
539 NTSTATUS
540 NTAPI
541 BdaCreateTopology(
542     IN PKSFILTER pKSFilter,
543     IN ULONG InputPinId,
544     IN ULONG OutputPinId)
545 {
546     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
547     PKSFILTERFACTORY FilterFactory;
548     KSTOPOLOGY_CONNECTION Connection;
549 
550     DPRINT("BdaCreateTopology\n");
551 
552     /* check input parameters */
553     if (!pKSFilter)
554         return STATUS_INVALID_PARAMETER;
555 
556     /* get parent filter factory */
557     FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
558 
559     /* sanity check */
560     ASSERT(FilterFactory);
561 
562     /* find instance entry */
563     InstanceEntry = GetFilterInstanceEntry(FilterFactory);
564 
565     if (!InstanceEntry)
566     {
567         /* the filter was not initialized with BDA */
568         return STATUS_NOT_FOUND;
569     }
570 
571     if (InputPinId >= InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount ||
572         OutputPinId >= InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount)
573     {
574         /* invalid pin id */
575         return STATUS_INVALID_PARAMETER;
576     }
577 
578     /* initialize topology connection */
579     Connection.FromNode = KSFILTER_NODE;
580     Connection.ToNode = KSFILTER_NODE;
581     Connection.FromNodePin = InputPinId;
582     Connection.ToNodePin = OutputPinId;
583 
584     /* add the connection */
585     return KsFilterAddTopologyConnections(pKSFilter, 1, &Connection);
586 }
587 
588 /*
589     @unimplemented
590 */
591 NTSTATUS
592 NTAPI
593 BdaDeletePin(
594     IN PKSFILTER pKSFilter,
595     IN ULONG *pulPinId)
596 {
597     UNIMPLEMENTED;
598     DPRINT("BdaDeletePin\n");
599     return STATUS_NOT_IMPLEMENTED;
600 }
601 
602 /*
603     @implemented
604 */
605 NTSTATUS
606 NTAPI
607 BdaFilterFactoryUpdateCacheData(
608     IN PKSFILTERFACTORY FilterFactory,
609     IN const KSFILTER_DESCRIPTOR *FilterDescriptor OPTIONAL)
610 {
611     DPRINT("BdaFilterFactoryUpdateCacheData\n");
612     return KsFilterFactoryUpdateCacheData(FilterFactory, FilterDescriptor);
613 }
614 
615 /*
616     @implemented
617 */
618 NTSTATUS
619 NTAPI
620 BdaGetChangeState(
621     IN PIRP Irp,
622     OUT BDA_CHANGE_STATE *ChangeState)
623 {
624     DPRINT("BdaGetChangeState\n");
625 
626     if (Irp && ChangeState)
627     {
628         *ChangeState = BDA_CHANGES_COMPLETE;
629         return STATUS_SUCCESS;
630     }
631 
632     /* invalid parameters supplied */
633     return STATUS_INVALID_PARAMETER;
634 
635 }
636 
637 /*
638     @implemented
639 */
640 NTSTATUS
641 NTAPI
642 BdaMethodCreateTopology(
643     IN PIRP Irp,
644     IN KSMETHOD *pKSMethod,
645     OPTIONAL PVOID pvIgnored)
646 {
647     PKSFILTER Filter;
648     PKSP_BDA_NODE_PIN Node;
649 
650     DPRINT("BdaMethodCreateTopology\n");
651 
652     /* check input parameters */
653     if (!Irp || !pKSMethod)
654         return STATUS_INVALID_PARAMETER;
655 
656     /* get filter */
657     Filter = KsGetFilterFromIrp(Irp);
658 
659     /* sanity check */
660     ASSERT(Filter);
661 
662     /* get method request */
663     Node = (PKSP_BDA_NODE_PIN)pKSMethod;
664 
665     /* create the topology */
666     return BdaCreateTopology(Filter, Node->ulInputPinId, Node->ulOutputPinId);
667 }
668 
669 /*
670     @implemented
671 */
672 NTSTATUS
673 NTAPI
674 BdaMethodDeletePin(
675     IN PIRP Irp,
676     IN KSMETHOD *pKSMethod,
677     OPTIONAL PVOID pvIgnored)
678 {
679     DPRINT("BdaMethodDeletePin\n");
680 
681     if (!Irp)
682         return STATUS_INVALID_PARAMETER;
683 
684     return STATUS_SUCCESS;
685 }
686 
687 /*
688     @unimplemented
689 */
690 NTSTATUS
691 NTAPI
692 BdaPropertyGetControllingPinId(
693     IN PIRP Irp,
694     IN KSP_BDA_NODE_PIN *pProperty,
695     OUT ULONG *pulControllingPinId)
696 {
697     UNIMPLEMENTED;
698     DPRINT("BdaPropertyGetControllingPinId\n");
699     return STATUS_NOT_IMPLEMENTED;
700 }
701 
702 /*
703     @implemented
704 */
705 NTSTATUS
706 NTAPI
707 BdaPropertyGetPinControl(
708     IN PIRP Irp,
709     IN KSPROPERTY *pKSProperty,
710     OUT ULONG *pulProperty)
711 {
712     PKSPIN Pin;
713     PKSFILTER Filter;
714     PKSFILTERFACTORY FilterFactory;
715     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
716 
717     DPRINT("BdaPropertyGetPinControl\n");
718 
719     /* first get the pin */
720     Pin = KsGetPinFromIrp(Irp);
721     ASSERT(Pin);
722 
723     /* now get the parent filter */
724     Filter = KsPinGetParentFilter(Pin);
725     ASSERT(Filter);
726 
727     /* get parent filter factory */
728     FilterFactory = KsFilterGetParentFilterFactory(Filter);
729     ASSERT(FilterFactory);
730 
731     /* find instance entry */
732     InstanceEntry = GetFilterInstanceEntry(FilterFactory);
733     ASSERT(InstanceEntry);
734 
735     /* sanity check */
736     pKSProperty++;
737     ASSERT(pKSProperty->Id == KSPROPERTY_BDA_PIN_TYPE);
738 
739     /* store pin id */
740     *pulProperty = Pin->Id;
741 
742     return STATUS_SUCCESS;
743 }
744 
745 /*
746     @unimplemented
747 */
748 NTSTATUS
749 NTAPI
750 BdaPropertyNodeDescriptors(
751     IN PIRP Irp,
752     IN KSPROPERTY *pKSProperty,
753     OUT BDANODE_DESCRIPTOR *pNodeDescriptorProperty)
754 {
755     UNIMPLEMENTED;
756     DPRINT("BdaPropertyNodeDescriptors\n");
757     return STATUS_NOT_IMPLEMENTED;
758 }
759 
760 /*
761     @unimplemented
762 */
763 NTSTATUS
764 NTAPI
765 BdaPropertyNodeEvents(
766     IN PIRP Irp,
767     IN KSP_NODE *pKSProperty,
768     OUT GUID *pguidProperty)
769 {
770     UNIMPLEMENTED;
771     DPRINT("BdaPropertyNodeEvents\n");
772     return STATUS_NOT_IMPLEMENTED;
773 }
774 
775 /*
776     @unimplemented
777 */
778 NTSTATUS
779 NTAPI
780 BdaPropertyNodeMethods(
781     IN PIRP Irp,
782     IN KSP_NODE *pKSProperty,
783     OUT GUID *pguidProperty)
784 {
785     UNIMPLEMENTED;
786     DPRINT("BdaPropertyNodeMethods\n");
787     return STATUS_NOT_IMPLEMENTED;
788 }
789 
790 /*
791     @unimplemented
792 */
793 NTSTATUS
794 NTAPI
795 BdaPropertyNodeProperties(
796     IN PIRP Irp,
797     IN KSP_NODE *pKSProperty,
798     OUT GUID *pguidProperty)
799 {
800     UNIMPLEMENTED;
801     DPRINT("BdaPropertyNodeProperties\n");
802     return STATUS_NOT_IMPLEMENTED;
803 }
804 
805 /*
806     @implemented
807 */
808 NTSTATUS
809 NTAPI
810 BdaPropertyNodeTypes(
811     IN PIRP Irp,
812     IN KSPROPERTY *pKSProperty,
813     OUT ULONG *pulProperty)
814 {
815     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
816     PKSFILTERFACTORY FilterFactory;
817     PKSFILTER pKSFilter;
818     PIO_STACK_LOCATION IoStack;
819     ULONG Index;
820 
821     DPRINT("BdaPropertyNodeTypes\n");
822 
823     /* check input parameter */
824     if (!Irp || !pKSProperty)
825         return STATUS_INVALID_PARAMETER;
826 
827     /* first get the filter */
828     pKSFilter = KsGetFilterFromIrp(Irp);
829 
830     /* sanity check */
831     ASSERT(pKSFilter);
832 
833     /* get parent filter factory */
834     FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
835 
836     /* sanity check */
837     ASSERT(FilterFactory);
838 
839     /* find instance entry */
840     InstanceEntry = GetFilterInstanceEntry(FilterFactory);
841     ASSERT(InstanceEntry);
842 
843     /* get current irp stack */
844     IoStack = IoGetCurrentIrpStackLocation(Irp);
845 
846     /* are there node types provided */
847     if (!pulProperty)
848     {
849         /* no node entry array provided */
850         Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount * sizeof(ULONG);
851         Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
852         return STATUS_MORE_ENTRIES;
853     }
854 
855     if (InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount * sizeof(ULONG) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
856     {
857         /* buffer too small */
858         Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount * sizeof(ULONG);
859         Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
860         return STATUS_BUFFER_TOO_SMALL;
861     }
862 
863     /* now copy all descriptors */
864     for(Index = 0; Index < InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount; Index++)
865     {
866         /* use the index as the type */
867         pulProperty[Index] = Index;
868     }
869 
870     return STATUS_SUCCESS;
871 }
872 
873 /*
874     @implemented
875 */
876 NTSTATUS
877 NTAPI
878 BdaPropertyPinTypes(
879     IN PIRP Irp,
880     IN KSPROPERTY *pKSProperty,
881     OUT ULONG *pulProperty)
882 {
883     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
884     PKSFILTERFACTORY FilterFactory;
885     PKSFILTER pKSFilter;
886     PIO_STACK_LOCATION IoStack;
887     ULONG Index;
888 
889     DPRINT("BdaPropertyPinTypes\n");
890 
891     /* check input parameter */
892     if (!Irp || !pKSProperty)
893         return STATUS_INVALID_PARAMETER;
894 
895     /* first get the filter */
896     pKSFilter = KsGetFilterFromIrp(Irp);
897 
898     /* sanity check */
899     ASSERT(pKSFilter);
900 
901     /* get parent filter factory */
902     FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
903 
904     /* sanity check */
905     ASSERT(FilterFactory);
906 
907     /* find instance entry */
908     InstanceEntry = GetFilterInstanceEntry(FilterFactory);
909     ASSERT(InstanceEntry);
910 
911     /* get current irp stack */
912     IoStack = IoGetCurrentIrpStackLocation(Irp);
913 
914     /* are there node types provided */
915     if (!pKSProperty)
916     {
917         /* no node entry array provided */
918         Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount * sizeof(ULONG);
919         Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
920         return STATUS_MORE_ENTRIES;
921     }
922 
923     if (InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount * sizeof(ULONG) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
924     {
925         /* buffer too small */
926         Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount * sizeof(ULONG);
927         Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
928         return STATUS_BUFFER_TOO_SMALL;
929     }
930 
931     /* now copy all descriptors */
932     for(Index = 0; Index < InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount; Index++)
933     {
934         /* use the index as the type */
935         pulProperty[Index] = Index;
936     }
937 
938     return STATUS_SUCCESS;
939 }
940 
941 /*
942     @implemented
943 */
944 NTSTATUS
945 NTAPI
946 BdaPropertyTemplateConnections(
947     IN PIRP Irp,
948     IN KSPROPERTY *pKSProperty,
949     OUT KSTOPOLOGY_CONNECTION *pConnectionProperty)
950 {
951     PBDA_FILTER_INSTANCE_ENTRY FilterInstance;
952     PKSFILTER Filter;
953     PIO_STACK_LOCATION IoStack;
954     ULONG Index;
955 
956     DPRINT("BdaPropertyTemplateConnections\n");
957 
958     /* validate parameters */
959     if (!Irp || !pKSProperty)
960         return STATUS_INVALID_PARAMETER;
961 
962     /* first get the filter */
963     Filter = KsGetFilterFromIrp(Irp);
964 
965     /* sanity check */
966     ASSERT(Filter);
967 
968     /* verify filter has been registered with BDA */
969     FilterInstance = GetFilterInstanceEntry(KsFilterGetParentFilterFactory(Filter));
970 
971     if (!FilterInstance)
972         return STATUS_INVALID_PARAMETER;
973 
974     /* get current irp stack */
975     IoStack = IoGetCurrentIrpStackLocation(Irp);
976 
977     if (!pConnectionProperty)
978     {
979         /* caller needs the size first */
980         Irp->IoStatus.Information = FilterInstance->FilterTemplate->pFilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION);
981         Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
982         return STATUS_BUFFER_OVERFLOW;
983     }
984 
985     /* sanity check */
986     ASSERT(FilterInstance->FilterTemplate->pFilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION) <= IoStack->Parameters.DeviceIoControl.OutputBufferLength);
987 
988     for(Index = 0; Index < FilterInstance->FilterTemplate->pFilterDescriptor->ConnectionsCount; Index++)
989     {
990         /* sanity check */
991         ASSERT(FilterInstance->FilterTemplate->pFilterDescriptor->Connections);
992 
993         /* copy connection */
994         RtlMoveMemory(pConnectionProperty, &FilterInstance->FilterTemplate->pFilterDescriptor->Connections[Index], sizeof(KSTOPOLOGY_CONNECTION));
995     }
996 
997     /* store result */
998     Irp->IoStatus.Information = FilterInstance->FilterTemplate->pFilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION);
999     Irp->IoStatus.Status = STATUS_SUCCESS;
1000 
1001     /* done */
1002     return STATUS_SUCCESS;
1003 
1004 }
1005 
1006 /*
1007     @implemented
1008 */
1009 NTSTATUS
1010 NTAPI
1011 BdaStartChanges(IN PIRP Irp)
1012 {
1013     DPRINT("BdaStartChanges\n");
1014 
1015     if (Irp)
1016         return STATUS_SUCCESS;
1017     else
1018         return STATUS_INVALID_PARAMETER;
1019 
1020 }
1021 
1022 /*
1023     @implemented
1024 */
1025 NTSTATUS
1026 NTAPI
1027 BdaUninitFilter(IN PKSFILTER pKSFilter)
1028 {
1029     DPRINT("BdaUninitFilter\n");
1030     return STATUS_SUCCESS;
1031 }
1032 
1033 /*
1034     @implemented
1035 */
1036 NTSTATUS
1037 NTAPI
1038 BdaValidateNodeProperty(
1039     IN PIRP Irp,
1040     IN KSPROPERTY *KSProperty)
1041 {
1042     DPRINT("BdaValidateNodeProperty\n");
1043 
1044     /* check for valid parameter */
1045     if (Irp && KSProperty)
1046         return STATUS_SUCCESS;
1047 
1048     return STATUS_INVALID_PARAMETER;
1049 }
1050