Example #1
0
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;
}
Example #2
0
/*
    @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;
}