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