KSDDKAPI NTSTATUS NTAPI KspPinPropertyHandler( IN PIRP Irp, IN PKSPROPERTY Property, IN OUT PVOID Data, IN ULONG DescriptorsCount, IN const KSPIN_DESCRIPTOR* Descriptors, IN ULONG DescriptorSize) { KSP_PIN * Pin; KSMULTIPLE_ITEM * Item; PIO_STACK_LOCATION IoStack; ULONG Size, Index; PVOID Buffer; PKSDATARANGE_AUDIO *WaveFormatOut; PKSDATAFORMAT_WAVEFORMATEX WaveFormatIn; PKEY_VALUE_PARTIAL_INFORMATION KeyInfo; const KSPIN_DESCRIPTOR *Descriptor; NTSTATUS Status = STATUS_NOT_SUPPORTED; ULONG Count; const PKSDATARANGE* DataRanges; LPGUID Guid; IoStack = IoGetCurrentIrpStackLocation(Irp); Buffer = Data; //DPRINT("KsPinPropertyHandler Irp %p Property %p Data %p DescriptorsCount %u Descriptor %p OutputLength %u Id %u\n", Irp, Property, Data, DescriptorsCount, Descriptor, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Property->Id); /* convert to PKSP_PIN */ Pin = (KSP_PIN*)Property; if (Property->Id != KSPROPERTY_PIN_CTYPES) { if (Pin->PinId >= DescriptorsCount) { /* invalid parameter */ return STATUS_INVALID_PARAMETER; } } else { (*(PULONG)Buffer) = DescriptorsCount; Irp->IoStatus.Information = sizeof(ULONG); return STATUS_SUCCESS; } if (DescriptorSize == sizeof(KSPIN_DESCRIPTOR)) { /* it is simple pin descriptor */ Descriptor = &Descriptors[Pin->PinId]; } else { /* get offset to pin descriptor */ Descriptor = &(((PKSPIN_DESCRIPTOR_EX)((ULONG_PTR)Descriptors + Pin->PinId * DescriptorSize))->PinDescriptor); } switch(Property->Id) { case KSPROPERTY_PIN_DATAFLOW: Size = sizeof(KSPIN_DATAFLOW); if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size) { Irp->IoStatus.Information = Size; Status = STATUS_BUFFER_TOO_SMALL; break; } *((KSPIN_DATAFLOW*)Buffer) = Descriptor->DataFlow; Irp->IoStatus.Information = sizeof(KSPIN_DATAFLOW); Status = STATUS_SUCCESS; break; case KSPROPERTY_PIN_DATARANGES: case KSPROPERTY_PIN_CONSTRAINEDDATARANGES: Size = sizeof(KSMULTIPLE_ITEM); DPRINT("Id %lu PinId %lu DataRangesCount %lu ConstrainedDataRangesCount %lu\n", Property->Id, Pin->PinId, Descriptor->DataRangesCount, Descriptor->ConstrainedDataRangesCount); if (Property->Id == KSPROPERTY_PIN_DATARANGES || Descriptor->ConstrainedDataRangesCount == 0) { DataRanges = Descriptor->DataRanges; Count = Descriptor->DataRangesCount; } else { DataRanges = Descriptor->ConstrainedDataRanges; Count = Descriptor->ConstrainedDataRangesCount; } for (Index = 0; Index < Count; Index++) { Size += ((DataRanges[Index]->FormatSize + 0x7) & ~0x7); } if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0) { /* buffer too small */ Irp->IoStatus.Information = Size; Status = STATUS_BUFFER_OVERFLOW; break; } Item = (KSMULTIPLE_ITEM*)Buffer; if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG)) { /* store the result size */ Item->Size = Size; Irp->IoStatus.Information = sizeof(ULONG); Status = STATUS_SUCCESS; break; } /* store descriptor size */ Item->Size = Size; Item->Count = Count; if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM)) { Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM); Status = STATUS_SUCCESS; break; } /* now copy all dataranges */ Data = (PUCHAR)(Item +1); /* alignment assert */ ASSERT(((ULONG_PTR)Data & 0x7) == 0); for (Index = 0; Index < Count; Index++) { UNICODE_STRING GuidString; /* convert the guid to string */ RtlStringFromGUID(&DataRanges[Index]->MajorFormat, &GuidString); DPRINT("Index %lu MajorFormat %S\n", Index, GuidString.Buffer); RtlStringFromGUID(&DataRanges[Index]->SubFormat, &GuidString); DPRINT("Index %lu SubFormat %S\n", Index, GuidString.Buffer); RtlStringFromGUID(&DataRanges[Index]->Specifier, &GuidString); DPRINT("Index %lu Specifier %S\n", Index, GuidString.Buffer); RtlStringFromGUID(&DataRanges[Index]->Specifier, &GuidString); DPRINT("Index %lu FormatSize %lu Flags %lu SampleSize %lu Reserved %lu KSDATAFORMAT %lu\n", Index, DataRanges[Index]->FormatSize, DataRanges[Index]->Flags, DataRanges[Index]->SampleSize, DataRanges[Index]->Reserved, sizeof(KSDATAFORMAT)); RtlMoveMemory(Data, DataRanges[Index], DataRanges[Index]->FormatSize); Data = ((PUCHAR)Data + DataRanges[Index]->FormatSize); /* alignment assert */ ASSERT(((ULONG_PTR)Data & 0x7) == 0); Data = (PVOID)(((ULONG_PTR)Data + 0x7) & ~0x7); } Status = STATUS_SUCCESS; Irp->IoStatus.Information = Size; break; case KSPROPERTY_PIN_INTERFACES: if (Descriptor->Interfaces) { /* use mediums provided by driver */ return KsHandleSizedListQuery(Irp, Descriptor->InterfacesCount, sizeof(KSPIN_MEDIUM), Descriptor->Interfaces); } else { /* use standard medium */ return KsHandleSizedListQuery(Irp, 1, sizeof(KSPIN_INTERFACE), &StandardPinInterface); } break; case KSPROPERTY_PIN_MEDIUMS: if (Descriptor->MediumsCount) { /* use mediums provided by driver */ return KsHandleSizedListQuery(Irp, Descriptor->MediumsCount, sizeof(KSPIN_MEDIUM), Descriptor->Mediums); } else { /* use standard medium */ return KsHandleSizedListQuery(Irp, 1, sizeof(KSPIN_MEDIUM), &StandardPinMedium); } break; case KSPROPERTY_PIN_COMMUNICATION: Size = sizeof(KSPIN_COMMUNICATION); if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size) { Irp->IoStatus.Information = Size; Status = STATUS_BUFFER_TOO_SMALL; break; } *((KSPIN_COMMUNICATION*)Buffer) = Descriptor->Communication; Status = STATUS_SUCCESS; Irp->IoStatus.Information = Size; break; case KSPROPERTY_PIN_CATEGORY: if (!Descriptor->Category) { /* no pin category */ return STATUS_NOT_FOUND; } /* check size */ Size = sizeof(GUID); if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size) { /* buffer too small */ Irp->IoStatus.Information = Size; Status = STATUS_BUFFER_TOO_SMALL; break; } /* copy category guid */ RtlMoveMemory(Buffer, Descriptor->Category, sizeof(GUID)); /* save result */ Status = STATUS_SUCCESS; Irp->IoStatus.Information = Size; break; case KSPROPERTY_PIN_NAME: if (Descriptor->Name) { /* use pin name */ Guid = (LPGUID)Descriptor->Name; } else { /* use pin category as fallback */ Guid = (LPGUID)Descriptor->Category; } if (!Guid) { /* no friendly name available */ return STATUS_NOT_FOUND; } /* read friendly name category name */ Status = KspReadMediaCategory(Guid, &KeyInfo); if (!NT_SUCCESS(Status)) { /* failed to read category */ Irp->IoStatus.Information = 0; break; } /* store required length */ Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR); /* check if buffer is too small */ if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength) { /* buffer too small */ Status = STATUS_BUFFER_OVERFLOW; FreeItem(KeyInfo); break; } /* copy result */ RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, &KeyInfo->Data, KeyInfo->DataLength); /* null terminate name */ ((LPWSTR)Irp->AssociatedIrp.SystemBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0'; /* free key info */ FreeItem(KeyInfo); break; case KSPROPERTY_PIN_PROPOSEDATAFORMAT: Size = sizeof(KSDATAFORMAT); if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size) { Irp->IoStatus.Information = Size; Status = STATUS_BUFFER_TOO_SMALL; break; } if (IoStack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(KSDATAFORMAT_WAVEFORMATEX)) { UNIMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED; Irp->IoStatus.Information = 0; break; } WaveFormatIn = (PKSDATAFORMAT_WAVEFORMATEX)Buffer; if (!Descriptor->DataRanges || !Descriptor->DataRangesCount) { Status = STATUS_UNSUCCESSFUL; Irp->IoStatus.Information = 0; break; } WaveFormatOut = (PKSDATARANGE_AUDIO*)Descriptor->DataRanges; for(Index = 0; Index < Descriptor->DataRangesCount; Index++) { if (WaveFormatOut[Index]->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO)) { UNIMPLEMENTED; continue; } if (WaveFormatOut[Index]->MinimumSampleFrequency > WaveFormatIn->WaveFormatEx.nSamplesPerSec || WaveFormatOut[Index]->MaximumSampleFrequency < WaveFormatIn->WaveFormatEx.nSamplesPerSec || WaveFormatOut[Index]->MinimumBitsPerSample > WaveFormatIn->WaveFormatEx.wBitsPerSample || WaveFormatOut[Index]->MaximumBitsPerSample < WaveFormatIn->WaveFormatEx.wBitsPerSample || WaveFormatOut[Index]->MaximumChannels < WaveFormatIn->WaveFormatEx.nChannels) { Irp->IoStatus.Status = STATUS_NO_MATCH; Irp->IoStatus.Information = 0; return STATUS_NO_MATCH; } else { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; return STATUS_SUCCESS; } } Status = STATUS_NO_MATCH; Irp->IoStatus.Information = 0; break; default: DPRINT1("Unhandled property request %x\n", Property->Id); Status = STATUS_NOT_IMPLEMENTED; Irp->IoStatus.Information = 0; } return Status; }
/* @implemented */ KSDDKAPI NTSTATUS NTAPI KsTopologyPropertyHandler( IN PIRP Irp, IN PKSPROPERTY Property, IN OUT PVOID Data, IN const KSTOPOLOGY* Topology) { KSP_NODE * Node; PIO_STACK_LOCATION IoStack; NTSTATUS Status; PKEY_VALUE_PARTIAL_INFORMATION KeyInfo; LPGUID Guid; IoStack = IoGetCurrentIrpStackLocation(Irp); DPRINT("KsTopologyPropertyHandler Irp %p Property %p Data %p Topology %p OutputLength %lu PropertyId %lu\n", Irp, Property, Data, Topology, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Property->Id); if (Property->Flags != KSPROPERTY_TYPE_GET) { Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; Irp->IoStatus.Information = 0; return STATUS_NOT_IMPLEMENTED; } switch(Property->Id) { case KSPROPERTY_TOPOLOGY_CATEGORIES: return KsHandleSizedListQuery(Irp, Topology->CategoriesCount, sizeof(GUID), Topology->Categories); case KSPROPERTY_TOPOLOGY_NODES: return KsHandleSizedListQuery(Irp, Topology->TopologyNodesCount, sizeof(GUID), Topology->TopologyNodes); case KSPROPERTY_TOPOLOGY_CONNECTIONS: return KsHandleSizedListQuery(Irp, Topology->TopologyConnectionsCount, sizeof(KSTOPOLOGY_CONNECTION), Topology->TopologyConnections); case KSPROPERTY_TOPOLOGY_NAME: Node = (KSP_NODE*)Property; /* check for invalid node id */ if (Node->NodeId >= Topology->TopologyNodesCount) { /* invalid node id */ Irp->IoStatus.Information = 0; Status = STATUS_INVALID_PARAMETER; break; } /* check if there is a name supplied */ if (!IsEqualGUIDAligned(&Topology->TopologyNodesNames[Node->NodeId], &GUID_NULL)) { /* node name has been supplied */ Guid = (LPGUID)&Topology->TopologyNodesNames[Node->NodeId]; } else { /* fallback to topology node type */ Guid = (LPGUID)&Topology->TopologyNodes[Node->NodeId]; } /* read topology node name */ Status = KspReadMediaCategory(Guid, &KeyInfo); if (!NT_SUCCESS(Status)) { Irp->IoStatus.Information = 0; break; } /* store result size */ Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR); /* check for buffer overflow */ if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength) { /* buffer too small */ Status = STATUS_BUFFER_OVERFLOW; FreeItem(KeyInfo); break; } /* copy result buffer */ RtlMoveMemory(Irp->UserBuffer, &KeyInfo->Data, KeyInfo->DataLength); /* zero terminate it */ ((LPWSTR)Irp->UserBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0'; /* free key info */ FreeItem(KeyInfo); break; default: Irp->IoStatus.Information = 0; Status = STATUS_NOT_FOUND; } return Status; }