reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp
Serge Gautherie c6c6c62cb5
[PORTCLS] Remove meaningless YDEBUG (#5858)
Addendum to b77ebc4 (r54584).
Follow-up of #5818.
2023-11-02 13:14:12 +01:00

992 lines
35 KiB
C++

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel Streaming
* FILE: drivers/wdm/audio/backpln/portcls/api.cpp
* PURPOSE: Port api functions
* PROGRAMMER: Johannes Anderwald
*/
#include "private.hpp"
#define NDEBUG
#include <debug.h>
NTSTATUS
NTAPI
KsoDispatchCreateWithGenericFactory(
LONG Unknown,
PIRP Irp)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
IIrpTarget *
NTAPI
KsoGetIrpTargetFromFileObject(
PFILE_OBJECT FileObject)
{
PC_ASSERT(FileObject);
// IrpTarget is stored in FsContext
return (IIrpTarget*)FileObject->FsContext;
}
IIrpTarget *
NTAPI
KsoGetIrpTargetFromIrp(
PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
// IIrpTarget is stored in Context member
return (IIrpTarget*)IoStack->FileObject->FsContext;
}
NTSTATUS
NTAPI
PcHandleEnableEventWithTable(
IN PIRP Irp,
IN PSUBDEVICE_DESCRIPTOR Descriptor)
{
// store descriptor
KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
// FIXME seh probing
return KsEnableEvent(Irp, Descriptor->EventSetCount, Descriptor->EventSet, NULL, KSEVENTS_NONE, NULL);
}
NTSTATUS
NTAPI
PcHandleDisableEventWithTable(
IN PIRP Irp,
IN PSUBDEVICE_DESCRIPTOR Descriptor)
{
// store descriptor
KSEVENT_ITEM_IRP_STORAGE(Irp) = (PKSEVENT_ITEM)Descriptor;
// FIXME seh probing
return KsDisableEvent(Irp, Descriptor->EventList, KSEVENTS_SPINLOCK, (PVOID)Descriptor->EventListLock);
}
NTSTATUS
NTAPI
PcHandlePropertyWithTable(
IN PIRP Irp,
IN ULONG PropertySetCount,
IN PKSPROPERTY_SET PropertySet,
IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
{
PIO_STACK_LOCATION IoStack;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
{
// certainly an invalid request
return STATUS_INVALID_PARAMETER;
}
// store device descriptor
KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
// then try KsPropertyHandler
return KsPropertyHandler(Irp, PropertySetCount, PropertySet);
}
VOID
NTAPI
PcAcquireFormatResources(
LONG Unknown,
LONG Unknown2,
LONG Unknown3,
LONG Unknown4)
{
UNIMPLEMENTED;
}
NTSTATUS
PcAddToEventTable(
PVOID Ptr,
LONG Unknown2,
ULONG Length,
LONG Unknown3,
LONG Unknown4,
LONG Unknown5,
LONG Unknown6,
LONG Unknown7)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
PropertyItemDispatch(
IN PIRP Irp,
IN PKSIDENTIFIER Request,
IN OUT PVOID Data)
{
PPCPROPERTY_REQUEST PropertyRequest;
PSUBDEVICE_DESCRIPTOR Descriptor;
PKSPROPERTY Property;
PPCNODE_DESCRIPTOR NodeDescriptor;
PKSNODEPROPERTY NodeProperty;
PKSPROPERTY_SET PropertySet;
PPCPROPERTY_ITEM PropertyItem;
PPCAUTOMATION_TABLE NodeAutomation;
PIO_STACK_LOCATION IoStack;
ULONG InstanceSize, ValueSize, Index;
PVOID Instance;
NTSTATUS Status;
// allocate a property request
PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
if (!PropertyRequest)
return STATUS_INSUFFICIENT_RESOURCES;
// grab device descriptor
Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
// get current irp stack
IoStack = IoGetCurrentIrpStackLocation(Irp);
// get input property request
Property = (PKSPROPERTY)Request;
// get property set
PropertySet = (PKSPROPERTY_SET)KSPROPERTY_SET_IRP_STORAGE(Irp);
// sanity check
PC_ASSERT(Descriptor);
PC_ASSERT(Descriptor->UnknownMiniport);
// get instance / value size
InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength;
Instance = Request;
ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
// initialize property request
PropertyRequest->MajorTarget = Descriptor->UnknownMiniport;
PropertyRequest->MinorTarget = Descriptor->UnknownStream;
PropertyRequest->Irp = Irp;
PropertyRequest->Verb = Property->Flags;
// check if this is filter / pin property request
if (!(Property->Flags & KSPROPERTY_TYPE_TOPOLOGY))
{
// adjust input buffer size
InstanceSize -= sizeof(KSPROPERTY);
Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSPROPERTY));
// filter / pin property request dont use node field
PropertyRequest->Node = MAXULONG;
}
else if (InstanceSize >= sizeof(KSNODEPROPERTY))
{
// request is for a node
InstanceSize -= sizeof(KSNODEPROPERTY);
Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSNODEPROPERTY));
// cast node property request
NodeProperty = (PKSNODEPROPERTY)Request;
// store node id
PropertyRequest->Node = NodeProperty->NodeId;
}
else
{
// invalid buffer size
FreeItem(PropertyRequest, TAG_PORTCLASS);
return STATUS_INVALID_BUFFER_SIZE;
}
// store instance size
PropertyRequest->InstanceSize = InstanceSize;
PropertyRequest->Instance = (InstanceSize != 0 ? Instance : NULL);
// store value size
PropertyRequest->ValueSize = ValueSize;
PropertyRequest->Value = Data;
// now scan the property set for the attached property set item stored in Relations member
if (PropertySet)
{
// sanity check
PC_ASSERT(IsEqualGUIDAligned(Property->Set, *PropertySet->Set));
for(Index = 0; Index < PropertySet->PropertiesCount; Index++)
{
// check if they got the same property id
if (PropertySet->PropertyItem[Index].PropertyId == Property->Id)
{
// found item
PropertyRequest->PropertyItem = (const PCPROPERTY_ITEM*)PropertySet->PropertyItem[Index].Relations;
// done
break;
}
}
}
// check if there has been a property set item attached
if (!PropertyRequest->PropertyItem)
{
// is topology node id valid
if (PropertyRequest->Node < Descriptor->DeviceDescriptor->NodeCount)
{
// get node descriptor
NodeDescriptor = (PPCNODE_DESCRIPTOR) ((ULONG_PTR)Descriptor->DeviceDescriptor->Nodes + PropertyRequest->Node * Descriptor->DeviceDescriptor->NodeSize);
// get node automation table
NodeAutomation = (PPCAUTOMATION_TABLE)NodeDescriptor->AutomationTable;
// has it got a automation table
if (NodeAutomation)
{
// now scan the properties and check if it supports this request
PropertyItem = (PPCPROPERTY_ITEM)NodeAutomation->Properties;
for(Index = 0; Index < NodeAutomation->PropertyCount; Index++)
{
// are they same property
if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Set))
{
if (PropertyItem->Id == Property->Id)
{
// found match
PropertyRequest->PropertyItem = PropertyItem;
DPRINT("Using property item %p\n", PropertyItem);
// done
break;
}
}
// move to next property item
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeAutomation->PropertyItemSize);
}
}
}
}
if (PropertyRequest->PropertyItem && PropertyRequest->PropertyItem->Handler)
{
// now call the handler
UNICODE_STRING GuidBuffer;
RtlStringFromGUID(Property->Set, &GuidBuffer);
DPRINT("Calling Node %lu MajorTarget %p MinorTarget %p PropertySet %S PropertyId %lu PropertyFlags %lx InstanceSize %lu ValueSize %lu Handler %p PropertyRequest %p PropertyItemFlags %lx PropertyItemId %lu\n",
PropertyRequest->Node, PropertyRequest->MajorTarget, PropertyRequest->MinorTarget, GuidBuffer.Buffer, Property->Id, Property->Flags, PropertyRequest->InstanceSize, PropertyRequest->ValueSize,
PropertyRequest->PropertyItem->Handler, PropertyRequest, PropertyRequest->PropertyItem->Flags, PropertyRequest->PropertyItem->Id);
RtlFreeUnicodeString(&GuidBuffer);
Status = PropertyRequest->PropertyItem->Handler(PropertyRequest);
DPRINT("Status %lx ValueSize %lu Information %lu\n", Status, PropertyRequest->ValueSize, Irp->IoStatus.Information);
Irp->IoStatus.Information = PropertyRequest->ValueSize;
if (Status != STATUS_PENDING)
{
// free property request
FreeItem(PropertyRequest, TAG_PORTCLASS);
}
}
else
{
FreeItem(PropertyRequest, TAG_PORTCLASS);
Status = STATUS_NOT_FOUND;
}
/* done */
return Status;
}
NTSTATUS
PcAddToPropertyTable(
IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
IN PPCPROPERTY_ITEM PropertyItem,
IN ULONG bNode)
{
ULONG bFound = FALSE;
ULONG Index, PropertySetIndex, PropertySetItemIndex;
PKSPROPERTY_SET NewPropertySet;
PKSPROPERTY_ITEM FilterPropertyItem, NewFilterPropertyItem;
LPGUID Guid;
//UNICODE_STRING GuidBuffer;
ASSERT(PropertyItem->Set);
// RtlStringFromGUID(*PropertyItem->Set, &GuidBuffer);
// DPRINT1("PcAddToPropertyTable Adding Item Set %S Id %lu Flags %lx\n", GuidBuffer.Buffer, PropertyItem->Id, PropertyItem->Flags);
//DPRINT1("FilterPropertySetCount %lu\n", SubDeviceDescriptor->FilterPropertySetCount);
// first step check if the property set is present already
for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySetCount; Index++)
{
//RtlStringFromGUID(*SubDeviceDescriptor->FilterPropertySet[Index].Set, &GuidBuffer);
//DPRINT1("FilterProperty Set %S PropertyCount %lu\n", GuidBuffer.Buffer, SubDeviceDescriptor->FilterPropertySet[Index].PropertiesCount);
if (IsEqualGUIDAligned(*SubDeviceDescriptor->FilterPropertySet[Index].Set, *PropertyItem->Set))
{
// property set is already present
bFound = TRUE;
PropertySetIndex = Index;
// break out
break;
}
}
// is the property set present
if (!bFound)
{
// need to allocate a property set
NewPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySetCount + 1) * sizeof(KSPROPERTY_SET), TAG_PORTCLASS);
if (!NewPropertySet)
{
// out of memory
return STATUS_INSUFFICIENT_RESOURCES;
}
// need to allocate property set guid
Guid = (LPGUID)AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS);
if (!Guid)
{
// out of memory
FreeItem(NewPropertySet, TAG_PORTCLASS);
return STATUS_INSUFFICIENT_RESOURCES;
}
// are any existing property sets
if (SubDeviceDescriptor->FilterPropertySetCount)
{
// copy property sets
RtlMoveMemory(NewPropertySet, SubDeviceDescriptor->FilterPropertySet, SubDeviceDescriptor->FilterPropertySetCount * sizeof(KSPROPERTY_SET));
// release memory
FreeItem(SubDeviceDescriptor->FilterPropertySet, TAG_PORTCLASS);
}
// store new property set descriptors
SubDeviceDescriptor->FilterPropertySet = NewPropertySet;
// store index
PropertySetIndex = SubDeviceDescriptor->FilterPropertySetCount;
// increment property set count
SubDeviceDescriptor->FilterPropertySetCount++;
// copy property guid
RtlMoveMemory(Guid, PropertyItem->Set, sizeof(GUID));
// initialize property set
SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].Set = Guid;
SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount = 0;
}
// as the property set has been identified, now search for duplicate property set item entries
FilterPropertyItem = (PKSPROPERTY_ITEM)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem;
bFound = FALSE;
for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount; Index++)
{
// now search for an equal property set item
if (FilterPropertyItem->PropertyId == PropertyItem->Id)
{
// found existing property set item
bFound = TRUE;
PropertySetItemIndex = Index;
break;
}
// move to next entry
FilterPropertyItem++;
}
if (!bFound)
{
// need to allocate memory for new property set item
NewFilterPropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount + 1) * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
if (!NewFilterPropertyItem)
{
// out of memory
return STATUS_INSUFFICIENT_RESOURCES;
}
// are any existing property set items
if (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount)
{
// copy property item sets
RtlMoveMemory(NewFilterPropertyItem,
(PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem,
SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount * sizeof(KSPROPERTY_ITEM));
// release old descriptors
FreeItem((PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem, TAG_PORTCLASS);
}
// store new descriptor
SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem = NewFilterPropertyItem;
// store index
PropertySetItemIndex = SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount;
// increment property item set count
SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount++;
// now initialize property item
FilterPropertyItem = (PKSPROPERTY_ITEM)&SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex];
FilterPropertyItem->PropertyId = PropertyItem->Id;
FilterPropertyItem->MinProperty = sizeof(KSPROPERTY);
FilterPropertyItem->MinData = 0;
// are any set operations supported
if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_SET)
{
// setup handler
FilterPropertyItem->SetPropertyHandler = PropertyItemDispatch;
}
// are set operation supported
if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
{
// setup handler
FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
}
// are get operations supported
if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
{
// setup handler
FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
}
// are basic support operations supported
if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_BASICSUPPORT)
{
// setup handler
FilterPropertyItem->SupportHandler = PropertyItemDispatch;
}
if (!bNode)
{
// store property item in relations
// only store property item of filter properties / pin properties
// because filter & pin properties do not require a specific context
// on the other hand node properties are specifically bound to a node
FilterPropertyItem->Relations = (const KSPROPERTY*)PropertyItem;
}
}
else
{
// property set item handler already present
if (bNode)
{
// filter & pin properties should not be exposed on a node
ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations == NULL);
}
else
{
// node properties should not be exposed on a filter & pin
ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations != NULL);
}
}
// done
return STATUS_SUCCESS;
}
NTSTATUS
PcCaptureFormat(
LONG Unknown,
LONG Unknown2,
LONG Unknown3,
LONG Unknown4)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
VOID
DumpAutomationTable(
IN PPCAUTOMATION_TABLE AutomationTable,
IN LPCWSTR DebugPrefix,
IN LPCWSTR DebugIndentation)
{
PPCPROPERTY_ITEM PropertyItem;
PPCEVENT_ITEM EventItem;
PPCMETHOD_ITEM MethodItem;
ULONG Index;
UNICODE_STRING GuidString;
if (!AutomationTable)
{
// no table
return;
}
DPRINT("=====================================================================\n");
DPRINT("%S%S AutomationTable %p\n", DebugIndentation, DebugPrefix, AutomationTable);
DPRINT("%S%S PropertyCount %lu\n", DebugIndentation, DebugPrefix, AutomationTable->PropertyCount);
DPRINT("%S%S EventCount %lu\n", DebugIndentation, DebugPrefix, AutomationTable->EventCount);
DPRINT("%S%S MethodCount %lu\n", DebugIndentation, DebugPrefix, AutomationTable->MethodCount);
// print properties
if (AutomationTable->PropertyCount)
{
if (AutomationTable->PropertyItemSize >= sizeof(PCPROPERTY_ITEM))
{
// get property item
PropertyItem = (PPCPROPERTY_ITEM)AutomationTable->Properties;
// sanity check
ASSERT(PropertyItem);
// display all properties associated
for(Index = 0; Index < AutomationTable->PropertyCount; Index++)
{
// convert to printable string
RtlStringFromGUID(*PropertyItem->Set, &GuidString);
DPRINT("%SPropertyItemIndex %lu %p GUID %S Id %u Flags %x\n", DebugIndentation, Index, PropertyItem, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
RtlFreeUnicodeString(&GuidString);
// move to next item
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + AutomationTable->PropertyItemSize);
}
}
else
{
DPRINT1("DRIVER BUG: property item must be at least %lu but got %lu\n", sizeof(PCPROPERTY_ITEM), AutomationTable->PropertyItemSize);
}
}
// print events
if (AutomationTable->EventCount)
{
if (AutomationTable->EventItemSize >= sizeof(PCEVENT_ITEM))
{
// get first event item
EventItem = (PPCEVENT_ITEM)AutomationTable->Events;
// sanity check
ASSERT(EventItem);
for(Index = 0; Index < AutomationTable->EventCount; Index++)
{
// convert to printable string
RtlStringFromGUID(*EventItem->Set, &GuidString);
DPRINT("%SEventItemIndex %lu %p GUID %S Id %u Flags %x\n", DebugIndentation, Index, EventItem, GuidString.Buffer, EventItem->Id, EventItem->Flags);
RtlFreeUnicodeString(&GuidString);
// move to next item
EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + AutomationTable->EventItemSize);
}
}
else
{
DPRINT1("DRIVER BUG: event item must be at least %lu but got %lu\n", sizeof(PCEVENT_ITEM), AutomationTable->EventItemSize);
}
}
// print methods
if (AutomationTable->MethodCount)
{
if (AutomationTable->MethodItemSize >= sizeof(PCMETHOD_ITEM))
{
// get first event item
MethodItem = (PPCMETHOD_ITEM)AutomationTable->Methods;
// sanity check
ASSERT(MethodItem);
for(Index = 0; Index < AutomationTable->MethodCount; Index++)
{
// convert to printable string
RtlStringFromGUID(*MethodItem->Set, &GuidString);
DPRINT("%SMethodItemIndex %lu %p GUID %S Id %u Flags %x\n", DebugIndentation, Index, MethodItem, GuidString.Buffer, MethodItem->Id, MethodItem->Flags);
RtlFreeUnicodeString(&GuidString);
// move to next item
MethodItem = (PPCMETHOD_ITEM)((ULONG_PTR)MethodItem + AutomationTable->MethodItemSize);
}
}
else
{
DPRINT1("DRIVER BUG: method item must be at least %lu but got %lu\n", sizeof(PCEVENT_ITEM), AutomationTable->MethodItemSize);
}
}
DPRINT("=====================================================================\n");
}
VOID
DumpFilterDescriptor(
IN PPCFILTER_DESCRIPTOR FilterDescription)
{
ULONG Index;
WCHAR Buffer[30];
PPCPIN_DESCRIPTOR PinDescriptor;
PPCNODE_DESCRIPTOR NodeDescriptor;
DPRINT("======================\n");
DPRINT("Descriptor Automation Table %p\n",FilterDescription->AutomationTable);
DPRINT("PinCount %lu PinSize %lu StandardSize %lu\n", FilterDescription->PinCount, FilterDescription->PinSize, sizeof(PCPIN_DESCRIPTOR));
DPRINT("NodeCount %lu NodeSize %lu StandardSize %lu\n", FilterDescription->NodeCount, FilterDescription->NodeSize, sizeof(PCNODE_DESCRIPTOR));
// dump filter description table
DumpAutomationTable((PPCAUTOMATION_TABLE)FilterDescription->AutomationTable, L"Filter", L"");
if (FilterDescription->PinCount)
{
if (FilterDescription->PinSize >= sizeof(PCPIN_DESCRIPTOR))
{
// get first pin
PinDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
// sanity check
ASSERT(PinDescriptor);
for(Index = 0; Index < FilterDescription->PinCount; Index++)
{
// print prefix
swprintf(Buffer, L"PinIndex %lu", Index);
// dump automation table
DumpAutomationTable((PPCAUTOMATION_TABLE)PinDescriptor->AutomationTable, Buffer, L" ");
// move to next pin descriptor
PinDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)PinDescriptor + FilterDescription->PinSize);
}
}
else
{
DPRINT1("DRIVER BUG: pin size smaller than minimum size\n");
}
}
if (FilterDescription->Nodes)
{
if (FilterDescription->NodeSize >= sizeof(PCNODE_DESCRIPTOR))
{
// get first descriptor
NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
// sanity check
ASSERT(NodeDescriptor);
for(Index = 0; Index < FilterDescription->NodeCount; Index++)
{
// print prefix
swprintf(Buffer, L"NodeIndex %lu", Index);
// dump automation table
DumpAutomationTable((PPCAUTOMATION_TABLE)NodeDescriptor->AutomationTable, Buffer, L" ");
// move to next node descriptor
NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
}
}
else
{
DPRINT1("DRIVER BUG: node size smaller than standard descriptor size\n");
}
}
DPRINT("ConnectionCount: %lu\n", FilterDescription->ConnectionCount);
if (FilterDescription->ConnectionCount)
{
DPRINT("------ Start of Nodes Connections ----------------\n");
for(Index = 0; Index < FilterDescription->ConnectionCount; Index++)
{
DPRINT1("Index %ld FromPin %ld FromNode %ld -> ToPin %ld ToNode %ld\n", Index,
FilterDescription->Connections[Index].FromNodePin,
FilterDescription->Connections[Index].FromNode,
FilterDescription->Connections[Index].ToNodePin,
FilterDescription->Connections[Index].ToNode);
}
DPRINT("------ End of Nodes Connections----------------\n");
}
DPRINT1("======================\n");
}
NTSTATUS
NTAPI
PcCreateSubdeviceDescriptor(
OUT SUBDEVICE_DESCRIPTOR ** OutSubdeviceDescriptor,
IN ULONG InterfaceCount,
IN GUID * InterfaceGuids,
IN ULONG IdentifierCount,
IN KSIDENTIFIER *Identifier,
IN ULONG FilterPropertiesCount,
IN KSPROPERTY_SET * FilterProperties,
IN ULONG Unknown1,
IN ULONG Unknown2,
IN ULONG PinPropertiesCount,
IN KSPROPERTY_SET * PinProperties,
IN ULONG EventSetCount,
IN KSEVENT_SET * EventSet,
IN PPCFILTER_DESCRIPTOR FilterDescription)
{
SUBDEVICE_DESCRIPTOR * Descriptor;
ULONG Index, SubIndex;
NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
PPCPIN_DESCRIPTOR SrcDescriptor;
PPCNODE_DESCRIPTOR NodeDescriptor;
PPCPROPERTY_ITEM PropertyItem;
// allocate subdevice descriptor
Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
if (!Descriptor)
return STATUS_INSUFFICIENT_RESOURCES;
// initialize physical / symbolic link connection list
InitializeListHead(&Descriptor->SymbolicLinkList);
InitializeListHead(&Descriptor->PhysicalConnectionList);
//FIXME add driver category guids
Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
if (!Descriptor->Interfaces)
goto cleanup;
// copy interface guids
RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount);
Descriptor->InterfaceCount = InterfaceCount;
//DumpFilterDescriptor(FilterDescription);
// are any property sets supported by the portcls
if (FilterPropertiesCount)
{
// first allocate filter properties set
Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
if (! Descriptor->FilterPropertySet)
goto cleanup;
// now copy all filter property sets
Descriptor->FilterPropertySetCount = FilterPropertiesCount;
for(Index = 0; Index < FilterPropertiesCount; Index++)
{
// copy property set
RtlMoveMemory(&Descriptor->FilterPropertySet[Index], &FilterProperties[Index], sizeof(KSPROPERTY_SET));
if (Descriptor->FilterPropertySet[Index].PropertiesCount)
{
// copy property items to make sure they are dynamically allocated
Descriptor->FilterPropertySet[Index].PropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
if (!Descriptor->FilterPropertySet[Index].PropertyItem)
{
// no memory
goto cleanup;
}
// copy filter property items
RtlMoveMemory((PVOID)Descriptor->FilterPropertySet[Index].PropertyItem, FilterProperties[Index].PropertyItem, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM));
}
}
}
// now check if the filter descriptor supports filter properties
if (FilterDescription->AutomationTable)
{
// get first entry
PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
// copy driver filter property sets
for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
{
// add the property item
Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
// check for success
if (Status != STATUS_SUCCESS)
{
// goto cleanup
goto cleanup;
}
// move to next entry
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
}
}
// check if the filter has pins
if (FilterDescription->PinCount)
{
// allocate pin factory descriptors
Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS);
if (!Descriptor->Factory.KsPinDescriptor)
goto cleanup;
// allocate pin instance info
Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
if (!Descriptor->Factory.Instances)
goto cleanup;
// initialize pin factory descriptor
Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR);
// grab first entry
SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
// copy pin factories
for(Index = 0; Index < FilterDescription->PinCount; Index++)
{
// copy pin descriptor
RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
// initialize pin factory instance data
Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount;
Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount;
Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount;
// check if the descriptor has an automation table
if (SrcDescriptor->AutomationTable)
{
// it has, grab first entry
PropertyItem = (PPCPROPERTY_ITEM)SrcDescriptor->AutomationTable->Properties;
// now add all supported property items
for(SubIndex = 0; SubIndex < SrcDescriptor->AutomationTable->PropertyCount; SubIndex++)
{
// add the property item to the table
Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
// check for success
if (Status != STATUS_SUCCESS)
{
// goto cleanup
goto cleanup;
}
// move to next entry
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + SrcDescriptor->AutomationTable->PropertyItemSize);
}
}
// move to next entry
SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize);
}
}
// allocate topology descriptor
Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
if (!Descriptor->Topology)
goto cleanup;
// are there any connections
if (FilterDescription->ConnectionCount)
{
// allocate connection descriptor
Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
if (!Descriptor->Topology->TopologyConnections)
goto cleanup;
// copy connection descriptor
RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
// store connection count
Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
}
// does the filter have nodes
if (FilterDescription->NodeCount)
{
// allocate topology node types array
Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
if (!Descriptor->Topology->TopologyNodes)
goto cleanup;
// allocate topology node names array
Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
if (!Descriptor->Topology->TopologyNodesNames)
goto cleanup;
// grab first entry
NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
// iterate all nodes and copy node types / names and node properties
for(Index = 0; Index < FilterDescription->NodeCount; Index++)
{
// does it have a type
if (NodeDescriptor->Type)
{
// copy node type
RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
}
// does it have a node name
if (NodeDescriptor->Name)
{
// copy node name
RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
}
// check if has an automation table
if (NodeDescriptor->AutomationTable)
{
// grab first entry
PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
// copy all node properties into the global property set
for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
{
// add to property set
Status = PcAddToPropertyTable(Descriptor, PropertyItem, TRUE);
// check for success
if (Status != STATUS_SUCCESS)
{
// failed
goto cleanup;
}
// move to next property item
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
}
}
// move to next descriptor
NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
}
// now store the topology node count
Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
}
// store descriptor
Descriptor->DeviceDescriptor = FilterDescription;
// store result
*OutSubdeviceDescriptor = Descriptor;
// done
return STATUS_SUCCESS;
cleanup:
if (Descriptor)
{
if (Descriptor->Interfaces)
FreeItem(Descriptor->Interfaces, TAG_PORTCLASS);
if (Descriptor->Factory.KsPinDescriptor)
FreeItem(Descriptor->Factory.KsPinDescriptor, TAG_PORTCLASS);
FreeItem(Descriptor, TAG_PORTCLASS);
}
return Status;
}
NTSTATUS
NTAPI
PcValidateConnectRequest(
IN PIRP Irp,
IN KSPIN_FACTORY * Factory,
OUT PKSPIN_CONNECT * Connect)
{
return KsValidateConnectRequest(Irp, Factory->PinDescriptorCount, Factory->KsPinDescriptor, Connect);
}