[KS]
[reactos.git] / reactos / drivers / ksfilter / ks / connectivity.c
1 /*
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
7 */
8
9 #include "precomp.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 KSPIN_INTERFACE StandardPinInterface =
15 {
16 {STATIC_KSINTERFACESETID_Standard},
17 KSINTERFACE_STANDARD_STREAMING,
18 0
19 };
20
21 KSPIN_MEDIUM StandardPinMedium =
22 {
23 {STATIC_KSMEDIUMSETID_Standard},
24 KSMEDIUM_TYPE_ANYINSTANCE,
25 0
26 };
27
28 const GUID KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT = {0xf4aeb342, 0x0329, 0x4fdd, {0xa8, 0xfd, 0x4a, 0xff, 0x49, 0x26, 0xc9, 0x78}};
29
30 /*
31 @implemented
32 */
33 KSDDKAPI
34 NTSTATUS
35 NTAPI
36 KsCreatePin(
37 IN HANDLE FilterHandle,
38 IN PKSPIN_CONNECT Connect,
39 IN ACCESS_MASK DesiredAccess,
40 OUT PHANDLE ConnectionHandle)
41 {
42 UINT ConnectSize = sizeof(KSPIN_CONNECT);
43
44 PKSDATAFORMAT_WAVEFORMATEX Format = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1);
45 if (Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) ||
46 Format->DataFormat.FormatSize == sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX))
47 {
48 ConnectSize += Format->DataFormat.FormatSize;
49 }
50
51 return KspCreateObjectType(FilterHandle,
52 KSSTRING_Pin,
53 (PVOID)Connect,
54 ConnectSize,
55 DesiredAccess,
56 ConnectionHandle);
57 }
58
59 NTSTATUS
60 KspValidateConnectRequest(
61 IN PIRP Irp,
62 IN ULONG DescriptorsCount,
63 IN PVOID Descriptors,
64 IN ULONG DescriptorSize,
65 OUT PKSPIN_CONNECT* Connect)
66 {
67 PKSPIN_CONNECT ConnectDetails;
68 PKSPIN_INTERFACE Interface;
69 PKSPIN_MEDIUM Medium;
70 ULONG Size;
71 NTSTATUS Status;
72 ULONG Index;
73 ULONG Count;
74 BOOLEAN Found;
75 PKSPIN_DESCRIPTOR Descriptor;
76 UNICODE_STRING GuidString2;
77
78 /* did the caller miss the connect parameter */
79 if (!Connect)
80 return STATUS_INVALID_PARAMETER;
81
82 /* set create param size */
83 Size = sizeof(KSPIN_CONNECT);
84
85 /* fetch create parameters */
86 Status = KspCopyCreateRequest(Irp,
87 KSSTRING_Pin,
88 &Size,
89 (PVOID*)&ConnectDetails);
90
91 /* check for success */
92 if (!NT_SUCCESS(Status))
93 return Status;
94
95 /* is pin id out of bounds */
96 if (ConnectDetails->PinId >= DescriptorsCount)
97 {
98 FreeItem(ConnectDetails);
99 return STATUS_INVALID_PARAMETER;
100 }
101
102 if (DescriptorSize == sizeof(KSPIN_DESCRIPTOR))
103 {
104 /* standard pin descriptor */
105 Descriptor = (PKSPIN_DESCRIPTOR)((ULONG_PTR)Descriptors + sizeof(KSPIN_DESCRIPTOR) * ConnectDetails->PinId);
106 }
107 else
108 {
109 /* extended / variable pin descriptor */
110 Descriptor = &((PKSPIN_DESCRIPTOR_EX)((ULONG_PTR)Descriptors + DescriptorSize * ConnectDetails->PinId))->PinDescriptor;
111 }
112
113
114 /* does the pin have interface details filled in */
115 if (Descriptor->InterfacesCount && Descriptor->Interfaces)
116 {
117 /* use provided pin interface count */
118 Count = Descriptor->InterfacesCount;
119 Interface = (PKSPIN_INTERFACE)Descriptor->Interfaces;
120 }
121 else
122 {
123 /* use standard pin interface */
124 Count = 1;
125 Interface = &StandardPinInterface;
126 }
127
128 /* now check the interface */
129 Found = FALSE;
130 Index = 0;
131 RtlStringFromGUID(&ConnectDetails->Interface.Set, &GuidString2);
132 do
133 {
134 UNICODE_STRING GuidString;
135 RtlStringFromGUID(&Interface[Index].Set, &GuidString);
136
137 DPRINT("Driver Interface %S Id %u\n", GuidString.Buffer, Interface[Index].Id);
138 DPRINT("Connect Interface %S Id %u\n", GuidString2.Buffer, ConnectDetails->Interface.Id);
139
140 RtlFreeUnicodeString(&GuidString);
141
142 if (IsEqualGUIDAligned(&Interface[Index].Set, &ConnectDetails->Interface.Set) &&
143 Interface[Index].Id == ConnectDetails->Interface.Id)
144 {
145 /* found a matching interface */
146 Found = TRUE;
147 break;
148 }
149 /* iterate to next interface */
150 Index++;
151 }while(Index < Count);
152 RtlFreeUnicodeString(&GuidString2);
153
154 if (!Found)
155 {
156 /* pin doesnt support this interface */
157 FreeItem(ConnectDetails);
158 return STATUS_NO_MATCH;
159 }
160
161 /* does the pin have medium details filled in */
162 if (Descriptor->MediumsCount && Descriptor->Mediums)
163 {
164 /* use provided pin interface count */
165 Count = Descriptor->MediumsCount;
166 Medium = (PKSPIN_MEDIUM)Descriptor->Mediums;
167 }
168 else
169 {
170 /* use standard pin interface */
171 Count = 1;
172 Medium = &StandardPinMedium;
173 }
174
175 /* now check the interface */
176 Found = FALSE;
177 Index = 0;
178 RtlStringFromGUID(&ConnectDetails->Medium.Set, &GuidString2);
179 do
180 {
181 UNICODE_STRING GuidString;
182 RtlStringFromGUID(&Medium[Index].Set, &GuidString);
183
184 DPRINT("Driver Medium %S Id %u\n", GuidString.Buffer, Medium[Index].Id);
185 DPRINT("Connect Medium %S Id %u\n", GuidString2.Buffer, ConnectDetails->Medium.Id);
186
187 RtlFreeUnicodeString(&GuidString);
188
189 if (IsEqualGUIDAligned(&Medium[Index].Set, &ConnectDetails->Medium.Set) &&
190 Medium[Index].Id == ConnectDetails->Medium.Id)
191 {
192 /* found a matching interface */
193 Found = TRUE;
194 break;
195 }
196
197 /* iterate to next medium */
198 Index++;
199 }while(Index < Count);
200 RtlFreeUnicodeString(&GuidString2);
201
202 if (!Found)
203 {
204 /* pin doesnt support this medium */
205 FreeItem(ConnectDetails);
206 return STATUS_NO_MATCH;
207 }
208
209 /// FIXME
210 /// implement format checking
211
212 *Connect = ConnectDetails;
213 return STATUS_SUCCESS;
214 }
215
216 /*
217 @implemented
218 */
219 KSDDKAPI
220 NTSTATUS
221 NTAPI
222 KsValidateConnectRequest(
223 IN PIRP Irp,
224 IN ULONG DescriptorsCount,
225 IN KSPIN_DESCRIPTOR* Descriptor,
226 OUT PKSPIN_CONNECT* Connect)
227 {
228 return KspValidateConnectRequest(Irp, DescriptorsCount, Descriptor, sizeof(KSPIN_DESCRIPTOR), Connect);
229 }
230
231 NTSTATUS
232 KspReadMediaCategory(
233 IN LPGUID Category,
234 PKEY_VALUE_PARTIAL_INFORMATION *OutInformation)
235 {
236 UNICODE_STRING MediaPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\");
237 UNICODE_STRING Name = RTL_CONSTANT_STRING(L"Name");
238 UNICODE_STRING GuidString, Path;
239 NTSTATUS Status;
240 OBJECT_ATTRIBUTES ObjectAttributes;
241 HANDLE hKey;
242 ULONG Size;
243 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
244
245 /* convert the guid to string */
246 Status = RtlStringFromGUID(Category, &GuidString);
247 if (!NT_SUCCESS(Status))
248 return Status;
249
250 /* allocate buffer for the registry key */
251 Path.Length = 0;
252 Path.MaximumLength = MediaPath.MaximumLength + GuidString.MaximumLength;
253 Path.Buffer = AllocateItem(NonPagedPool, Path.MaximumLength);
254 if (!Path.Buffer)
255 {
256 /* not enough memory */
257 RtlFreeUnicodeString(&GuidString);
258 return STATUS_INSUFFICIENT_RESOURCES;
259 }
260
261 RtlAppendUnicodeStringToString(&Path, &MediaPath);
262 RtlAppendUnicodeStringToString(&Path, &GuidString);
263
264 /* free guid string */
265 RtlFreeUnicodeString(&GuidString);
266
267 /* initialize object attributes */
268 InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_CASE_INSENSITIVE, NULL, NULL);
269
270 /* open the key */
271 Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes);
272
273 DPRINT("ZwOpenKey() status 0x%08lx %wZ\n", Status, &Path);
274
275 /* free path buffer */
276 FreeItem(Path.Buffer);
277
278 /* check for success */
279 if (!NT_SUCCESS(Status))
280 {
281 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
282 return Status;
283 }
284
285 /* query the name size */
286 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, NULL, 0, &Size);
287 if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
288 {
289 /* failed to query for name key */
290 ZwClose(hKey);
291 return Status;
292 }
293
294 /* allocate buffer to read key info */
295 KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION) AllocateItem(NonPagedPool, Size);
296 if (!KeyInfo)
297 {
298 /* not enough memory */
299 ZwClose(hKey);
300 return STATUS_INSUFFICIENT_RESOURCES;
301 }
302
303 /* now read the info */
304 Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, (PVOID)KeyInfo, Size, &Size);
305
306 /* close the key */
307 ZwClose(hKey);
308
309 if (!NT_SUCCESS(Status))
310 {
311 /* failed to read key */
312 FreeItem(KeyInfo);
313 return Status;
314 }
315
316 /* store key information */
317 *OutInformation = KeyInfo;
318 return Status;
319 }
320
321 KSDDKAPI
322 NTSTATUS
323 NTAPI
324 KspPinPropertyHandler(
325 IN PIRP Irp,
326 IN PKSPROPERTY Property,
327 IN OUT PVOID Data,
328 IN ULONG DescriptorsCount,
329 IN const KSPIN_DESCRIPTOR* Descriptors,
330 IN ULONG DescriptorSize)
331 {
332 KSP_PIN * Pin;
333 KSMULTIPLE_ITEM * Item;
334 PIO_STACK_LOCATION IoStack;
335 ULONG Size, Index;
336 PVOID Buffer;
337 PKSDATARANGE_AUDIO *WaveFormatOut;
338 PKSDATAFORMAT_WAVEFORMATEX WaveFormatIn;
339 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
340 const KSPIN_DESCRIPTOR *Descriptor;
341 NTSTATUS Status = STATUS_NOT_SUPPORTED;
342 ULONG Count;
343 const PKSDATARANGE* DataRanges;
344 LPGUID Guid;
345
346 IoStack = IoGetCurrentIrpStackLocation(Irp);
347 Buffer = Data;
348
349 //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);
350
351 /* convert to PKSP_PIN */
352 Pin = (KSP_PIN*)Property;
353
354 if (Property->Id != KSPROPERTY_PIN_CTYPES)
355 {
356 if (Pin->PinId >= DescriptorsCount)
357 {
358 /* invalid parameter */
359 return STATUS_INVALID_PARAMETER;
360 }
361 }
362 else
363 {
364 (*(PULONG)Buffer) = DescriptorsCount;
365 Irp->IoStatus.Information = sizeof(ULONG);
366 return STATUS_SUCCESS;
367 }
368
369
370 if (DescriptorSize == sizeof(KSPIN_DESCRIPTOR))
371 {
372 /* it is simple pin descriptor */
373 Descriptor = &Descriptors[Pin->PinId];
374 }
375 else
376 {
377 /* get offset to pin descriptor */
378 Descriptor = &(((PKSPIN_DESCRIPTOR_EX)((ULONG_PTR)Descriptors + Pin->PinId * DescriptorSize))->PinDescriptor);
379 }
380
381 switch(Property->Id)
382 {
383 case KSPROPERTY_PIN_DATAFLOW:
384
385 Size = sizeof(KSPIN_DATAFLOW);
386 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
387 {
388 Irp->IoStatus.Information = Size;
389 Status = STATUS_BUFFER_TOO_SMALL;
390 break;
391 }
392
393 *((KSPIN_DATAFLOW*)Buffer) = Descriptor->DataFlow;
394 Irp->IoStatus.Information = sizeof(KSPIN_DATAFLOW);
395 Status = STATUS_SUCCESS;
396 break;
397
398 case KSPROPERTY_PIN_DATARANGES:
399 case KSPROPERTY_PIN_CONSTRAINEDDATARANGES:
400
401 Size = sizeof(KSMULTIPLE_ITEM);
402 DPRINT("Id %lu PinId %lu DataRangesCount %lu ConstrainedDataRangesCount %lu\n", Property->Id, Pin->PinId, Descriptor->DataRangesCount, Descriptor->ConstrainedDataRangesCount);
403
404 if (Property->Id == KSPROPERTY_PIN_DATARANGES || Descriptor->ConstrainedDataRangesCount == 0)
405 {
406 DataRanges = Descriptor->DataRanges;
407 Count = Descriptor->DataRangesCount;
408 }
409 else
410 {
411 DataRanges = Descriptor->ConstrainedDataRanges;
412 Count = Descriptor->ConstrainedDataRangesCount;
413 }
414
415 for (Index = 0; Index < Count; Index++)
416 {
417 Size += ((DataRanges[Index]->FormatSize + 0x7) & ~0x7);
418 }
419
420 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0)
421 {
422 /* buffer too small */
423 Irp->IoStatus.Information = Size;
424 Status = STATUS_BUFFER_OVERFLOW;
425 break;
426 }
427
428 Item = (KSMULTIPLE_ITEM*)Buffer;
429
430 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG))
431 {
432 /* store the result size */
433 Item->Size = Size;
434 Irp->IoStatus.Information = sizeof(ULONG);
435 Status = STATUS_SUCCESS;
436 break;
437 }
438
439 /* store descriptor size */
440 Item->Size = Size;
441 Item->Count = Count;
442
443 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM))
444 {
445 Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM);
446 Status = STATUS_SUCCESS;
447 break;
448 }
449
450 /* now copy all dataranges */
451 Data = (PUCHAR)(Item +1);
452
453 /* alignment assert */
454 ASSERT(((ULONG_PTR)Data & 0x7) == 0);
455
456 for (Index = 0; Index < Count; Index++)
457 {
458 UNICODE_STRING GuidString;
459 /* convert the guid to string */
460 RtlStringFromGUID(&DataRanges[Index]->MajorFormat, &GuidString);
461 DPRINT("Index %lu MajorFormat %S\n", Index, GuidString.Buffer);
462 RtlStringFromGUID(&DataRanges[Index]->SubFormat, &GuidString);
463 DPRINT("Index %lu SubFormat %S\n", Index, GuidString.Buffer);
464 RtlStringFromGUID(&DataRanges[Index]->Specifier, &GuidString);
465 DPRINT("Index %lu Specifier %S\n", Index, GuidString.Buffer);
466 RtlStringFromGUID(&DataRanges[Index]->Specifier, &GuidString);
467 DPRINT("Index %lu FormatSize %lu Flags %lu SampleSize %lu Reserved %lu KSDATAFORMAT %lu\n", Index,
468 DataRanges[Index]->FormatSize, DataRanges[Index]->Flags, DataRanges[Index]->SampleSize, DataRanges[Index]->Reserved, sizeof(KSDATAFORMAT));
469
470 RtlMoveMemory(Data, DataRanges[Index], DataRanges[Index]->FormatSize);
471 Data = ((PUCHAR)Data + DataRanges[Index]->FormatSize);
472 /* alignment assert */
473 ASSERT(((ULONG_PTR)Data & 0x7) == 0);
474 Data = (PVOID)(((ULONG_PTR)Data + 0x7) & ~0x7);
475 }
476
477 Status = STATUS_SUCCESS;
478 Irp->IoStatus.Information = Size;
479 break;
480 case KSPROPERTY_PIN_INTERFACES:
481
482 if (Descriptor->Interfaces)
483 {
484 /* use mediums provided by driver */
485 return KsHandleSizedListQuery(Irp, Descriptor->InterfacesCount, sizeof(KSPIN_MEDIUM), Descriptor->Interfaces);
486 }
487 else
488 {
489 /* use standard medium */
490 return KsHandleSizedListQuery(Irp, 1, sizeof(KSPIN_INTERFACE), &StandardPinInterface);
491 }
492 break;
493
494 case KSPROPERTY_PIN_MEDIUMS:
495
496 if (Descriptor->MediumsCount)
497 {
498 /* use mediums provided by driver */
499 return KsHandleSizedListQuery(Irp, Descriptor->MediumsCount, sizeof(KSPIN_MEDIUM), Descriptor->Mediums);
500 }
501 else
502 {
503 /* use standard medium */
504 return KsHandleSizedListQuery(Irp, 1, sizeof(KSPIN_MEDIUM), &StandardPinMedium);
505 }
506 break;
507
508 case KSPROPERTY_PIN_COMMUNICATION:
509
510 Size = sizeof(KSPIN_COMMUNICATION);
511 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
512 {
513 Irp->IoStatus.Information = Size;
514 Status = STATUS_BUFFER_TOO_SMALL;
515 break;
516 }
517
518 *((KSPIN_COMMUNICATION*)Buffer) = Descriptor->Communication;
519
520 Status = STATUS_SUCCESS;
521 Irp->IoStatus.Information = Size;
522 break;
523
524 case KSPROPERTY_PIN_CATEGORY:
525
526 if (!Descriptor->Category)
527 {
528 /* no pin category */
529 return STATUS_NOT_FOUND;
530 }
531
532 /* check size */
533 Size = sizeof(GUID);
534 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
535 {
536 /* buffer too small */
537 Irp->IoStatus.Information = Size;
538 Status = STATUS_BUFFER_TOO_SMALL;
539 break;
540 }
541
542 /* copy category guid */
543 RtlMoveMemory(Buffer, Descriptor->Category, sizeof(GUID));
544
545 /* save result */
546 Status = STATUS_SUCCESS;
547 Irp->IoStatus.Information = Size;
548 break;
549
550 case KSPROPERTY_PIN_NAME:
551
552 if (Descriptor->Name)
553 {
554 /* use pin name */
555 Guid = (LPGUID)Descriptor->Name;
556 }
557 else
558 {
559 /* use pin category as fallback */
560 Guid = (LPGUID)Descriptor->Category;
561 }
562
563 if (!Guid)
564 {
565 /* no friendly name available */
566 return STATUS_NOT_FOUND;
567 }
568
569 /* read friendly name category name */
570 Status = KspReadMediaCategory(Guid, &KeyInfo);
571 if (!NT_SUCCESS(Status))
572 {
573 /* failed to read category */
574 Irp->IoStatus.Information = 0;
575 break;
576 }
577
578 /* store required length */
579 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
580
581 /* check if buffer is too small */
582 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
583 {
584 /* buffer too small */
585 Status = STATUS_BUFFER_OVERFLOW;
586 FreeItem(KeyInfo);
587 break;
588 }
589
590 /* copy result */
591 RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, &KeyInfo->Data, KeyInfo->DataLength);
592
593 /* null terminate name */
594 ((LPWSTR)Irp->AssociatedIrp.SystemBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
595
596 /* free key info */
597 FreeItem(KeyInfo);
598 break;
599 case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
600 Size = sizeof(KSDATAFORMAT);
601 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
602 {
603 Irp->IoStatus.Information = Size;
604 Status = STATUS_BUFFER_TOO_SMALL;
605 break;
606 }
607 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(KSDATAFORMAT_WAVEFORMATEX))
608 {
609 UNIMPLEMENTED
610 Status = STATUS_NOT_IMPLEMENTED;
611 Irp->IoStatus.Information = 0;
612 break;
613 }
614
615 WaveFormatIn = (PKSDATAFORMAT_WAVEFORMATEX)Buffer;
616 if (!Descriptor->DataRanges || !Descriptor->DataRangesCount)
617 {
618 Status = STATUS_UNSUCCESSFUL;
619 Irp->IoStatus.Information = 0;
620 break;
621 }
622 WaveFormatOut = (PKSDATARANGE_AUDIO*)Descriptor->DataRanges;
623 for(Index = 0; Index < Descriptor->DataRangesCount; Index++)
624 {
625 if (WaveFormatOut[Index]->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO))
626 {
627 UNIMPLEMENTED
628 continue;
629 }
630
631 if (WaveFormatOut[Index]->MinimumSampleFrequency > WaveFormatIn->WaveFormatEx.nSamplesPerSec ||
632 WaveFormatOut[Index]->MaximumSampleFrequency < WaveFormatIn->WaveFormatEx.nSamplesPerSec ||
633 WaveFormatOut[Index]->MinimumBitsPerSample > WaveFormatIn->WaveFormatEx.wBitsPerSample ||
634 WaveFormatOut[Index]->MaximumBitsPerSample < WaveFormatIn->WaveFormatEx.wBitsPerSample ||
635 WaveFormatOut[Index]->MaximumChannels < WaveFormatIn->WaveFormatEx.nChannels)
636 {
637 Irp->IoStatus.Status = STATUS_NO_MATCH;
638 Irp->IoStatus.Information = 0;
639 return STATUS_NO_MATCH;
640 }
641 else
642 {
643 Irp->IoStatus.Status = STATUS_SUCCESS;
644 Irp->IoStatus.Information = 0;
645 return STATUS_SUCCESS;
646 }
647 }
648 Status = STATUS_NO_MATCH;
649 Irp->IoStatus.Information = 0;
650 break;
651 default:
652 DPRINT1("Unhandled property request %x\n", Property->Id);
653 Status = STATUS_NOT_IMPLEMENTED;
654 Irp->IoStatus.Information = 0;
655 }
656
657 return Status;
658 }
659
660 /*
661 @implemented
662 */
663 KSDDKAPI
664 NTSTATUS
665 NTAPI
666 KsPinPropertyHandler(
667 IN PIRP Irp,
668 IN PKSPROPERTY Property,
669 IN OUT PVOID Data,
670 IN ULONG DescriptorsCount,
671 IN const KSPIN_DESCRIPTOR* Descriptor)
672 {
673 return KspPinPropertyHandler(Irp, Property, Data, DescriptorsCount, Descriptor, sizeof(KSPIN_DESCRIPTOR));
674 }
675
676 /*
677 @unimplemented
678 */
679 KSDDKAPI NTSTATUS NTAPI
680 KsPinDataIntersectionEx(
681 IN PIRP Irp,
682 IN PKSP_PIN Pin,
683 OUT PVOID Data,
684 IN ULONG DescriptorsCount,
685 IN const KSPIN_DESCRIPTOR* Descriptor,
686 IN ULONG DescriptorSize,
687 IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL,
688 IN PVOID HandlerContext OPTIONAL)
689 {
690 UNIMPLEMENTED;
691 return STATUS_UNSUCCESSFUL;
692 }
693
694 /*
695 @implemented
696 */
697 KSDDKAPI
698 NTSTATUS
699 NTAPI
700 KsPinDataIntersection(
701 IN PIRP Irp,
702 IN PKSP_PIN Pin,
703 OUT PVOID Data,
704 IN ULONG DescriptorsCount,
705 IN const KSPIN_DESCRIPTOR* Descriptor,
706 IN PFNKSINTERSECTHANDLER IntersectHandler)
707 {
708 KSMULTIPLE_ITEM * Item;
709 KSDATARANGE * DataRange;
710 PIO_STACK_LOCATION IoStack;
711 ULONG Size;
712 ULONG Index;
713 NTSTATUS Status;
714
715 /* get current irp stack location */
716 IoStack = IoGetCurrentIrpStackLocation(Irp);
717
718 /* calculate minimum data size */
719 Size = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATARANGE);
720 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < Size)
721 {
722 /* buffer too small */
723 Irp->IoStatus.Information = Size;
724 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
725 return STATUS_BUFFER_TOO_SMALL;
726 }
727 /* is pin id out of bounds */
728 if (Pin->PinId >= DescriptorsCount)
729 {
730 /* it is */
731 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
732 Irp->IoStatus.Information = 0;
733 return STATUS_INVALID_PARAMETER;
734 }
735
736 /* get start item */
737 Item = (KSMULTIPLE_ITEM*)(Pin + 1);
738 /* get first data range */
739 DataRange = (KSDATARANGE*)(Item + 1);
740 /* iterate through all data ranges */
741 for(Index = 0; Index < Item->Count; Index++, DataRange++)
742 {
743 /* call intersect handler */
744 Status = IntersectHandler(Irp, Pin, DataRange, Data);
745 if (NT_SUCCESS(Status))
746 {
747 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < DataRange->FormatSize)
748 {
749 /* buffer is too small */
750 Irp->IoStatus.Information = DataRange->FormatSize;
751 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
752 return STATUS_BUFFER_TOO_SMALL;
753 }
754 RtlMoveMemory(Irp->UserBuffer, DataRange, sizeof(KSDATARANGE));
755 Irp->IoStatus.Information = sizeof(KSDATARANGE);
756 Irp->IoStatus.Status = STATUS_SUCCESS;
757 return STATUS_SUCCESS;
758 }
759
760 }
761
762 Irp->IoStatus.Information = 0;
763 Irp->IoStatus.Status = STATUS_NO_MATCH;
764 return STATUS_NO_MATCH;
765 }
766
767 /*
768 @implemented
769 */
770
771 KSDDKAPI
772 NTSTATUS
773 NTAPI
774 KsHandleSizedListQuery(
775 IN PIRP Irp,
776 IN ULONG DataItemsCount,
777 IN ULONG DataItemSize,
778 IN const VOID* DataItems)
779 {
780 ULONG Size;
781 PIO_STACK_LOCATION IoStack;
782 PKSMULTIPLE_ITEM Item;
783
784 /* get current irp stack location */
785 IoStack = IoGetCurrentIrpStackLocation(Irp);
786
787 /* calculate size */
788 Size = DataItemSize * DataItemsCount + sizeof(KSMULTIPLE_ITEM);
789
790 /* get multiple item */
791 Item = (PKSMULTIPLE_ITEM)Irp->AssociatedIrp.SystemBuffer;
792
793 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0)
794 {
795 /* buffer too small */
796 Irp->IoStatus.Information = Size;
797
798 return STATUS_BUFFER_OVERFLOW;
799 }
800
801 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG))
802 {
803 /* store just the size */
804 Item->Size = Size;
805 Irp->IoStatus.Information = sizeof(ULONG);
806
807 return STATUS_SUCCESS;
808 }
809
810
811 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSMULTIPLE_ITEM))
812 {
813 /* buffer too small */
814 return STATUS_BUFFER_TOO_SMALL;
815 }
816
817 Item->Count = DataItemsCount;
818 Item->Size = DataItemSize;
819
820 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM))
821 {
822 /* buffer can only hold the length descriptor */
823 Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM);
824 return STATUS_SUCCESS;
825 }
826
827 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= Size)
828 {
829 /* copy items */
830 RtlMoveMemory((PVOID)(Item + 1), DataItems, DataItemSize * DataItemsCount);
831 /* store result */
832 Irp->IoStatus.Information = Size;
833 /* done */
834 return STATUS_SUCCESS;
835 }
836 else
837 {
838 /* buffer too small */
839 return STATUS_BUFFER_TOO_SMALL;
840 }
841 }
842