2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/connectivity.c
5 * PURPOSE: KS Pin functions
6 * PROGRAMMER: Johannes Anderwald
12 KSPIN_INTERFACE StandardPinInterface
=
14 {STATIC_KSINTERFACESETID_Standard
},
15 KSINTERFACE_STANDARD_STREAMING
,
19 KSPIN_MEDIUM StandardPinMedium
=
21 {STATIC_KSMEDIUMSETID_Standard
},
22 KSMEDIUM_TYPE_ANYINSTANCE
,
34 IN HANDLE FilterHandle
,
35 IN PKSPIN_CONNECT Connect
,
36 IN ACCESS_MASK DesiredAccess
,
37 OUT PHANDLE ConnectionHandle
)
39 UINT ConnectSize
= sizeof(KSPIN_CONNECT
);
41 PKSDATAFORMAT_WAVEFORMATEX Format
= (PKSDATAFORMAT_WAVEFORMATEX
)(Connect
+ 1);
42 if (Format
->DataFormat
.FormatSize
== sizeof(KSDATAFORMAT
) ||
43 Format
->DataFormat
.FormatSize
== sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
))
45 ConnectSize
+= Format
->DataFormat
.FormatSize
;
48 return KspCreateObjectType(FilterHandle
,
62 KsValidateConnectRequest(
64 IN ULONG DescriptorsCount
,
65 IN KSPIN_DESCRIPTOR
* Descriptor
,
66 OUT PKSPIN_CONNECT
* Connect
)
68 PKSPIN_CONNECT ConnectDetails
;
69 PKSPIN_INTERFACE Interface
;
77 /* did the caller miss the connect parameter */
79 return STATUS_INVALID_PARAMETER
;
81 /* set create param size */
82 Size
= sizeof(KSPIN_CONNECT
);
84 /* fetch create parameters */
85 Status
= KspCopyCreateRequest(Irp
,
88 (PVOID
*)&ConnectDetails
);
90 /* check for success */
91 if (!NT_SUCCESS(Status
))
94 /* is pin id out of bounds */
95 if (ConnectDetails
->PinId
>= DescriptorsCount
)
96 return STATUS_INVALID_PARAMETER
;
98 /* does the pin have interface details filled in */
99 if (Descriptor
[ConnectDetails
->PinId
].InterfacesCount
&& Descriptor
[ConnectDetails
->PinId
].Interfaces
)
101 /* use provided pin interface count */
102 Count
= Descriptor
[ConnectDetails
->PinId
].InterfacesCount
;
103 Interface
= (PKSPIN_INTERFACE
)Descriptor
[ConnectDetails
->PinId
].Interfaces
;
107 /* use standard pin interface */
109 Interface
= &StandardPinInterface
;
112 /* now check the interface */
117 if (IsEqualGUIDAligned(&Interface
[Index
].Set
, &ConnectDetails
->Interface
.Set
) &&
118 Interface
[Index
].Id
== ConnectDetails
->Interface
.Id
)
120 /* found a matching interface */
124 /* iterate to next interface */
126 }while(Index
< Count
);
130 /* pin doesnt support this interface */
131 return STATUS_NO_MATCH
;
134 /* does the pin have medium details filled in */
135 if (Descriptor
[ConnectDetails
->PinId
].MediumsCount
&& Descriptor
[ConnectDetails
->PinId
].Mediums
)
137 /* use provided pin interface count */
138 Count
= Descriptor
[ConnectDetails
->PinId
].MediumsCount
;
139 Medium
= (PKSPIN_MEDIUM
)Descriptor
[ConnectDetails
->PinId
].Mediums
;
143 /* use standard pin interface */
145 Medium
= &StandardPinMedium
;
148 /* now check the interface */
153 if (IsEqualGUIDAligned(&Medium
[Index
].Set
, &ConnectDetails
->Medium
.Set
) &&
154 Medium
[Index
].Id
== ConnectDetails
->Medium
.Id
)
156 /* found a matching interface */
160 /* iterate to next medium */
162 }while(Index
< Count
);
166 /* pin doesnt support this medium */
167 return STATUS_NO_MATCH
;
171 /// implement format checking
173 *Connect
= ConnectDetails
;
174 return STATUS_SUCCESS
;
179 KspReadMediaCategory(
181 PKEY_VALUE_PARTIAL_INFORMATION
*OutInformation
)
183 UNICODE_STRING MediaPath
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
184 UNICODE_STRING Name
= RTL_CONSTANT_STRING(L
"Name");
185 UNICODE_STRING GuidString
, Path
;
187 OBJECT_ATTRIBUTES ObjectAttributes
;
190 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
192 /* convert the guid to string */
193 Status
= RtlStringFromGUID(Category
, &GuidString
);
194 if (!NT_SUCCESS(Status
))
197 /* allocate buffer for the registry key */
199 Path
.MaximumLength
= MediaPath
.MaximumLength
+ GuidString
.MaximumLength
;
200 Path
.Buffer
= ExAllocatePool(NonPagedPool
, Path
.MaximumLength
);
203 /* not enough memory */
204 RtlFreeUnicodeString(&GuidString
);
205 return STATUS_INSUFFICIENT_RESOURCES
;
208 RtlAppendUnicodeStringToString(&Path
, &MediaPath
);
209 RtlAppendUnicodeStringToString(&Path
, &GuidString
);
211 /* free guid string */
212 RtlFreeUnicodeString(&GuidString
);
214 /* initialize object attributes */
215 InitializeObjectAttributes(&ObjectAttributes
, &Path
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
218 Status
= ZwOpenKey(&hKey
, GENERIC_READ
, &ObjectAttributes
);
220 DPRINT("ZwOpenKey() status 0x%08lx %S\n", Status
, Path
.Buffer
);
222 /* free path buffer */
223 ExFreePool(Path
.Buffer
);
225 /* check for success */
226 if (!NT_SUCCESS(Status
))
228 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
232 /* query the name size */
233 Status
= ZwQueryValueKey(hKey
, &Name
, KeyValuePartialInformation
, NULL
, 0, &Size
);
234 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
)
236 /* failed to query for name key */
241 /* allocate buffer to read key info */
242 KeyInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
) ExAllocatePool(NonPagedPool
, Size
);
245 /* not enough memory */
247 return STATUS_INSUFFICIENT_RESOURCES
;
250 /* now read the info */
251 Status
= ZwQueryValueKey(hKey
, &Name
, KeyValuePartialInformation
, (PVOID
)KeyInfo
, Size
, &Size
);
256 if (!NT_SUCCESS(Status
))
258 /* failed to read key */
263 /* store key information */
264 *OutInformation
= KeyInfo
;
274 KsPinPropertyHandler(
276 IN PKSPROPERTY Property
,
278 IN ULONG DescriptorsCount
,
279 IN
const KSPIN_DESCRIPTOR
* Descriptor
)
282 KSMULTIPLE_ITEM
* Item
;
283 PIO_STACK_LOCATION IoStack
;
286 PKSDATARANGE_AUDIO
*WaveFormatOut
;
287 PKSDATAFORMAT_WAVEFORMATEX WaveFormatIn
;
288 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
289 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
291 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
292 Buffer
= Irp
->UserBuffer
;
294 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
);
298 case KSPROPERTY_PIN_CTYPES
:
299 (*(PULONG
)Buffer
) = DescriptorsCount
;
300 Irp
->IoStatus
.Information
= sizeof(ULONG
);
301 Status
= STATUS_SUCCESS
;
303 case KSPROPERTY_PIN_DATAFLOW
:
304 Pin
= (KSP_PIN
*)Property
;
305 if (Pin
->PinId
>= DescriptorsCount
)
307 Status
= STATUS_INVALID_PARAMETER
;
308 Irp
->IoStatus
.Information
= 0;
311 Size
= sizeof(KSPIN_DATAFLOW
);
312 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
314 Irp
->IoStatus
.Information
= Size
;
315 Status
= STATUS_BUFFER_TOO_SMALL
;
319 *((KSPIN_DATAFLOW
*)Buffer
) = Descriptor
[Pin
->PinId
].DataFlow
;
320 Irp
->IoStatus
.Information
= sizeof(KSPIN_DATAFLOW
);
321 Status
= STATUS_SUCCESS
;
324 case KSPROPERTY_PIN_DATARANGES
:
325 Pin
= (KSP_PIN
*)Property
;
326 if (Pin
->PinId
>= DescriptorsCount
)
328 Status
= STATUS_INVALID_PARAMETER
;
329 Irp
->IoStatus
.Information
= 0;
332 Size
= sizeof(KSMULTIPLE_ITEM
);
333 for (Index
= 0; Index
< Descriptor
[Pin
->PinId
].DataRangesCount
; Index
++)
335 Size
+= Descriptor
[Pin
->PinId
].DataRanges
[Index
]->FormatSize
;
338 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== 0)
340 /* buffer too small */
341 Irp
->IoStatus
.Information
= Size
;
342 Status
= STATUS_BUFFER_OVERFLOW
;
346 Item
= (KSMULTIPLE_ITEM
*)Buffer
;
348 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(ULONG
))
350 /* store the result size */
352 Irp
->IoStatus
.Information
= sizeof(ULONG
);
353 Status
= STATUS_SUCCESS
;
357 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSMULTIPLE_ITEM
))
359 /* buffer too small */
360 Status
= STATUS_BUFFER_TOO_SMALL
;
364 /* store descriptor size */
366 Item
->Count
= Descriptor
[Pin
->PinId
].DataRangesCount
;
368 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(KSMULTIPLE_ITEM
))
370 Irp
->IoStatus
.Information
= sizeof(KSMULTIPLE_ITEM
);
371 Status
= STATUS_SUCCESS
;
375 /* now copy all dataranges */
376 Data
= (PUCHAR
)(Item
+1);
377 for (Index
= 0; Index
< Descriptor
[Pin
->PinId
].DataRangesCount
; Index
++)
379 RtlMoveMemory(Data
, Descriptor
[Pin
->PinId
].DataRanges
[Index
], Descriptor
[Pin
->PinId
].DataRanges
[Index
]->FormatSize
);
380 Data
= ((PUCHAR
)Data
+ Descriptor
[Pin
->PinId
].DataRanges
[Index
]->FormatSize
);
383 Status
= STATUS_SUCCESS
;
384 Irp
->IoStatus
.Information
= Size
;
386 case KSPROPERTY_PIN_INTERFACES
:
387 Pin
= (KSP_PIN
*)Property
;
388 if (Pin
->PinId
>= DescriptorsCount
)
390 Status
= STATUS_INVALID_PARAMETER
;
391 Irp
->IoStatus
.Information
= 0;
395 if (Descriptor
[Pin
->PinId
].Interfaces
)
397 /* use mediums provided by driver */
398 return KsHandleSizedListQuery(Irp
, Descriptor
[Pin
->PinId
].InterfacesCount
, sizeof(KSPIN_MEDIUM
), Descriptor
[Pin
->PinId
].Interfaces
);
402 /* use standard medium */
403 return KsHandleSizedListQuery(Irp
, 1, sizeof(KSPIN_INTERFACE
), &StandardPinInterface
);
407 case KSPROPERTY_PIN_MEDIUMS
:
408 Pin
= (KSP_PIN
*)Property
;
409 if (Pin
->PinId
>= DescriptorsCount
)
411 Status
= STATUS_INVALID_PARAMETER
;
412 Irp
->IoStatus
.Information
= 0;
416 if (Descriptor
[Pin
->PinId
].MediumsCount
)
418 /* use mediums provided by driver */
419 return KsHandleSizedListQuery(Irp
, Descriptor
[Pin
->PinId
].MediumsCount
, sizeof(KSPIN_MEDIUM
), Descriptor
[Pin
->PinId
].Mediums
);
423 /* use standard medium */
424 return KsHandleSizedListQuery(Irp
, 1, sizeof(KSPIN_MEDIUM
), &StandardPinMedium
);
428 case KSPROPERTY_PIN_COMMUNICATION
:
429 Pin
= (KSP_PIN
*)Property
;
430 if (Pin
->PinId
>= DescriptorsCount
)
432 Status
= STATUS_INVALID_PARAMETER
;
433 Irp
->IoStatus
.Information
= 0;
437 Size
= sizeof(KSPIN_COMMUNICATION
);
438 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
440 Irp
->IoStatus
.Information
= Size
;
441 Status
= STATUS_BUFFER_TOO_SMALL
;
445 *((KSPIN_COMMUNICATION
*)Buffer
) = Descriptor
[Pin
->PinId
].Communication
;
446 Status
= STATUS_SUCCESS
;
447 Irp
->IoStatus
.Information
= Size
;
450 case KSPROPERTY_PIN_CATEGORY
:
451 Pin
= (KSP_PIN
*)Property
;
452 if (Pin
->PinId
>= DescriptorsCount
)
454 Status
= STATUS_INVALID_PARAMETER
;
455 Irp
->IoStatus
.Information
= 0;
460 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
462 Irp
->IoStatus
.Information
= Size
;
463 Status
= STATUS_BUFFER_TOO_SMALL
;
466 if (Descriptor
[Pin
->PinId
].Category
)
468 RtlMoveMemory(Buffer
, Descriptor
[Pin
->PinId
].Category
, sizeof(GUID
));
471 Status
= STATUS_SUCCESS
;
472 Irp
->IoStatus
.Information
= Size
;
475 case KSPROPERTY_PIN_NAME
:
476 Pin
= (KSP_PIN
*)Property
;
477 if (Pin
->PinId
>= DescriptorsCount
)
479 Status
= STATUS_INVALID_PARAMETER
;
480 Irp
->IoStatus
.Information
= 0;
484 if (!Descriptor
[Pin
->PinId
].Name
)
486 Irp
->IoStatus
.Information
= 0;
487 Status
= STATUS_SUCCESS
;
491 Status
= KspReadMediaCategory((LPGUID
)Descriptor
[Pin
->PinId
].Name
, &KeyInfo
);
492 if (!NT_SUCCESS(Status
))
494 Irp
->IoStatus
.Information
= 0;
499 Irp
->IoStatus
.Information
= KeyInfo
->DataLength
+ sizeof(WCHAR
);
501 if (KeyInfo
->DataLength
+ sizeof(WCHAR
) > IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
503 Status
= STATUS_BUFFER_OVERFLOW
;
508 RtlMoveMemory(Irp
->UserBuffer
, &KeyInfo
->Data
, KeyInfo
->DataLength
);
509 ((LPWSTR
)Irp
->UserBuffer
)[KeyInfo
->DataLength
/ sizeof(WCHAR
)] = L
'\0';
512 case KSPROPERTY_PIN_PROPOSEDATAFORMAT
:
513 Pin
= (KSP_PIN
*)Property
;
514 if (Pin
->PinId
>= DescriptorsCount
)
516 Status
= STATUS_INVALID_PARAMETER
;
517 Irp
->IoStatus
.Information
= 0;
520 Size
= sizeof(KSDATAFORMAT
);
521 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
523 Irp
->IoStatus
.Information
= Size
;
524 Status
= STATUS_BUFFER_TOO_SMALL
;
527 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
!= sizeof(KSDATAFORMAT_WAVEFORMATEX
))
530 Status
= STATUS_NOT_IMPLEMENTED
;
531 Irp
->IoStatus
.Information
= 0;
535 WaveFormatIn
= (PKSDATAFORMAT_WAVEFORMATEX
)Buffer
;
536 if (!Descriptor
[Pin
->PinId
].DataRanges
|| !Descriptor
[Pin
->PinId
].DataRangesCount
)
538 Status
= STATUS_UNSUCCESSFUL
;
539 Irp
->IoStatus
.Information
= 0;
542 WaveFormatOut
= (PKSDATARANGE_AUDIO
*)Descriptor
[Pin
->PinId
].DataRanges
;
543 for(Index
= 0; Index
< Descriptor
[Pin
->PinId
].DataRangesCount
; Index
++)
545 if (WaveFormatOut
[Index
]->DataRange
.FormatSize
!= sizeof(KSDATARANGE_AUDIO
))
551 if (WaveFormatOut
[Index
]->MinimumSampleFrequency
> WaveFormatIn
->WaveFormatEx
.nSamplesPerSec
||
552 WaveFormatOut
[Index
]->MaximumSampleFrequency
< WaveFormatIn
->WaveFormatEx
.nSamplesPerSec
||
553 WaveFormatOut
[Index
]->MinimumBitsPerSample
> WaveFormatIn
->WaveFormatEx
.wBitsPerSample
||
554 WaveFormatOut
[Index
]->MaximumBitsPerSample
< WaveFormatIn
->WaveFormatEx
.wBitsPerSample
||
555 WaveFormatOut
[Index
]->MaximumChannels
< WaveFormatIn
->WaveFormatEx
.nChannels
)
557 Irp
->IoStatus
.Status
= STATUS_NO_MATCH
;
558 Irp
->IoStatus
.Information
= 0;
559 return STATUS_NO_MATCH
;
563 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
564 Irp
->IoStatus
.Information
= 0;
565 return STATUS_SUCCESS
;
568 Status
= STATUS_NO_MATCH
;
569 Irp
->IoStatus
.Information
= 0;
572 DPRINT1("Unhandled property request %x\n", Property
->Id
);
573 Status
= STATUS_NOT_IMPLEMENTED
;
574 Irp
->IoStatus
.Information
= 0;
583 KSDDKAPI NTSTATUS NTAPI
584 KsPinDataIntersectionEx(
588 IN ULONG DescriptorsCount
,
589 IN
const KSPIN_DESCRIPTOR
* Descriptor
,
590 IN ULONG DescriptorSize
,
591 IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL
,
592 IN PVOID HandlerContext OPTIONAL
)
595 return STATUS_UNSUCCESSFUL
;
604 KsPinDataIntersection(
608 IN ULONG DescriptorsCount
,
609 IN
const KSPIN_DESCRIPTOR
* Descriptor
,
610 IN PFNKSINTERSECTHANDLER IntersectHandler
)
612 KSMULTIPLE_ITEM
* Item
;
613 KSDATARANGE
* DataRange
;
614 PIO_STACK_LOCATION IoStack
;
619 /* get current irp stack location */
620 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
622 /* calculate minimum data size */
623 Size
= sizeof(KSP_PIN
) + sizeof(KSMULTIPLE_ITEM
) + sizeof(KSDATARANGE
);
624 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< Size
)
626 /* buffer too small */
627 Irp
->IoStatus
.Information
= Size
;
628 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
629 return STATUS_BUFFER_TOO_SMALL
;
631 /* is pin id out of bounds */
632 if (Pin
->PinId
>= DescriptorsCount
)
635 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
636 Irp
->IoStatus
.Information
= 0;
637 return STATUS_INVALID_PARAMETER
;
641 Item
= (KSMULTIPLE_ITEM
*)(Pin
+ 1);
642 /* get first data range */
643 DataRange
= (KSDATARANGE
*)(Item
+ 1);
644 /* iterate through all data ranges */
645 for(Index
= 0; Index
< Item
->Count
; Index
++, DataRange
++)
647 /* call intersect handler */
648 Status
= IntersectHandler(Irp
, Pin
, DataRange
, Data
);
649 if (NT_SUCCESS(Status
))
651 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< DataRange
->FormatSize
)
653 /* buffer is too small */
654 Irp
->IoStatus
.Information
= DataRange
->FormatSize
;
655 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
656 return STATUS_BUFFER_TOO_SMALL
;
658 RtlMoveMemory(Irp
->UserBuffer
, DataRange
, sizeof(KSDATARANGE
));
659 Irp
->IoStatus
.Information
= sizeof(KSDATARANGE
);
660 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
661 return STATUS_SUCCESS
;
666 Irp
->IoStatus
.Information
= 0;
667 Irp
->IoStatus
.Status
= STATUS_NO_MATCH
;
668 return STATUS_NO_MATCH
;
678 KsHandleSizedListQuery(
680 IN ULONG DataItemsCount
,
681 IN ULONG DataItemSize
,
682 IN
const VOID
* DataItems
)
685 PIO_STACK_LOCATION IoStack
;
686 PKSMULTIPLE_ITEM Item
;
688 /* get current irp stack location */
689 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
692 Size
= DataItemSize
* DataItemsCount
+ sizeof(KSMULTIPLE_ITEM
);
694 /* get multiple item */
695 Item
= (PKSMULTIPLE_ITEM
)Irp
->UserBuffer
;
697 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== 0)
699 /* buffer too small */
700 Irp
->IoStatus
.Information
= Size
;
702 return STATUS_BUFFER_OVERFLOW
;
705 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(ULONG
))
707 /* store just the size */
709 Irp
->IoStatus
.Information
= sizeof(ULONG
);
711 return STATUS_SUCCESS
;
715 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSMULTIPLE_ITEM
))
717 /* buffer too small */
718 return STATUS_BUFFER_TOO_SMALL
;
721 Item
->Count
= DataItemsCount
;
722 Item
->Size
= DataItemSize
;
724 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(KSMULTIPLE_ITEM
))
726 /* buffer can only hold the length descriptor */
727 Irp
->IoStatus
.Information
= sizeof(KSMULTIPLE_ITEM
);
728 return STATUS_SUCCESS
;
731 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= Size
)
734 RtlMoveMemory((PVOID
)(Item
+ 1), DataItems
, DataItemSize
* DataItemsCount
);
736 Irp
->IoStatus
.Information
= Size
;
738 return STATUS_SUCCESS
;
742 /* buffer too small */
743 return STATUS_BUFFER_TOO_SMALL
;