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