[gdi32]
[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 DPRINT("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 == 0)
339 {
340 /* buffer too small */
341 Irp->IoStatus.Information = Size;
342 Status = STATUS_BUFFER_OVERFLOW;
343 break;
344 }
345
346 Item = (KSMULTIPLE_ITEM*)Buffer;
347
348 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG))
349 {
350 /* store the result size */
351 Item->Size = Size;
352 Irp->IoStatus.Information = sizeof(ULONG);
353 Status = STATUS_SUCCESS;
354 break;
355 }
356
357 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSMULTIPLE_ITEM))
358 {
359 /* buffer too small */
360 Status = STATUS_BUFFER_TOO_SMALL;
361 break;
362 }
363
364 /* store descriptor size */
365 Item->Size = Size;
366 Item->Count = Descriptor[Pin->PinId].DataRangesCount;
367
368 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM))
369 {
370 Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM);
371 Status = STATUS_SUCCESS;
372 break;
373 }
374
375 /* now copy all dataranges */
376 Data = (PUCHAR)(Item +1);
377 for (Index = 0; Index < Descriptor[Pin->PinId].DataRangesCount; Index++)
378 {
379 RtlMoveMemory(Data, Descriptor[Pin->PinId].DataRanges[Index], Descriptor[Pin->PinId].DataRanges[Index]->FormatSize);
380 Data = ((PUCHAR)Data + Descriptor[Pin->PinId].DataRanges[Index]->FormatSize);
381 }
382
383 Status = STATUS_SUCCESS;
384 Irp->IoStatus.Information = Size;
385 break;
386 case KSPROPERTY_PIN_INTERFACES:
387 Pin = (KSP_PIN*)Property;
388 if (Pin->PinId >= DescriptorsCount)
389 {
390 Status = STATUS_INVALID_PARAMETER;
391 Irp->IoStatus.Information = 0;
392 break;
393 }
394
395 /* calculate size */
396 Size = sizeof(KSMULTIPLE_ITEM);
397 Size += max(1, Descriptor[Pin->PinId].InterfacesCount) * sizeof(KSPIN_INTERFACE);
398
399 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
400 {
401 Irp->IoStatus.Information = Size;
402 Status = STATUS_MORE_ENTRIES;
403 break;
404 }
405
406 Item = (KSMULTIPLE_ITEM*)Buffer;
407 Item->Size = Size;
408
409 if (Descriptor[Pin->PinId].InterfacesCount)
410 {
411 Item->Count = Descriptor[Pin->PinId].InterfacesCount;
412 RtlMoveMemory((PVOID)(Item + 1), Descriptor[Pin->PinId].Interfaces, Descriptor[Pin->PinId].InterfacesCount * sizeof(KSPIN_INTERFACE));
413 }
414 else
415 {
416 Item->Count = 1;
417 RtlMoveMemory((PVOID)(Item + 1), &StandardPinInterface, sizeof(KSPIN_INTERFACE));
418 }
419
420 Status = STATUS_SUCCESS;
421 Irp->IoStatus.Information = Size;
422 break;
423 case KSPROPERTY_PIN_MEDIUMS:
424 Pin = (KSP_PIN*)Property;
425 if (Pin->PinId >= DescriptorsCount)
426 {
427 Status = STATUS_INVALID_PARAMETER;
428 Irp->IoStatus.Information = 0;
429 break;
430 }
431
432 if (Descriptor[Pin->PinId].MediumsCount)
433 {
434 /* use mediums provided by driver */
435 return KsHandleSizedListQuery(Irp, Descriptor[Pin->PinId].MediumsCount, sizeof(KSPIN_MEDIUM), Descriptor[Pin->PinId].Mediums);
436 }
437 else
438 {
439 /* use standard medium */
440 return KsHandleSizedListQuery(Irp, 1, sizeof(KSPIN_MEDIUM), &StandardPinMedium);
441 }
442 break;
443
444 case KSPROPERTY_PIN_COMMUNICATION:
445 Pin = (KSP_PIN*)Property;
446 if (Pin->PinId >= DescriptorsCount)
447 {
448 Status = STATUS_INVALID_PARAMETER;
449 Irp->IoStatus.Information = 0;
450 break;
451 }
452
453 Size = sizeof(KSPIN_COMMUNICATION);
454 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
455 {
456 Irp->IoStatus.Information = Size;
457 Status = STATUS_BUFFER_TOO_SMALL;
458 break;
459 }
460
461 *((KSPIN_COMMUNICATION*)Buffer) = Descriptor[Pin->PinId].Communication;
462 Status = STATUS_SUCCESS;
463 Irp->IoStatus.Information = Size;
464 break;
465
466 case KSPROPERTY_PIN_CATEGORY:
467 Pin = (KSP_PIN*)Property;
468 if (Pin->PinId >= DescriptorsCount)
469 {
470 Status = STATUS_INVALID_PARAMETER;
471 Irp->IoStatus.Information = 0;
472 break;
473 }
474
475 Size = sizeof(GUID);
476 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
477 {
478 Irp->IoStatus.Information = Size;
479 Status = STATUS_BUFFER_TOO_SMALL;
480 break;
481 }
482 if (Descriptor[Pin->PinId].Category)
483 {
484 RtlMoveMemory(Buffer, Descriptor[Pin->PinId].Category, sizeof(GUID));
485 }
486
487 Status = STATUS_SUCCESS;
488 Irp->IoStatus.Information = Size;
489 break;
490
491 case KSPROPERTY_PIN_NAME:
492 Pin = (KSP_PIN*)Property;
493 if (Pin->PinId >= DescriptorsCount)
494 {
495 Status = STATUS_INVALID_PARAMETER;
496 Irp->IoStatus.Information = 0;
497 break;
498 }
499
500 if (!Descriptor[Pin->PinId].Name)
501 {
502 Irp->IoStatus.Information = 0;
503 Status = STATUS_SUCCESS;
504 break;
505 }
506
507 Status = KspReadMediaCategory((LPGUID)Descriptor[Pin->PinId].Name, &KeyInfo);
508 if (!NT_SUCCESS(Status))
509 {
510 Irp->IoStatus.Information = 0;
511 break;
512 }
513
514 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
515
516
517 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
518 {
519 Status = STATUS_MORE_ENTRIES;
520 ExFreePool(KeyInfo);
521 break;
522 }
523
524 RtlMoveMemory(Irp->UserBuffer, &KeyInfo->Data, KeyInfo->DataLength);
525 ((LPWSTR)Irp->UserBuffer)[KeyInfo->DataLength / sizeof(WCHAR)] = L'\0';
526 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
527 ExFreePool(KeyInfo);
528 break;
529 case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
530 Pin = (KSP_PIN*)Property;
531 if (Pin->PinId >= DescriptorsCount)
532 {
533 Status = STATUS_INVALID_PARAMETER;
534 Irp->IoStatus.Information = 0;
535 break;
536 }
537 Size = sizeof(KSDATAFORMAT);
538 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
539 {
540 Irp->IoStatus.Information = Size;
541 Status = STATUS_BUFFER_TOO_SMALL;
542 break;
543 }
544 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(KSDATAFORMAT_WAVEFORMATEX))
545 {
546 UNIMPLEMENTED
547 Status = STATUS_NOT_IMPLEMENTED;
548 Irp->IoStatus.Information = 0;
549 break;
550 }
551
552 WaveFormatIn = (PKSDATAFORMAT_WAVEFORMATEX)Buffer;
553 if (!Descriptor[Pin->PinId].DataRanges || !Descriptor[Pin->PinId].DataRangesCount)
554 {
555 Status = STATUS_UNSUCCESSFUL;
556 Irp->IoStatus.Information = 0;
557 break;
558 }
559 WaveFormatOut = (PKSDATARANGE_AUDIO*)Descriptor[Pin->PinId].DataRanges;
560 for(Index = 0; Index < Descriptor[Pin->PinId].DataRangesCount; Index++)
561 {
562 if (WaveFormatOut[Index]->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO))
563 {
564 UNIMPLEMENTED
565 continue;
566 }
567
568 if (WaveFormatOut[Index]->MinimumSampleFrequency > WaveFormatIn->WaveFormatEx.nSamplesPerSec ||
569 WaveFormatOut[Index]->MaximumSampleFrequency < WaveFormatIn->WaveFormatEx.nSamplesPerSec ||
570 WaveFormatOut[Index]->MinimumBitsPerSample > WaveFormatIn->WaveFormatEx.wBitsPerSample ||
571 WaveFormatOut[Index]->MaximumBitsPerSample < WaveFormatIn->WaveFormatEx.wBitsPerSample ||
572 WaveFormatOut[Index]->MaximumChannels < WaveFormatIn->WaveFormatEx.nChannels)
573 {
574 Irp->IoStatus.Status = STATUS_NO_MATCH;
575 Irp->IoStatus.Information = 0;
576 return STATUS_NO_MATCH;
577 }
578 else
579 {
580 Irp->IoStatus.Status = STATUS_SUCCESS;
581 Irp->IoStatus.Information = 0;
582 return STATUS_SUCCESS;
583 }
584 }
585 Status = STATUS_NO_MATCH;
586 Irp->IoStatus.Information = 0;
587 break;
588 default:
589 DPRINT1("Unhandled property request %x\n", Property->Id);
590 Status = STATUS_NOT_IMPLEMENTED;
591 Irp->IoStatus.Information = 0;
592 }
593
594 return Status;
595 }
596
597 /*
598 @unimplemented
599 */
600 KSDDKAPI NTSTATUS NTAPI
601 KsPinDataIntersectionEx(
602 IN PIRP Irp,
603 IN PKSP_PIN Pin,
604 OUT PVOID Data,
605 IN ULONG DescriptorsCount,
606 IN const KSPIN_DESCRIPTOR* Descriptor,
607 IN ULONG DescriptorSize,
608 IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL,
609 IN PVOID HandlerContext OPTIONAL)
610 {
611 UNIMPLEMENTED;
612 return STATUS_UNSUCCESSFUL;
613 }
614
615 /*
616 @implemented
617 */
618 KSDDKAPI
619 NTSTATUS
620 NTAPI
621 KsPinDataIntersection(
622 IN PIRP Irp,
623 IN PKSP_PIN Pin,
624 OUT PVOID Data,
625 IN ULONG DescriptorsCount,
626 IN const KSPIN_DESCRIPTOR* Descriptor,
627 IN PFNKSINTERSECTHANDLER IntersectHandler)
628 {
629 KSMULTIPLE_ITEM * Item;
630 KSDATARANGE * DataRange;
631 PIO_STACK_LOCATION IoStack;
632 ULONG Size;
633 ULONG Index;
634 NTSTATUS Status;
635
636 /* get current irp stack location */
637 IoStack = IoGetCurrentIrpStackLocation(Irp);
638
639 /* calculate minimum data size */
640 Size = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATARANGE);
641 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < Size)
642 {
643 /* buffer too small */
644 Irp->IoStatus.Information = Size;
645 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
646 return STATUS_BUFFER_TOO_SMALL;
647 }
648 /* is pin id out of bounds */
649 if (Pin->PinId >= DescriptorsCount)
650 {
651 /* it is */
652 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
653 Irp->IoStatus.Information = 0;
654 return STATUS_INVALID_PARAMETER;
655 }
656
657 /* get start item */
658 Item = (KSMULTIPLE_ITEM*)(Pin + 1);
659 /* get first data range */
660 DataRange = (KSDATARANGE*)(Item + 1);
661 /* iterate through all data ranges */
662 for(Index = 0; Index < Item->Count; Index++, DataRange++)
663 {
664 /* call intersect handler */
665 Status = IntersectHandler(Irp, Pin, DataRange, Data);
666 if (NT_SUCCESS(Status))
667 {
668 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < DataRange->FormatSize)
669 {
670 /* buffer is too small */
671 Irp->IoStatus.Information = DataRange->FormatSize;
672 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
673 return STATUS_BUFFER_TOO_SMALL;
674 }
675 RtlMoveMemory(Irp->UserBuffer, DataRange, sizeof(KSDATARANGE));
676 Irp->IoStatus.Information = sizeof(KSDATARANGE);
677 Irp->IoStatus.Status = STATUS_SUCCESS;
678 return STATUS_SUCCESS;
679 }
680
681 }
682
683 Irp->IoStatus.Information = 0;
684 Irp->IoStatus.Status = STATUS_NO_MATCH;
685 return STATUS_NO_MATCH;
686 }
687
688 /*
689 @implemented
690 */
691
692 KSDDKAPI
693 NTSTATUS
694 NTAPI
695 KsHandleSizedListQuery(
696 IN PIRP Irp,
697 IN ULONG DataItemsCount,
698 IN ULONG DataItemSize,
699 IN const VOID* DataItems)
700 {
701 ULONG Size;
702 PIO_STACK_LOCATION IoStack;
703 PKSMULTIPLE_ITEM Item;
704
705 /* get current irp stack location */
706 IoStack = IoGetCurrentIrpStackLocation(Irp);
707
708 /* calculate size */
709 Size = DataItemSize * DataItemsCount + sizeof(KSMULTIPLE_ITEM);
710
711 /* get multiple item */
712 Item = (PKSMULTIPLE_ITEM)Irp->UserBuffer;
713
714 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0)
715 {
716 /* buffer too small */
717 Irp->IoStatus.Information = Size;
718
719 return STATUS_BUFFER_OVERFLOW;
720 }
721
722 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG))
723 {
724 /* store just the size */
725 Item->Size = Size;
726 Irp->IoStatus.Information = sizeof(ULONG);
727
728 return STATUS_SUCCESS;
729 }
730
731
732 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSMULTIPLE_ITEM))
733 {
734 /* buffer too small */
735 return STATUS_BUFFER_TOO_SMALL;
736 }
737
738 Item->Count = DataItemsCount;
739 Item->Size = DataItemSize;
740
741 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM))
742 {
743 /* buffer can only hold the length descriptor */
744 return STATUS_SUCCESS;
745 }
746
747 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= Size)
748 {
749 /* copy items */
750 RtlMoveMemory((PVOID)(Item + 1), DataItems, DataItemSize * DataItemsCount);
751 /* store result */
752 Irp->IoStatus.Information = Size;
753 /* done */
754 return STATUS_SUCCESS;
755 }
756 else
757 {
758 /* buffer too small */
759 return STATUS_BUFFER_TOO_SMALL;
760 }
761 }
762