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