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 DPRINT1("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 %x\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
< Size
)
340 Irp
->IoStatus
.Information
= Size
;
341 Status
= STATUS_MORE_ENTRIES
;
345 Item
= (KSMULTIPLE_ITEM
*)Buffer
;
347 Item
->Count
= Descriptor
[Pin
->PinId
].DataRangesCount
;
349 Data
= (PUCHAR
)(Item
+1);
350 for (Index
= 0; Index
< Descriptor
[Pin
->PinId
].DataRangesCount
; Index
++)
352 RtlMoveMemory(Data
, Descriptor
[Pin
->PinId
].DataRanges
[Index
], Descriptor
[Pin
->PinId
].DataRanges
[Index
]->FormatSize
);
353 Data
= ((PUCHAR
)Data
+ Descriptor
[Pin
->PinId
].DataRanges
[Index
]->FormatSize
);
356 Status
= STATUS_SUCCESS
;
357 Irp
->IoStatus
.Information
= Size
;
359 case KSPROPERTY_PIN_INTERFACES
:
360 Pin
= (KSP_PIN
*)Property
;
361 if (Pin
->PinId
>= DescriptorsCount
)
363 Status
= STATUS_INVALID_PARAMETER
;
364 Irp
->IoStatus
.Information
= 0;
369 Size
= sizeof(KSMULTIPLE_ITEM
);
370 Size
+= max(1, Descriptor
[Pin
->PinId
].InterfacesCount
) * sizeof(KSPIN_INTERFACE
);
372 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
374 Irp
->IoStatus
.Information
= Size
;
375 Status
= STATUS_MORE_ENTRIES
;
379 Item
= (KSMULTIPLE_ITEM
*)Buffer
;
382 if (Descriptor
[Pin
->PinId
].InterfacesCount
)
384 Item
->Count
= Descriptor
[Pin
->PinId
].InterfacesCount
;
385 RtlMoveMemory((PVOID
)(Item
+ 1), Descriptor
[Pin
->PinId
].Interfaces
, Descriptor
[Pin
->PinId
].InterfacesCount
* sizeof(KSPIN_INTERFACE
));
390 RtlMoveMemory((PVOID
)(Item
+ 1), &StandardPinInterface
, sizeof(KSPIN_INTERFACE
));
393 Status
= STATUS_SUCCESS
;
394 Irp
->IoStatus
.Information
= Size
;
396 case KSPROPERTY_PIN_MEDIUMS
:
397 Pin
= (KSP_PIN
*)Property
;
398 if (Pin
->PinId
>= DescriptorsCount
)
400 Status
= STATUS_INVALID_PARAMETER
;
401 Irp
->IoStatus
.Information
= 0;
406 Size
= sizeof(KSMULTIPLE_ITEM
);
407 Size
+= max(1, Descriptor
[Pin
->PinId
].MediumsCount
) * sizeof(KSPIN_MEDIUM
);
409 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
411 Irp
->IoStatus
.Information
= Size
;
412 Status
= STATUS_MORE_ENTRIES
;
416 Item
= (KSMULTIPLE_ITEM
*)Buffer
;
419 if (Descriptor
[Pin
->PinId
].MediumsCount
)
421 Item
->Count
= Descriptor
[Pin
->PinId
].MediumsCount
;
422 RtlMoveMemory((PVOID
)(Item
+ 1), Descriptor
[Pin
->PinId
].Mediums
, Descriptor
[Pin
->PinId
].MediumsCount
* sizeof(KSPIN_MEDIUM
));
427 RtlMoveMemory((PVOID
)(Item
+ 1), &StandardPinMedium
, sizeof(KSPIN_MEDIUM
));
430 Status
= STATUS_SUCCESS
;
431 Irp
->IoStatus
.Information
= Size
;
434 case KSPROPERTY_PIN_COMMUNICATION
:
435 Pin
= (KSP_PIN
*)Property
;
436 if (Pin
->PinId
>= DescriptorsCount
)
438 Status
= STATUS_INVALID_PARAMETER
;
439 Irp
->IoStatus
.Information
= 0;
443 Size
= sizeof(KSPIN_COMMUNICATION
);
444 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
446 Irp
->IoStatus
.Information
= Size
;
447 Status
= STATUS_BUFFER_TOO_SMALL
;
451 *((KSPIN_COMMUNICATION
*)Buffer
) = Descriptor
[Pin
->PinId
].Communication
;
452 Status
= STATUS_SUCCESS
;
453 Irp
->IoStatus
.Information
= Size
;
456 case KSPROPERTY_PIN_CATEGORY
:
457 Pin
= (KSP_PIN
*)Property
;
458 if (Pin
->PinId
>= DescriptorsCount
)
460 Status
= STATUS_INVALID_PARAMETER
;
461 Irp
->IoStatus
.Information
= 0;
466 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
468 Irp
->IoStatus
.Information
= Size
;
469 Status
= STATUS_BUFFER_TOO_SMALL
;
472 if (Descriptor
[Pin
->PinId
].Category
)
474 RtlMoveMemory(Buffer
, Descriptor
[Pin
->PinId
].Category
, sizeof(GUID
));
477 Status
= STATUS_SUCCESS
;
478 Irp
->IoStatus
.Information
= Size
;
481 case KSPROPERTY_PIN_NAME
:
482 Pin
= (KSP_PIN
*)Property
;
483 if (Pin
->PinId
>= DescriptorsCount
)
485 Status
= STATUS_INVALID_PARAMETER
;
486 Irp
->IoStatus
.Information
= 0;
490 if (!Descriptor
[Pin
->PinId
].Name
)
492 Irp
->IoStatus
.Information
= 0;
493 Status
= STATUS_SUCCESS
;
497 Status
= KspReadMediaCategory((LPGUID
)Descriptor
[Pin
->PinId
].Name
, &KeyInfo
);
498 if (!NT_SUCCESS(Status
))
500 Irp
->IoStatus
.Information
= 0;
504 Irp
->IoStatus
.Information
= KeyInfo
->DataLength
+ sizeof(WCHAR
);
507 if (KeyInfo
->DataLength
+ sizeof(WCHAR
) > IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
509 Status
= STATUS_MORE_ENTRIES
;
514 RtlMoveMemory(Irp
->UserBuffer
, &KeyInfo
->Data
, KeyInfo
->DataLength
);
515 ((LPWSTR
)Irp
->UserBuffer
)[KeyInfo
->DataLength
/ sizeof(WCHAR
)] = L
'\0';
516 Irp
->IoStatus
.Information
= KeyInfo
->DataLength
+ sizeof(WCHAR
);
519 case KSPROPERTY_PIN_PROPOSEDATAFORMAT
:
520 Pin
= (KSP_PIN
*)Property
;
521 if (Pin
->PinId
>= DescriptorsCount
)
523 Status
= STATUS_INVALID_PARAMETER
;
524 Irp
->IoStatus
.Information
= 0;
527 Size
= sizeof(KSDATAFORMAT
);
528 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
530 Irp
->IoStatus
.Information
= Size
;
531 Status
= STATUS_BUFFER_TOO_SMALL
;
534 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
!= sizeof(KSDATAFORMAT_WAVEFORMATEX
))
537 Status
= STATUS_NOT_IMPLEMENTED
;
538 Irp
->IoStatus
.Information
= 0;
542 WaveFormatIn
= (PKSDATAFORMAT_WAVEFORMATEX
)Buffer
;
543 if (!Descriptor
[Pin
->PinId
].DataRanges
|| !Descriptor
[Pin
->PinId
].DataRangesCount
)
545 Status
= STATUS_UNSUCCESSFUL
;
546 Irp
->IoStatus
.Information
= 0;
549 WaveFormatOut
= (PKSDATARANGE_AUDIO
*)Descriptor
[Pin
->PinId
].DataRanges
;
550 for(Index
= 0; Index
< Descriptor
[Pin
->PinId
].DataRangesCount
; Index
++)
552 if (WaveFormatOut
[Index
]->DataRange
.FormatSize
!= sizeof(KSDATARANGE_AUDIO
))
558 if (WaveFormatOut
[Index
]->MinimumSampleFrequency
> WaveFormatIn
->WaveFormatEx
.nSamplesPerSec
||
559 WaveFormatOut
[Index
]->MaximumSampleFrequency
< WaveFormatIn
->WaveFormatEx
.nSamplesPerSec
||
560 WaveFormatOut
[Index
]->MinimumBitsPerSample
> WaveFormatIn
->WaveFormatEx
.wBitsPerSample
||
561 WaveFormatOut
[Index
]->MaximumBitsPerSample
< WaveFormatIn
->WaveFormatEx
.wBitsPerSample
||
562 WaveFormatOut
[Index
]->MaximumChannels
< WaveFormatIn
->WaveFormatEx
.nChannels
)
564 Irp
->IoStatus
.Status
= STATUS_NO_MATCH
;
565 Irp
->IoStatus
.Information
= 0;
566 return STATUS_NO_MATCH
;
570 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
571 Irp
->IoStatus
.Information
= 0;
572 return STATUS_SUCCESS
;
575 Status
= STATUS_NO_MATCH
;
576 Irp
->IoStatus
.Information
= 0;
579 DPRINT1("Unhandled property request %x\n", Property
->Id
);
580 Status
= STATUS_NOT_IMPLEMENTED
;
581 Irp
->IoStatus
.Information
= 0;
593 KsPinDataIntersection(
597 IN ULONG DescriptorsCount
,
598 IN
const KSPIN_DESCRIPTOR
* Descriptor
,
599 IN PFNKSINTERSECTHANDLER IntersectHandler
)
601 KSMULTIPLE_ITEM
* Item
;
602 KSDATARANGE
* DataRange
;
603 PIO_STACK_LOCATION IoStack
;
608 /* get current irp stack location */
609 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
611 /* calculate minimum data size */
612 Size
= sizeof(KSP_PIN
) + sizeof(KSMULTIPLE_ITEM
) + sizeof(KSDATARANGE
);
613 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< Size
)
615 /* buffer too small */
616 Irp
->IoStatus
.Information
= Size
;
617 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
618 return STATUS_BUFFER_TOO_SMALL
;
620 /* is pin id out of bounds */
621 if (Pin
->PinId
>= DescriptorsCount
)
624 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
625 Irp
->IoStatus
.Information
= 0;
626 return STATUS_INVALID_PARAMETER
;
630 Item
= (KSMULTIPLE_ITEM
*)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
631 /* get first data range */
632 DataRange
= (KSDATARANGE
*)(Item
+ 1);
633 /* iterate through all data ranges */
634 for(Index
= 0; Index
< Item
->Count
; Index
++, DataRange
++)
636 /* call intersect handler */
637 Status
= IntersectHandler(Irp
, Pin
, DataRange
, Data
);
638 if (NT_SUCCESS(Status
))
640 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< DataRange
->FormatSize
)
642 /* buffer is too small */
643 Irp
->IoStatus
.Information
= DataRange
->FormatSize
;
644 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
645 return STATUS_BUFFER_TOO_SMALL
;
647 RtlMoveMemory(Irp
->UserBuffer
, DataRange
, sizeof(KSDATARANGE
));
648 Irp
->IoStatus
.Information
= sizeof(KSDATARANGE
);
649 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
650 return STATUS_SUCCESS
;
655 Irp
->IoStatus
.Information
= 0;
656 Irp
->IoStatus
.Status
= STATUS_NO_MATCH
;
657 return STATUS_NO_MATCH
;
667 KsHandleSizedListQuery(
669 IN ULONG DataItemsCount
,
670 IN ULONG DataItemSize
,
671 IN
const VOID
* DataItems
)
674 PIO_STACK_LOCATION IoStack
;
675 PKSMULTIPLE_ITEM Item
;
677 /* get current irp stack location */
678 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
680 Size
= DataItemSize
* DataItemsCount
+ sizeof(KSMULTIPLE_ITEM
);
683 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< Size
)
685 /* buffer too small */
686 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
687 Irp
->IoStatus
.Information
= Size
;
688 return STATUS_BUFFER_TOO_SMALL
;
691 /* get multiple item */
692 Item
= (PKSMULTIPLE_ITEM
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
694 Item
->Count
= DataItemsCount
;
695 Item
->Size
= DataItemSize
;
697 RtlMoveMemory((PVOID
)(Item
+ 1), DataItems
, DataItemSize
* DataItemsCount
);
699 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
700 Irp
->IoStatus
.Information
= Size
;
702 return STATUS_SUCCESS
;