mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
1049 lines
25 KiB
C
1049 lines
25 KiB
C
|
|
#include "precomp.h"
|
|
|
|
#define TAG_BDASUP 'SadB'
|
|
|
|
const GUID KSPROPSETID_BdaPinControl = {0xded49d5, 0xa8b7, 0x4d5d, {0x97, 0xa1, 0x12, 0xb0, 0xc1, 0x95, 0x87, 0x4d}};
|
|
const GUID KSMETHODSETID_BdaDeviceConfiguration = {0x71985f45, 0x1ca1, 0x11d3, {0x9c, 0xc8, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}};
|
|
const GUID KSPROPSETID_BdaTopology = {0xa14ee835, 0x0a23, 0x11d3, {0x9c, 0xc7, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}};
|
|
|
|
BDA_GLOBAL g_Settings =
|
|
{
|
|
0,
|
|
0,
|
|
{NULL, NULL}
|
|
};
|
|
|
|
KSPROPERTY_ITEM FilterPropertyItem[] =
|
|
{
|
|
DEFINE_KSPROPERTY_ITEM_BDA_NODE_TYPES(BdaPropertyNodeTypes, NULL),
|
|
DEFINE_KSPROPERTY_ITEM_BDA_PIN_TYPES( BdaPropertyPinTypes, NULL),
|
|
DEFINE_KSPROPERTY_ITEM_BDA_TEMPLATE_CONNECTIONS(BdaPropertyTemplateConnections, NULL),
|
|
DEFINE_KSPROPERTY_ITEM_BDA_NODE_METHODS(BdaPropertyNodeMethods, NULL),
|
|
DEFINE_KSPROPERTY_ITEM_BDA_NODE_PROPERTIES(BdaPropertyNodeProperties, NULL),
|
|
DEFINE_KSPROPERTY_ITEM_BDA_NODE_EVENTS(BdaPropertyNodeEvents, NULL),
|
|
DEFINE_KSPROPERTY_ITEM_BDA_CONTROLLING_PIN_ID(BdaPropertyGetControllingPinId, NULL),
|
|
DEFINE_KSPROPERTY_ITEM_BDA_NODE_DESCRIPTORS(BdaPropertyNodeDescriptors, NULL)
|
|
};
|
|
|
|
KSPROPERTY_SET FilterPropertySet =
|
|
{
|
|
&KSPROPSETID_BdaTopology,
|
|
8,
|
|
FilterPropertyItem,
|
|
0,
|
|
NULL
|
|
};
|
|
|
|
KSMETHOD_ITEM FilterMethodItem[] =
|
|
{
|
|
//DEFINE_KSMETHOD_ITEM_BDA_CREATE_PIN_FACTORY(BdaMethodCreatePin, NULL),
|
|
DEFINE_KSMETHOD_ITEM_BDA_CREATE_TOPOLOGY(BdaMethodCreateTopology, NULL)
|
|
};
|
|
|
|
KSMETHOD_SET FilterMethodSet =
|
|
{
|
|
&KSMETHODSETID_BdaDeviceConfiguration,
|
|
2,
|
|
FilterMethodItem,
|
|
0,
|
|
NULL
|
|
};
|
|
|
|
KSAUTOMATION_TABLE FilterAutomationTable =
|
|
{
|
|
1,
|
|
sizeof(KSPROPERTY_ITEM),
|
|
&FilterPropertySet,
|
|
1,
|
|
sizeof(KSMETHOD_ITEM),
|
|
&FilterMethodSet,
|
|
0,
|
|
sizeof(KSEVENT_ITEM),
|
|
NULL
|
|
};
|
|
|
|
KSPROPERTY_ITEM PinPropertyItem[] =
|
|
{
|
|
DEFINE_KSPROPERTY_ITEM_BDA_PIN_ID(BdaPropertyGetPinControl, NULL),
|
|
DEFINE_KSPROPERTY_ITEM_BDA_PIN_TYPE(BdaPropertyGetPinControl, NULL)
|
|
};
|
|
|
|
KSPROPERTY_SET PinPropertySet =
|
|
{
|
|
&KSPROPSETID_BdaPinControl,
|
|
2,
|
|
PinPropertyItem,
|
|
0,
|
|
NULL
|
|
};
|
|
|
|
KSAUTOMATION_TABLE PinAutomationTable =
|
|
{
|
|
1,
|
|
sizeof(KSPROPERTY_ITEM),
|
|
&PinPropertySet,
|
|
0,
|
|
sizeof(KSMETHOD_ITEM),
|
|
NULL,
|
|
0,
|
|
sizeof(KSEVENT_ITEM),
|
|
NULL
|
|
};
|
|
|
|
PVOID
|
|
AllocateItem(
|
|
IN POOL_TYPE PoolType,
|
|
IN SIZE_T NumberOfBytes)
|
|
{
|
|
return ExAllocatePoolZero(PoolType, NumberOfBytes, TAG_BDASUP);
|
|
}
|
|
|
|
VOID
|
|
FreeItem(
|
|
IN PVOID Item)
|
|
{
|
|
ExFreePoolWithTag(Item, TAG_BDASUP);
|
|
}
|
|
|
|
PBDA_FILTER_INSTANCE_ENTRY
|
|
GetFilterInstanceEntry(
|
|
IN PKSFILTERFACTORY FilterFactory)
|
|
{
|
|
PBDA_FILTER_INSTANCE_ENTRY InstanceEntry = NULL;
|
|
PLIST_ENTRY Entry;
|
|
KIRQL OldLevel;
|
|
|
|
/* acquire list lock */
|
|
KeAcquireSpinLock(&g_Settings.FilterFactoryInstanceListLock, &OldLevel);
|
|
|
|
/* point to first entry */
|
|
Entry = g_Settings.FilterFactoryInstanceList.Flink;
|
|
|
|
while(Entry != &g_Settings.FilterFactoryInstanceList)
|
|
{
|
|
/* get instance entry from list entry offset */
|
|
InstanceEntry = (PBDA_FILTER_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BDA_FILTER_INSTANCE_ENTRY, Entry);
|
|
|
|
/* is the instance entry the requested one */
|
|
if (InstanceEntry->FilterFactoryInstance == FilterFactory)
|
|
break;
|
|
|
|
/* move to next entry */
|
|
Entry = Entry->Flink;
|
|
/* set to null as it has not been found */
|
|
InstanceEntry = NULL;
|
|
}
|
|
|
|
/* release spin lock */
|
|
KeReleaseSpinLock(&g_Settings.FilterFactoryInstanceListLock, OldLevel);
|
|
|
|
/* return result */
|
|
return InstanceEntry;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
DllInitialize(
|
|
PUNICODE_STRING RegistryPath)
|
|
{
|
|
DPRINT("BDASUP::DllInitialize\n");
|
|
|
|
KeInitializeSpinLock(&g_Settings.FilterFactoryInstanceListLock);
|
|
InitializeListHead(&g_Settings.FilterFactoryInstanceList);
|
|
g_Settings.Initialized = TRUE;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaCheckChanges(IN PIRP Irp)
|
|
{
|
|
DPRINT("BdaCheckChanges\n");
|
|
|
|
if (!Irp)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaCommitChanges(IN PIRP Irp)
|
|
{
|
|
DPRINT("BdaCommitChanges\n");
|
|
|
|
if (!Irp)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaCreateFilterFactory(
|
|
IN PKSDEVICE pKSDevice,
|
|
IN const KSFILTER_DESCRIPTOR *pFilterDescriptor,
|
|
IN const BDA_FILTER_TEMPLATE *pBdaFilterTemplate)
|
|
{
|
|
return BdaCreateFilterFactoryEx(pKSDevice, pFilterDescriptor, pBdaFilterTemplate, NULL);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
FreeFilterInstance(
|
|
IN PVOID Context)
|
|
{
|
|
PBDA_FILTER_INSTANCE_ENTRY InstanceEntry = NULL;
|
|
PLIST_ENTRY Entry;
|
|
KIRQL OldLevel;
|
|
|
|
/* acquire list lock */
|
|
KeAcquireSpinLock(&g_Settings.FilterFactoryInstanceListLock, &OldLevel);
|
|
|
|
/* point to first entry */
|
|
Entry = g_Settings.FilterFactoryInstanceList.Flink;
|
|
|
|
while(Entry != &g_Settings.FilterFactoryInstanceList)
|
|
{
|
|
/* get instance entry from list entry offset */
|
|
InstanceEntry = (PBDA_FILTER_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BDA_FILTER_INSTANCE_ENTRY, Entry);
|
|
|
|
/* is the instance entry the requested one */
|
|
if (InstanceEntry == (PBDA_FILTER_INSTANCE_ENTRY)Context)
|
|
{
|
|
RemoveEntryList(&InstanceEntry->Entry);
|
|
FreeItem(InstanceEntry);
|
|
break;
|
|
}
|
|
|
|
/* move to next entry */
|
|
Entry = Entry->Flink;
|
|
}
|
|
|
|
/* release spin lock */
|
|
KeReleaseSpinLock(&g_Settings.FilterFactoryInstanceListLock, OldLevel);
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaCreateFilterFactoryEx(
|
|
IN PKSDEVICE pKSDevice,
|
|
IN const KSFILTER_DESCRIPTOR *pFilterDescriptor,
|
|
IN const BDA_FILTER_TEMPLATE *BdaFilterTemplate,
|
|
OUT PKSFILTERFACTORY *ppKSFilterFactory)
|
|
{
|
|
PKSFILTERFACTORY FilterFactory;
|
|
PBDA_FILTER_INSTANCE_ENTRY FilterInstance;
|
|
KIRQL OldLevel;
|
|
NTSTATUS Status;
|
|
PKSFILTER_DESCRIPTOR FilterDescriptor;
|
|
|
|
DPRINT("BdaCreateFilterFactoryEx\n");
|
|
|
|
FilterDescriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
|
|
if (!FilterDescriptor)
|
|
{
|
|
/* no memory */
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
/* copy filter descriptor template */
|
|
RtlMoveMemory(FilterDescriptor, pFilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
|
|
|
|
/* erase pin / nodes / connections from filter descriptor */
|
|
FilterDescriptor->PinDescriptorsCount = 0;
|
|
FilterDescriptor->PinDescriptors = NULL;
|
|
FilterDescriptor->NodeDescriptorsCount = 0;
|
|
FilterDescriptor->NodeDescriptors = NULL;
|
|
FilterDescriptor->ConnectionsCount = 0;
|
|
FilterDescriptor->Connections = NULL;
|
|
|
|
/* merge the automation tables */
|
|
Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&FilterDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)pFilterDescriptor->AutomationTable, &FilterAutomationTable, NULL);
|
|
|
|
/* check for success */
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("KsMergeAutomationTables failed with %lx\n", Status);
|
|
FreeItem(FilterDescriptor);
|
|
return Status;
|
|
}
|
|
|
|
/* allocate filter instance */
|
|
FilterInstance = AllocateItem(NonPagedPool, sizeof(BDA_FILTER_INSTANCE_ENTRY));
|
|
if (!FilterInstance)
|
|
{
|
|
/* not enough memory */
|
|
FreeItem(FilterDescriptor);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
/* create the filter factory */
|
|
Status = KsCreateFilterFactory(pKSDevice->FunctionalDeviceObject, FilterDescriptor, NULL, NULL, 0, NULL, NULL, &FilterFactory);
|
|
|
|
/* check for success */
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
if (FilterDescriptor->AutomationTable != &FilterAutomationTable)
|
|
{
|
|
/* add the item to filter object bag */
|
|
KsAddItemToObjectBag(FilterFactory->Bag, (PVOID)FilterDescriptor->AutomationTable, FreeFilterInstance);
|
|
}
|
|
else
|
|
{
|
|
/* make sure the automation table is not-read only */
|
|
Status = _KsEdit(FilterFactory->Bag, (PVOID*)&FilterDescriptor->AutomationTable, sizeof(KSAUTOMATION_TABLE), sizeof(KSAUTOMATION_TABLE), 0);
|
|
|
|
/* sanity check */
|
|
ASSERT(Status == STATUS_SUCCESS);
|
|
|
|
/* add to object bag */
|
|
KsAddItemToObjectBag(FilterFactory->Bag, (PVOID)FilterDescriptor->AutomationTable, FreeFilterInstance);
|
|
}
|
|
|
|
/* initialize filter instance entry */
|
|
FilterInstance->FilterFactoryInstance = FilterFactory;
|
|
FilterInstance->FilterTemplate = (BDA_FILTER_TEMPLATE *)BdaFilterTemplate;
|
|
|
|
/* acquire list lock */
|
|
KeAcquireSpinLock(&g_Settings.FilterFactoryInstanceListLock, &OldLevel);
|
|
|
|
/* insert factory at the end */
|
|
InsertTailList(&g_Settings.FilterFactoryInstanceList, &FilterInstance->Entry);
|
|
|
|
/* release spin lock */
|
|
KeReleaseSpinLock(&g_Settings.FilterFactoryInstanceListLock, OldLevel);
|
|
|
|
if (ppKSFilterFactory)
|
|
{
|
|
/* store result */
|
|
*ppKSFilterFactory = FilterFactory;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* failed to create filter factory */
|
|
FreeItem(FilterInstance);
|
|
FreeItem(FilterDescriptor);
|
|
}
|
|
|
|
/* done */
|
|
DPRINT("BdaCreateFilterFactoryEx Status %x\n", Status);
|
|
return Status;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaCreatePin(
|
|
IN PKSFILTER pKSFilter,
|
|
IN ULONG ulPinType,
|
|
OUT ULONG *pulPinId)
|
|
{
|
|
PKSPIN_DESCRIPTOR_EX PinDescriptor;
|
|
PKSFILTERFACTORY FilterFactory;
|
|
PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
|
|
NTSTATUS Status;
|
|
ULONG PinId;
|
|
PKSPIN_DESCRIPTOR_EX NewPinDescriptor;
|
|
|
|
DPRINT("BdaCreatePin\n");
|
|
|
|
if (!pulPinId || !pKSFilter)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* get parent filter factory */
|
|
FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
|
|
|
|
/* sanity check */
|
|
ASSERT(FilterFactory);
|
|
|
|
/* find instance entry */
|
|
InstanceEntry = GetFilterInstanceEntry(FilterFactory);
|
|
|
|
if (!InstanceEntry)
|
|
{
|
|
/* the filter was not initialized with BDA */
|
|
return STATUS_NOT_FOUND;
|
|
}
|
|
|
|
/* sanity checks */
|
|
ASSERT(InstanceEntry->FilterTemplate);
|
|
ASSERT(InstanceEntry->FilterTemplate->pFilterDescriptor);
|
|
|
|
/* does the filter support any pins */
|
|
if (!InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount)
|
|
{
|
|
/* no pins supported */
|
|
DPRINT("BdaCreatePin NoPins supported\n");
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
/* is pin factory still existing */
|
|
if (InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount <= ulPinType)
|
|
{
|
|
/* pin request is out of bounds */
|
|
DPRINT("BdaCreatePin ulPinType %lu >= PinDescriptorCount %lu\n", ulPinType, InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount);
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* FIXME custom pin descriptors */
|
|
ASSERT(InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
|
|
|
|
/* get pin descriptor */
|
|
PinDescriptor = (PKSPIN_DESCRIPTOR_EX)&InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptors[ulPinType];
|
|
|
|
/* allocate pin descriptor */
|
|
NewPinDescriptor = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR_EX));
|
|
if (!NewPinDescriptor)
|
|
{
|
|
/* no memory */
|
|
DPRINT("BdaCreatePin OutOfMemory\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
/* make a copy of the pin descriptor */
|
|
RtlMoveMemory(NewPinDescriptor, PinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
|
|
|
|
/* merge the automation tables */
|
|
Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&NewPinDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)PinDescriptor->AutomationTable, &PinAutomationTable, pKSFilter->Bag);
|
|
|
|
/* check for success */
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* create the pin factory */
|
|
Status = KsFilterCreatePinFactory(pKSFilter, NewPinDescriptor, &PinId);
|
|
|
|
/* check for success */
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* store result */
|
|
*pulPinId = PinId;
|
|
}
|
|
}
|
|
|
|
DPRINT("BdaCreatePin Result %x PinId %u\n", Status, PinId);
|
|
return Status;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaMethodCreatePin(
|
|
IN PIRP Irp,
|
|
IN KSMETHOD *pKSMethod,
|
|
OUT ULONG *pulPinFactoryID)
|
|
{
|
|
PKSM_PIN Pin;
|
|
PKSFILTER Filter;
|
|
|
|
DPRINT("BdaMethodCreatePin\n");
|
|
|
|
if (!Irp)
|
|
{
|
|
/* invalid parameter */
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* get filter from irp */
|
|
Filter = KsGetFilterFromIrp(Irp);
|
|
|
|
/* sanity check */
|
|
ASSERT(Filter);
|
|
ASSERT(pKSMethod);
|
|
|
|
/* get method request */
|
|
Pin = (PKSM_PIN)pKSMethod;
|
|
|
|
/* create the pin */
|
|
return BdaCreatePin(Filter, Pin->PinId, pulPinFactoryID);
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaInitFilter(
|
|
IN PKSFILTER pKSFilter,
|
|
IN const BDA_FILTER_TEMPLATE *pBdaFilterTemplate)
|
|
{
|
|
PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
|
|
PKSFILTERFACTORY FilterFactory;
|
|
ULONG Index, PinId;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
DPRINT("BdaInitFilter %p\n", pBdaFilterTemplate);
|
|
|
|
/* check input parameters */
|
|
if (!pKSFilter)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* get parent filter factory */
|
|
FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
|
|
|
|
/* sanity check */
|
|
ASSERT(FilterFactory);
|
|
|
|
/* find instance entry */
|
|
InstanceEntry = GetFilterInstanceEntry(FilterFactory);
|
|
|
|
/* sanity check */
|
|
ASSERT(InstanceEntry);
|
|
|
|
if (!pBdaFilterTemplate)
|
|
{
|
|
/* use template from BdaCreateFilterFactoryEx */
|
|
pBdaFilterTemplate = InstanceEntry->FilterTemplate;
|
|
}
|
|
|
|
/* now create the pins */
|
|
for(Index = 0; Index < pBdaFilterTemplate->pFilterDescriptor->PinDescriptorsCount; Index++)
|
|
{
|
|
/* create the pin */
|
|
Status = BdaCreatePin(pKSFilter, Index, &PinId);
|
|
|
|
/* check for success */
|
|
if (!NT_SUCCESS(Status))
|
|
break;
|
|
}
|
|
|
|
/* done */
|
|
return Status;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaCreateTopology(
|
|
IN PKSFILTER pKSFilter,
|
|
IN ULONG InputPinId,
|
|
IN ULONG OutputPinId)
|
|
{
|
|
PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
|
|
PKSFILTERFACTORY FilterFactory;
|
|
KSTOPOLOGY_CONNECTION Connection;
|
|
|
|
DPRINT("BdaCreateTopology\n");
|
|
|
|
/* check input parameters */
|
|
if (!pKSFilter)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* get parent filter factory */
|
|
FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
|
|
|
|
/* sanity check */
|
|
ASSERT(FilterFactory);
|
|
|
|
/* find instance entry */
|
|
InstanceEntry = GetFilterInstanceEntry(FilterFactory);
|
|
|
|
if (!InstanceEntry)
|
|
{
|
|
/* the filter was not initialized with BDA */
|
|
return STATUS_NOT_FOUND;
|
|
}
|
|
|
|
if (InputPinId >= InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount ||
|
|
OutputPinId >= InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount)
|
|
{
|
|
/* invalid pin id */
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* initialize topology connection */
|
|
Connection.FromNode = KSFILTER_NODE;
|
|
Connection.ToNode = KSFILTER_NODE;
|
|
Connection.FromNodePin = InputPinId;
|
|
Connection.ToNodePin = OutputPinId;
|
|
|
|
/* add the connection */
|
|
return KsFilterAddTopologyConnections(pKSFilter, 1, &Connection);
|
|
}
|
|
|
|
/*
|
|
@unimplemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaDeletePin(
|
|
IN PKSFILTER pKSFilter,
|
|
IN ULONG *pulPinId)
|
|
{
|
|
UNIMPLEMENTED;
|
|
DPRINT("BdaDeletePin\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaFilterFactoryUpdateCacheData(
|
|
IN PKSFILTERFACTORY FilterFactory,
|
|
IN const KSFILTER_DESCRIPTOR *FilterDescriptor OPTIONAL)
|
|
{
|
|
DPRINT("BdaFilterFactoryUpdateCacheData\n");
|
|
return KsFilterFactoryUpdateCacheData(FilterFactory, FilterDescriptor);
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaGetChangeState(
|
|
IN PIRP Irp,
|
|
OUT BDA_CHANGE_STATE *ChangeState)
|
|
{
|
|
DPRINT("BdaGetChangeState\n");
|
|
|
|
if (Irp && ChangeState)
|
|
{
|
|
*ChangeState = BDA_CHANGES_COMPLETE;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* invalid parameters supplied */
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaMethodCreateTopology(
|
|
IN PIRP Irp,
|
|
IN KSMETHOD *pKSMethod,
|
|
OPTIONAL PVOID pvIgnored)
|
|
{
|
|
PKSFILTER Filter;
|
|
PKSP_BDA_NODE_PIN Node;
|
|
|
|
DPRINT("BdaMethodCreateTopology\n");
|
|
|
|
/* check input parameters */
|
|
if (!Irp || !pKSMethod)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* get filter */
|
|
Filter = KsGetFilterFromIrp(Irp);
|
|
|
|
/* sanity check */
|
|
ASSERT(Filter);
|
|
|
|
/* get method request */
|
|
Node = (PKSP_BDA_NODE_PIN)pKSMethod;
|
|
|
|
/* create the topology */
|
|
return BdaCreateTopology(Filter, Node->ulInputPinId, Node->ulOutputPinId);
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaMethodDeletePin(
|
|
IN PIRP Irp,
|
|
IN KSMETHOD *pKSMethod,
|
|
OPTIONAL PVOID pvIgnored)
|
|
{
|
|
DPRINT("BdaMethodDeletePin\n");
|
|
|
|
if (!Irp)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
@unimplemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaPropertyGetControllingPinId(
|
|
IN PIRP Irp,
|
|
IN KSP_BDA_NODE_PIN *pProperty,
|
|
OUT ULONG *pulControllingPinId)
|
|
{
|
|
UNIMPLEMENTED;
|
|
DPRINT("BdaPropertyGetControllingPinId\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaPropertyGetPinControl(
|
|
IN PIRP Irp,
|
|
IN KSPROPERTY *pKSProperty,
|
|
OUT ULONG *pulProperty)
|
|
{
|
|
PKSPIN Pin;
|
|
PKSFILTER Filter;
|
|
PKSFILTERFACTORY FilterFactory;
|
|
PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
|
|
|
|
DPRINT("BdaPropertyGetPinControl\n");
|
|
|
|
/* first get the pin */
|
|
Pin = KsGetPinFromIrp(Irp);
|
|
ASSERT(Pin);
|
|
|
|
/* now get the parent filter */
|
|
Filter = KsPinGetParentFilter(Pin);
|
|
ASSERT(Filter);
|
|
|
|
/* get parent filter factory */
|
|
FilterFactory = KsFilterGetParentFilterFactory(Filter);
|
|
ASSERT(FilterFactory);
|
|
|
|
/* find instance entry */
|
|
InstanceEntry = GetFilterInstanceEntry(FilterFactory);
|
|
ASSERT(InstanceEntry);
|
|
|
|
/* sanity check */
|
|
pKSProperty++;
|
|
ASSERT(pKSProperty->Id == KSPROPERTY_BDA_PIN_TYPE);
|
|
|
|
/* store pin id */
|
|
*pulProperty = Pin->Id;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
@unimplemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaPropertyNodeDescriptors(
|
|
IN PIRP Irp,
|
|
IN KSPROPERTY *pKSProperty,
|
|
OUT BDANODE_DESCRIPTOR *pNodeDescriptorProperty)
|
|
{
|
|
UNIMPLEMENTED;
|
|
DPRINT("BdaPropertyNodeDescriptors\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/*
|
|
@unimplemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaPropertyNodeEvents(
|
|
IN PIRP Irp,
|
|
IN KSP_NODE *pKSProperty,
|
|
OUT GUID *pguidProperty)
|
|
{
|
|
UNIMPLEMENTED;
|
|
DPRINT("BdaPropertyNodeEvents\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/*
|
|
@unimplemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaPropertyNodeMethods(
|
|
IN PIRP Irp,
|
|
IN KSP_NODE *pKSProperty,
|
|
OUT GUID *pguidProperty)
|
|
{
|
|
UNIMPLEMENTED;
|
|
DPRINT("BdaPropertyNodeMethods\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/*
|
|
@unimplemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaPropertyNodeProperties(
|
|
IN PIRP Irp,
|
|
IN KSP_NODE *pKSProperty,
|
|
OUT GUID *pguidProperty)
|
|
{
|
|
UNIMPLEMENTED;
|
|
DPRINT("BdaPropertyNodeProperties\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaPropertyNodeTypes(
|
|
IN PIRP Irp,
|
|
IN KSPROPERTY *pKSProperty,
|
|
OUT ULONG *pulProperty)
|
|
{
|
|
PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
|
|
PKSFILTERFACTORY FilterFactory;
|
|
PKSFILTER pKSFilter;
|
|
PIO_STACK_LOCATION IoStack;
|
|
ULONG Index;
|
|
|
|
DPRINT("BdaPropertyNodeTypes\n");
|
|
|
|
/* check input parameter */
|
|
if (!Irp || !pKSProperty)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* first get the filter */
|
|
pKSFilter = KsGetFilterFromIrp(Irp);
|
|
|
|
/* sanity check */
|
|
ASSERT(pKSFilter);
|
|
|
|
/* get parent filter factory */
|
|
FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
|
|
|
|
/* sanity check */
|
|
ASSERT(FilterFactory);
|
|
|
|
/* find instance entry */
|
|
InstanceEntry = GetFilterInstanceEntry(FilterFactory);
|
|
ASSERT(InstanceEntry);
|
|
|
|
/* get current irp stack */
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
/* are there node types provided */
|
|
if (!pulProperty)
|
|
{
|
|
/* no node entry array provided */
|
|
Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount * sizeof(ULONG);
|
|
Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
|
|
return STATUS_MORE_ENTRIES;
|
|
}
|
|
|
|
if (InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount * sizeof(ULONG) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
|
|
{
|
|
/* buffer too small */
|
|
Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount * sizeof(ULONG);
|
|
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
/* now copy all descriptors */
|
|
for(Index = 0; Index < InstanceEntry->FilterTemplate->pFilterDescriptor->NodeDescriptorsCount; Index++)
|
|
{
|
|
/* use the index as the type */
|
|
pulProperty[Index] = Index;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaPropertyPinTypes(
|
|
IN PIRP Irp,
|
|
IN KSPROPERTY *pKSProperty,
|
|
OUT ULONG *pulProperty)
|
|
{
|
|
PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
|
|
PKSFILTERFACTORY FilterFactory;
|
|
PKSFILTER pKSFilter;
|
|
PIO_STACK_LOCATION IoStack;
|
|
ULONG Index;
|
|
|
|
DPRINT("BdaPropertyPinTypes\n");
|
|
|
|
/* check input parameter */
|
|
if (!Irp || !pKSProperty)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* first get the filter */
|
|
pKSFilter = KsGetFilterFromIrp(Irp);
|
|
|
|
/* sanity check */
|
|
ASSERT(pKSFilter);
|
|
|
|
/* get parent filter factory */
|
|
FilterFactory = KsFilterGetParentFilterFactory(pKSFilter);
|
|
|
|
/* sanity check */
|
|
ASSERT(FilterFactory);
|
|
|
|
/* find instance entry */
|
|
InstanceEntry = GetFilterInstanceEntry(FilterFactory);
|
|
ASSERT(InstanceEntry);
|
|
|
|
/* get current irp stack */
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
/* are there node types provided */
|
|
if (!pKSProperty)
|
|
{
|
|
/* no node entry array provided */
|
|
Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount * sizeof(ULONG);
|
|
Irp->IoStatus.Status = STATUS_MORE_ENTRIES;
|
|
return STATUS_MORE_ENTRIES;
|
|
}
|
|
|
|
if (InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount * sizeof(ULONG) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
|
|
{
|
|
/* buffer too small */
|
|
Irp->IoStatus.Information = InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount * sizeof(ULONG);
|
|
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
/* now copy all descriptors */
|
|
for(Index = 0; Index < InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount; Index++)
|
|
{
|
|
/* use the index as the type */
|
|
pulProperty[Index] = Index;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaPropertyTemplateConnections(
|
|
IN PIRP Irp,
|
|
IN KSPROPERTY *pKSProperty,
|
|
OUT KSTOPOLOGY_CONNECTION *pConnectionProperty)
|
|
{
|
|
PBDA_FILTER_INSTANCE_ENTRY FilterInstance;
|
|
PKSFILTER Filter;
|
|
PIO_STACK_LOCATION IoStack;
|
|
ULONG Index;
|
|
|
|
DPRINT("BdaPropertyTemplateConnections\n");
|
|
|
|
/* validate parameters */
|
|
if (!Irp || !pKSProperty)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* first get the filter */
|
|
Filter = KsGetFilterFromIrp(Irp);
|
|
|
|
/* sanity check */
|
|
ASSERT(Filter);
|
|
|
|
/* verify filter has been registered with BDA */
|
|
FilterInstance = GetFilterInstanceEntry(KsFilterGetParentFilterFactory(Filter));
|
|
|
|
if (!FilterInstance)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
/* get current irp stack */
|
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
if (!pConnectionProperty)
|
|
{
|
|
/* caller needs the size first */
|
|
Irp->IoStatus.Information = FilterInstance->FilterTemplate->pFilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION);
|
|
Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
/* sanity check */
|
|
ASSERT(FilterInstance->FilterTemplate->pFilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION) <= IoStack->Parameters.DeviceIoControl.OutputBufferLength);
|
|
|
|
for(Index = 0; Index < FilterInstance->FilterTemplate->pFilterDescriptor->ConnectionsCount; Index++)
|
|
{
|
|
/* sanity check */
|
|
ASSERT(FilterInstance->FilterTemplate->pFilterDescriptor->Connections);
|
|
|
|
/* copy connection */
|
|
RtlMoveMemory(pConnectionProperty, &FilterInstance->FilterTemplate->pFilterDescriptor->Connections[Index], sizeof(KSTOPOLOGY_CONNECTION));
|
|
}
|
|
|
|
/* store result */
|
|
Irp->IoStatus.Information = FilterInstance->FilterTemplate->pFilterDescriptor->ConnectionsCount * sizeof(KSTOPOLOGY_CONNECTION);
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
|
|
/* done */
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaStartChanges(IN PIRP Irp)
|
|
{
|
|
DPRINT("BdaStartChanges\n");
|
|
|
|
if (Irp)
|
|
return STATUS_SUCCESS;
|
|
else
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaUninitFilter(IN PKSFILTER pKSFilter)
|
|
{
|
|
DPRINT("BdaUninitFilter\n");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
@implemented
|
|
*/
|
|
NTSTATUS
|
|
NTAPI
|
|
BdaValidateNodeProperty(
|
|
IN PIRP Irp,
|
|
IN KSPROPERTY *KSProperty)
|
|
{
|
|
DPRINT("BdaValidateNodeProperty\n");
|
|
|
|
/* check for valid parameter */
|
|
if (Irp && KSProperty)
|
|
return STATUS_SUCCESS;
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|