+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Kernel Streaming
+ * FILE: drivers/ksfilter/ks/connectivity.c
+ * PURPOSE: KS Pin functions
+ * PROGRAMMER: Johannes Anderwald
+ */
+
+
#include "priv.h"
+KSPIN_INTERFACE StandardPinInterface =
+{
+ {STATIC_KSINTERFACESETID_Standard},
+ KSINTERFACE_STANDARD_STREAMING,
+ 0
+};
+
+KSPIN_MEDIUM StandardPinMedium =
+{
+ {STATIC_KSMEDIUMSETID_Standard},
+ KSMEDIUM_TYPE_ANYINSTANCE,
+ 0
+};
+
+const GUID KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT = {0xf4aeb342, 0x0329, 0x4fdd, {0xa8, 0xfd, 0x4a, 0xff, 0x49, 0x26, 0xc9, 0x78}};
+
/*
@implemented
*/
}
return KspCreateObjectType(FilterHandle,
- L"{146F1A80-4791-11D0-A5D6-28DB04C10000}", //KSNAME_Pin
+ KSSTRING_Pin,
(PVOID)Connect,
ConnectSize,
DesiredAccess,
ConnectionHandle);
}
-/*
- @unimplemented
-*/
-KSDDKAPI
NTSTATUS
-NTAPI
-KsValidateConnectRequest(
- IN PIRP Irp,
- IN ULONG DescriptorsCount,
- IN KSPIN_DESCRIPTOR* Descriptor,
+KspValidateConnectRequest(
+ IN PIRP Irp,
+ IN ULONG DescriptorsCount,
+ IN PVOID Descriptors,
+ IN ULONG DescriptorSize,
OUT PKSPIN_CONNECT* Connect)
{
- PIO_STACK_LOCATION IoStack;
PKSPIN_CONNECT ConnectDetails;
- LPWSTR PinName = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}\\";
- PKSDATAFORMAT DataFormat;
+ PKSPIN_INTERFACE Interface;
+ PKSPIN_MEDIUM Medium;
+ ULONG Size;
+ NTSTATUS Status;
+ ULONG Index;
+ ULONG Count;
+ BOOLEAN Found;
+ PKSPIN_DESCRIPTOR Descriptor;
- IoStack = IoGetCurrentIrpStackLocation(Irp);
- if (!IoStack->FileObject->FileName.Buffer)
+ /* did the caller miss the connect parameter */
+ if (!Connect)
return STATUS_INVALID_PARAMETER;
- if (wcsncmp(IoStack->FileObject->FileName.Buffer, PinName, wcslen(PinName)))
+ /* set create param size */
+ Size = sizeof(KSPIN_CONNECT);
+
+ /* fetch create parameters */
+ Status = KspCopyCreateRequest(Irp,
+ KSSTRING_Pin,
+ &Size,
+ (PVOID*)&ConnectDetails);
+
+ /* check for success */
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* is pin id out of bounds */
+ if (ConnectDetails->PinId >= DescriptorsCount)
return STATUS_INVALID_PARAMETER;
- ConnectDetails = (PKSPIN_CONNECT)(IoStack->FileObject->FileName.Buffer + wcslen(PinName));
+ if (DescriptorSize == sizeof(KSPIN_DESCRIPTOR))
+ {
+ /* standard pin descriptor */
+ Descriptor = (PKSPIN_DESCRIPTOR)((ULONG_PTR)Descriptors + sizeof(KSPIN_DESCRIPTOR) * ConnectDetails->PinId);
+ }
+ else
+ {
+ /* extended / variable pin descriptor */
+ Descriptor = &((PKSPIN_DESCRIPTOR_EX)((ULONG_PTR)Descriptors + DescriptorSize * ConnectDetails->PinId))->PinDescriptor;
+ }
+
- if (ConnectDetails->PinToHandle != NULL)
+ /* does the pin have interface details filled in */
+ if (Descriptor->InterfacesCount && Descriptor->Interfaces)
{
- UNIMPLEMENTED
- return STATUS_NOT_IMPLEMENTED;
+ /* use provided pin interface count */
+ Count = Descriptor->InterfacesCount;
+ Interface = (PKSPIN_INTERFACE)Descriptor->Interfaces;
+ }
+ else
+ {
+ /* use standard pin interface */
+ Count = 1;
+ Interface = &StandardPinInterface;
}
- if (IoStack->FileObject->FileName.Length < wcslen(PinName) + sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT))
- return STATUS_INVALID_PARAMETER;
+ /* now check the interface */
+ Found = FALSE;
+ Index = 0;
+ do
+ {
+ UNICODE_STRING GuidString, GuidString2;
+ RtlStringFromGUID(&Interface[Index].Set, &GuidString);
+ RtlStringFromGUID(&ConnectDetails->Interface.Set, &GuidString2);
- ConnectDetails = (PKSPIN_CONNECT)(IoStack->FileObject->FileName.Buffer + wcslen(PinName));
+ DPRINT("Driver Interface %S Id %u\n", GuidString.Buffer, Interface[Index].Id);
+ DPRINT("Connect Interface %S Id %u\n", GuidString2.Buffer, ConnectDetails->Interface.Id);
- if (ConnectDetails->PinId >= DescriptorsCount)
- return STATUS_INVALID_PARAMETER;
+ if (IsEqualGUIDAligned(&Interface[Index].Set, &ConnectDetails->Interface.Set) &&
+ Interface[Index].Id == ConnectDetails->Interface.Id)
+ {
+ /* found a matching interface */
+ Found = TRUE;
+ break;
+ }
+ /* iterate to next interface */
+ Index++;
+ }while(Index < Count);
-#if 0
- if (!IsEqualGUIDAligned(&ConnectDetails->Interface.Set, &KSINTERFACESETID_Standard) &&
- ConnectDetails->Interface.Id != KSINTERFACE_STANDARD_STREAMING)
+ if (!Found)
{
- //FIXME
- // validate provided interface set
- DPRINT1("FIXME\n");
+ /* pin doesnt support this interface */
+ return STATUS_NO_MATCH;
}
- if (!IsEqualGUIDAligned(&ConnectDetails->Medium.Set, &KSMEDIUMSETID_Standard) &&
- ConnectDetails->Medium.Id != KSMEDIUM_TYPE_ANYINSTANCE)
+ /* does the pin have medium details filled in */
+ if (Descriptor->MediumsCount && Descriptor->Mediums)
{
- //FIXME
- // validate provided medium set
- DPRINT1("FIXME\n");
+ /* use provided pin interface count */
+ Count = Descriptor->MediumsCount;
+ Medium = (PKSPIN_MEDIUM)Descriptor->Mediums;
+ }
+ else
+ {
+ /* use standard pin interface */
+ Count = 1;
+ Medium = &StandardPinMedium;
+ }
+
+ /* now check the interface */
+ Found = FALSE;
+ Index = 0;
+ do
+ {
+ UNICODE_STRING GuidString, GuidString2;
+ RtlStringFromGUID(&Medium[Index].Set, &GuidString);
+ RtlStringFromGUID(&ConnectDetails->Medium.Set, &GuidString2);
+
+ DPRINT("Driver Medium %S Id %u\n", GuidString.Buffer, Medium[Index].Id);
+ DPRINT("Connect Medium %S Id %u\n", GuidString2.Buffer, ConnectDetails->Medium.Id);
+
+
+ if (IsEqualGUIDAligned(&Medium[Index].Set, &ConnectDetails->Medium.Set) &&
+ Medium[Index].Id == ConnectDetails->Medium.Id)
+ {
+ /* found a matching interface */
+ Found = TRUE;
+ break;
+ }
+
+
+
+ /* iterate to next medium */
+ Index++;
+ }while(Index < Count);
+
+ if (!Found)
+ {
+ /* pin doesnt support this medium */
+ return STATUS_NO_MATCH;
}
-#endif
/// FIXME
/// implement format checking
- DataFormat = (PKSDATAFORMAT) (ConnectDetails + 1);
*Connect = ConnectDetails;
-
return STATUS_SUCCESS;
}
KSDDKAPI
NTSTATUS
NTAPI
-KsPinPropertyHandler(
+KsValidateConnectRequest(
+ IN PIRP Irp,
+ IN ULONG DescriptorsCount,
+ IN KSPIN_DESCRIPTOR* Descriptor,
+ OUT PKSPIN_CONNECT* Connect)
+{
+ return KspValidateConnectRequest(Irp, DescriptorsCount, Descriptor, sizeof(KSPIN_DESCRIPTOR), Connect);
+}
+
+NTSTATUS
+KspReadMediaCategory(
+ IN LPGUID Category,
+ PKEY_VALUE_PARTIAL_INFORMATION *OutInformation)
+{
+ UNICODE_STRING MediaPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
+ UNICODE_STRING Name = RTL_CONSTANT_STRING(L"Name");
+ UNICODE_STRING GuidString, Path;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE hKey;
+ ULONG Size;
+ PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
+
+ /* convert the guid to string */
+ Status = RtlStringFromGUID(Category, &GuidString);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* allocate buffer for the registry key */
+ Path.Length = 0;
+ Path.MaximumLength = MediaPath.MaximumLength + GuidString.MaximumLength;
+ Path.Buffer = ExAllocatePool(NonPagedPool, Path.MaximumLength);
+ if (!Path.Buffer)
+ {
+ /* not enough memory */
+ RtlFreeUnicodeString(&GuidString);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlAppendUnicodeStringToString(&Path, &MediaPath);
+ RtlAppendUnicodeStringToString(&Path, &GuidString);
+
+ /* free guid string */
+ RtlFreeUnicodeString(&GuidString);
+
+ /* initialize object attributes */
+ InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ /* open the key */
+ Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes);
+
+ DPRINT("ZwOpenKey() status 0x%08lx %S\n", Status, Path.Buffer);
+
+ /* free path buffer */
+ ExFreePool(Path.Buffer);
+
+ /* check for success */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* query the name size */
+ Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, NULL, 0, &Size);
+ if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
+ {
+ /* failed to query for name key */
+ ZwClose(hKey);
+ return Status;
+ }
+
+ /* allocate buffer to read key info */
+ KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePool(NonPagedPool, Size);
+ if (!KeyInfo)
+ {
+ /* not enough memory */
+ ZwClose(hKey);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* now read the info */
+ Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, (PVOID)KeyInfo, Size, &Size);
+
+ /* close the key */
+ ZwClose(hKey);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* failed to read key */
+ ExFreePool(KeyInfo);
+ return Status;
+ }
+
+ /* store key information */
+ *OutInformation = KeyInfo;
+ return Status;
+}
+
+KSDDKAPI
+NTSTATUS
+NTAPI
+KspPinPropertyHandler(
IN PIRP Irp,
IN PKSPROPERTY Property,
IN OUT PVOID Data,
IN ULONG DescriptorsCount,
- IN const KSPIN_DESCRIPTOR* Descriptor)
+ 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;
IoStack = IoGetCurrentIrpStackLocation(Irp);
Buffer = Irp->UserBuffer;
- if (Property->Flags != KSPROPERTY_TYPE_GET)
+ //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)
{
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
- Irp->IoStatus.Information = 0;
- return STATUS_NOT_IMPLEMENTED;
+ if (Pin->PinId >= DescriptorsCount)
+ {
+ /* invalid parameter */
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ 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_CTYPES:
(*(PULONG)Buffer) = DescriptorsCount;
Irp->IoStatus.Information = sizeof(ULONG);
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
break;
case KSPROPERTY_PIN_DATAFLOW:
- Pin = (KSP_PIN*)Property;
- if (Pin->PinId >= DescriptorsCount)
- {
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
- Irp->IoStatus.Information = 0;
- break;
- }
+
Size = sizeof(KSPIN_DATAFLOW);
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
{
Irp->IoStatus.Information = Size;
- Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ Status = STATUS_BUFFER_TOO_SMALL;
break;
}
- *((KSPIN_DATAFLOW*)Buffer) = Descriptor[Pin->PinId].DataFlow;
+ *((KSPIN_DATAFLOW*)Buffer) = Descriptor->DataFlow;
Irp->IoStatus.Information = sizeof(KSPIN_DATAFLOW);
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
break;
case KSPROPERTY_PIN_DATARANGES:
- Pin = (KSP_PIN*)Property;
- if (Pin->PinId >= DescriptorsCount)
+ 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)
{
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
- Irp->IoStatus.Information = 0;
- break;
+ DataRanges = Descriptor->DataRanges;
+ Count = Descriptor->DataRangesCount;
}
- Size = sizeof(KSMULTIPLE_ITEM);
- for (Index = 0; Index < Descriptor[Pin->PinId].DataRangesCount; Index++)
+ else
{
- Size += Descriptor[Pin->PinId].DataRanges[Index]->FormatSize;
+ DataRanges = Descriptor->ConstrainedDataRanges;
+ Count = Descriptor->ConstrainedDataRangesCount;
}
- if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
+ 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;
- Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ 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 = Descriptor[Pin->PinId].DataRangesCount;
+ 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);
- for (Index = 0; Index < Descriptor[Pin->PinId].DataRangesCount; Index++)
+
+ /* alignment assert */
+ ASSERT(((ULONG_PTR)Data & 0x7) == 0);
+
+ for (Index = 0; Index < Count; Index++)
{
- RtlMoveMemory(Data, Descriptor[Pin->PinId].DataRanges[Index], Descriptor[Pin->PinId].DataRanges[Index]->FormatSize);
- Data = ((PUCHAR)Data + Descriptor[Pin->PinId].DataRanges[Index]->FormatSize);
+ 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);
}
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Size;
break;
case KSPROPERTY_PIN_INTERFACES:
- Pin = (KSP_PIN*)Property;
- if (Pin->PinId >= DescriptorsCount)
+
+ if (Descriptor->Interfaces)
{
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
- Irp->IoStatus.Information = 0;
- break;
+ /* 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;
- Size = sizeof(KSMULTIPLE_ITEM) + sizeof(KSPIN_INTERFACE) * Descriptor[Pin->PinId].InterfacesCount;
+ case KSPROPERTY_PIN_COMMUNICATION:
+ Size = sizeof(KSPIN_COMMUNICATION);
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
{
Irp->IoStatus.Information = Size;
- Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ Status = STATUS_BUFFER_TOO_SMALL;
break;
}
- Item = (KSMULTIPLE_ITEM*)Buffer;
- Item->Size = Size;
- Item->Count = Descriptor[Pin->PinId].InterfacesCount;
- RtlMoveMemory((PVOID)(Item + 1), Descriptor[Pin->PinId].Interfaces, Descriptor[Pin->PinId].InterfacesCount * sizeof(KSDATARANGE));
+ *((KSPIN_COMMUNICATION*)Buffer) = Descriptor->Communication;
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Size;
break;
- case KSPROPERTY_PIN_MEDIUMS:
- Pin = (KSP_PIN*)Property;
- if (Pin->PinId >= DescriptorsCount)
- {
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
- Irp->IoStatus.Information = 0;
- break;
- }
- Size = sizeof(KSMULTIPLE_ITEM) + sizeof(KSPIN_MEDIUM) * Descriptor[Pin->PinId].MediumsCount;
+ case KSPROPERTY_PIN_CATEGORY:
+
+ Size = sizeof(GUID);
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
{
Irp->IoStatus.Information = Size;
- Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ Status = STATUS_BUFFER_TOO_SMALL;
break;
}
+ if (Descriptor->Category)
+ {
+ RtlMoveMemory(Buffer, Descriptor->Category, sizeof(GUID));
+ }
- Item = (KSMULTIPLE_ITEM*)Buffer;
- Item->Size = Size;
- Item->Count = Descriptor[Pin->PinId].MediumsCount;
- RtlMoveMemory((PVOID)(Item + 1), Descriptor[Pin->PinId].Mediums, Descriptor[Pin->PinId].MediumsCount * sizeof(KSDATARANGE));
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
+ Status = STATUS_SUCCESS;
Irp->IoStatus.Information = Size;
break;
- case KSPROPERTY_PIN_COMMUNICATION:
- Pin = (KSP_PIN*)Property;
- if (Pin->PinId >= DescriptorsCount)
+ case KSPROPERTY_PIN_NAME:
+ if (!Descriptor->Name)
{
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
+ Status = STATUS_SUCCESS;
break;
}
- Size = sizeof(KSPIN_COMMUNICATION);
- if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
+ Status = KspReadMediaCategory((LPGUID)Descriptor->Name, &KeyInfo);
+ if (!NT_SUCCESS(Status))
{
- Irp->IoStatus.Information = Size;
- Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ Irp->IoStatus.Information = 0;
break;
}
- *((KSPIN_COMMUNICATION*)Buffer) = Descriptor[Pin->PinId].Communication;
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = Size;
- break;
+ Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
- case KSPROPERTY_PIN_CATEGORY:
- Pin = (KSP_PIN*)Property;
- if (Pin->PinId >= DescriptorsCount)
+ if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
{
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
- Irp->IoStatus.Information = 0;
+ Status = STATUS_BUFFER_OVERFLOW;
+ ExFreePool(KeyInfo);
break;
}
- Size = sizeof(GUID);
+ RtlMoveMemory(Irp->UserBuffer, &KeyInfo->Data, KeyInfo->DataLength);
+ ((LPWSTR)Irp->UserBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
+ ExFreePool(KeyInfo);
+ break;
+ case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
+ Size = sizeof(KSDATAFORMAT);
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
{
Irp->IoStatus.Information = Size;
- Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ Status = STATUS_BUFFER_TOO_SMALL;
break;
}
-
- RtlMoveMemory(Buffer, &Descriptor[Pin->PinId].Category, sizeof(GUID));
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = Size;
- break;
-
- case KSPROPERTY_PIN_NAME:
- Pin = (KSP_PIN*)Property;
- if (Pin->PinId >= DescriptorsCount)
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(KSDATAFORMAT_WAVEFORMATEX))
{
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ UNIMPLEMENTED
+ Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
break;
}
- Size = sizeof(GUID);
- if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
+ WaveFormatIn = (PKSDATAFORMAT_WAVEFORMATEX)Buffer;
+ if (!Descriptor->DataRanges || !Descriptor->DataRangesCount)
{
- Irp->IoStatus.Information = Size;
- Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ Status = STATUS_UNSUCCESSFUL;
+ Irp->IoStatus.Information = 0;
break;
}
-
-
- RtlMoveMemory(Buffer, &Descriptor[Pin->PinId].Name, sizeof(GUID));
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = Size;
+ 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);
- Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+ Status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Information = 0;
}
- return Irp->IoStatus.Status;
+ return Status;
+}
+
+/*
+ @implemented
+*/
+KSDDKAPI
+NTSTATUS
+NTAPI
+KsPinPropertyHandler(
+ IN PIRP Irp,
+ IN PKSPROPERTY Property,
+ IN OUT PVOID Data,
+ IN ULONG DescriptorsCount,
+ IN const KSPIN_DESCRIPTOR* Descriptor)
+{
+ return KspPinPropertyHandler(Irp, Property, Data, DescriptorsCount, Descriptor, sizeof(KSPIN_DESCRIPTOR));
+}
+
+/*
+ @unimplemented
+*/
+KSDDKAPI NTSTATUS NTAPI
+KsPinDataIntersectionEx(
+ IN PIRP Irp,
+ IN PKSP_PIN Pin,
+ OUT PVOID Data,
+ IN ULONG DescriptorsCount,
+ IN const KSPIN_DESCRIPTOR* Descriptor,
+ IN ULONG DescriptorSize,
+ IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL,
+ IN PVOID HandlerContext OPTIONAL)
+{
+ UNIMPLEMENTED;
+ return STATUS_UNSUCCESSFUL;
}
/*
ULONG Index;
NTSTATUS Status;
+ /* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
+ /* calculate minimum data size */
Size = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATARANGE);
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < Size)
{
- Irp->IoStatus.Information = 0;
- Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+ /* buffer too small */
+ Irp->IoStatus.Information = Size;
+ Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
return STATUS_BUFFER_TOO_SMALL;
}
-
+ /* is pin id out of bounds */
if (Pin->PinId >= DescriptorsCount)
{
+ /* it is */
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
return STATUS_INVALID_PARAMETER;
}
- Item = (KSMULTIPLE_ITEM*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+ /* get start item */
+ Item = (KSMULTIPLE_ITEM*)(Pin + 1);
+ /* get first data range */
DataRange = (KSDATARANGE*)(Item + 1);
-
+ /* iterate through all data ranges */
for(Index = 0; Index < Item->Count; Index++, DataRange++)
{
+ /* call intersect handler */
Status = IntersectHandler(Irp, Pin, DataRange, Data);
if (NT_SUCCESS(Status))
{
- if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSDATARANGE))
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < DataRange->FormatSize)
{
- Irp->IoStatus.Information = sizeof(KSDATARANGE);
+ /* buffer is too small */
+ Irp->IoStatus.Information = DataRange->FormatSize;
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
return STATUS_BUFFER_TOO_SMALL;
}
return STATUS_NO_MATCH;
}
-/* Does this belong here? */
+/*
+ @implemented
+*/
-KSDDKAPI NTSTATUS NTAPI
+KSDDKAPI
+NTSTATUS
+NTAPI
KsHandleSizedListQuery(
IN PIRP Irp,
IN ULONG DataItemsCount,
IN ULONG DataItemSize,
IN const VOID* DataItems)
{
- return STATUS_SUCCESS;
+ ULONG Size;
+ PIO_STACK_LOCATION IoStack;
+ PKSMULTIPLE_ITEM Item;
+
+ /* get current irp stack location */
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ /* calculate size */
+ Size = DataItemSize * DataItemsCount + sizeof(KSMULTIPLE_ITEM);
+
+ /* get multiple item */
+ Item = (PKSMULTIPLE_ITEM)Irp->UserBuffer;
+
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0)
+ {
+ /* buffer too small */
+ Irp->IoStatus.Information = Size;
+
+ return STATUS_BUFFER_OVERFLOW;
+ }
+
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG))
+ {
+ /* store just the size */
+ Item->Size = Size;
+ Irp->IoStatus.Information = sizeof(ULONG);
+
+ return STATUS_SUCCESS;
+ }
+
+
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSMULTIPLE_ITEM))
+ {
+ /* buffer too small */
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ Item->Count = DataItemsCount;
+ Item->Size = DataItemSize;
+
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM))
+ {
+ /* buffer can only hold the length descriptor */
+ Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM);
+ return STATUS_SUCCESS;
+ }
+
+ if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= Size)
+ {
+ /* copy items */
+ RtlMoveMemory((PVOID)(Item + 1), DataItems, DataItemSize * DataItemsCount);
+ /* store result */
+ Irp->IoStatus.Information = Size;
+ /* done */
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ /* buffer too small */
+ return STATUS_BUFFER_TOO_SMALL;
+ }
}
+