[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
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
515 Irp->IoStatus.Information = KeyInfo->DataLength + sizeof(WCHAR);
516
517 if (KeyInfo->DataLength + sizeof(WCHAR) > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
518 {
519 Status = STATUS_BUFFER_OVERFLOW;
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 ExFreePool(KeyInfo);
527 break;
528 case KSPROPERTY_PIN_PROPOSEDATAFORMAT:
529 Pin = (KSP_PIN*)Property;
530 if (Pin->PinId >= DescriptorsCount)
531 {
532 Status = STATUS_INVALID_PARAMETER;
533 Irp->IoStatus.Information = 0;
534 break;
535 }
536 Size = sizeof(KSDATAFORMAT);
537 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
538 {
539 Irp->IoStatus.Information = Size;
540 Status = STATUS_BUFFER_TOO_SMALL;
541 break;
542 }
543 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(KSDATAFORMAT_WAVEFORMATEX))
544 {
545 UNIMPLEMENTED
546 Status = STATUS_NOT_IMPLEMENTED;
547 Irp->IoStatus.Information = 0;
548 break;
549 }
550
551 WaveFormatIn = (PKSDATAFORMAT_WAVEFORMATEX)Buffer;
552 if (!Descriptor[Pin->PinId].DataRanges || !Descriptor[Pin->PinId].DataRangesCount)
553 {
554 Status = STATUS_UNSUCCESSFUL;
555 Irp->IoStatus.Information = 0;
556 break;
557 }
558 WaveFormatOut = (PKSDATARANGE_AUDIO*)Descriptor[Pin->PinId].DataRanges;
559 for(Index = 0; Index < Descriptor[Pin->PinId].DataRangesCount; Index++)
560 {
561 if (WaveFormatOut[Index]->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO))
562 {
563 UNIMPLEMENTED
564 continue;
565 }
566
567 if (WaveFormatOut[Index]->MinimumSampleFrequency > WaveFormatIn->WaveFormatEx.nSamplesPerSec ||
568 WaveFormatOut[Index]->MaximumSampleFrequency < WaveFormatIn->WaveFormatEx.nSamplesPerSec ||
569 WaveFormatOut[Index]->MinimumBitsPerSample > WaveFormatIn->WaveFormatEx.wBitsPerSample ||
570 WaveFormatOut[Index]->MaximumBitsPerSample < WaveFormatIn->WaveFormatEx.wBitsPerSample ||
571 WaveFormatOut[Index]->MaximumChannels < WaveFormatIn->WaveFormatEx.nChannels)
572 {
573 Irp->IoStatus.Status = STATUS_NO_MATCH;
574 Irp->IoStatus.Information = 0;
575 return STATUS_NO_MATCH;
576 }
577 else
578 {
579 Irp->IoStatus.Status = STATUS_SUCCESS;
580 Irp->IoStatus.Information = 0;
581 return STATUS_SUCCESS;
582 }
583 }
584 Status = STATUS_NO_MATCH;
585 Irp->IoStatus.Information = 0;
586 break;
587 default:
588 DPRINT1("Unhandled property request %x\n", Property->Id);
589 Status = STATUS_NOT_IMPLEMENTED;
590 Irp->IoStatus.Information = 0;
591 }
592
593 return Status;
594 }
595
596 /*
597 @unimplemented
598 */
599 KSDDKAPI NTSTATUS NTAPI
600 KsPinDataIntersectionEx(
601 IN PIRP Irp,
602 IN PKSP_PIN Pin,
603 OUT PVOID Data,
604 IN ULONG DescriptorsCount,
605 IN const KSPIN_DESCRIPTOR* Descriptor,
606 IN ULONG DescriptorSize,
607 IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL,
608 IN PVOID HandlerContext OPTIONAL)
609 {
610 UNIMPLEMENTED;
611 return STATUS_UNSUCCESSFUL;
612 }
613
614 /*
615 @implemented
616 */
617 KSDDKAPI
618 NTSTATUS
619 NTAPI
620 KsPinDataIntersection(
621 IN PIRP Irp,
622 IN PKSP_PIN Pin,
623 OUT PVOID Data,
624 IN ULONG DescriptorsCount,
625 IN const KSPIN_DESCRIPTOR* Descriptor,
626 IN PFNKSINTERSECTHANDLER IntersectHandler)
627 {
628 KSMULTIPLE_ITEM * Item;
629 KSDATARANGE * DataRange;
630 PIO_STACK_LOCATION IoStack;
631 ULONG Size;
632 ULONG Index;
633 NTSTATUS Status;
634
635 /* get current irp stack location */
636 IoStack = IoGetCurrentIrpStackLocation(Irp);
637
638 /* calculate minimum data size */
639 Size = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + sizeof(KSDATARANGE);
640 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < Size)
641 {
642 /* buffer too small */
643 Irp->IoStatus.Information = Size;
644 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
645 return STATUS_BUFFER_TOO_SMALL;
646 }
647 /* is pin id out of bounds */
648 if (Pin->PinId >= DescriptorsCount)
649 {
650 /* it is */
651 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
652 Irp->IoStatus.Information = 0;
653 return STATUS_INVALID_PARAMETER;
654 }
655
656 /* get start item */
657 Item = (KSMULTIPLE_ITEM*)(Pin + 1);
658 /* get first data range */
659 DataRange = (KSDATARANGE*)(Item + 1);
660 /* iterate through all data ranges */
661 for(Index = 0; Index < Item->Count; Index++, DataRange++)
662 {
663 /* call intersect handler */
664 Status = IntersectHandler(Irp, Pin, DataRange, Data);
665 if (NT_SUCCESS(Status))
666 {
667 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < DataRange->FormatSize)
668 {
669 /* buffer is too small */
670 Irp->IoStatus.Information = DataRange->FormatSize;
671 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
672 return STATUS_BUFFER_TOO_SMALL;
673 }
674 RtlMoveMemory(Irp->UserBuffer, DataRange, sizeof(KSDATARANGE));
675 Irp->IoStatus.Information = sizeof(KSDATARANGE);
676 Irp->IoStatus.Status = STATUS_SUCCESS;
677 return STATUS_SUCCESS;
678 }
679
680 }
681
682 Irp->IoStatus.Information = 0;
683 Irp->IoStatus.Status = STATUS_NO_MATCH;
684 return STATUS_NO_MATCH;
685 }
686
687 /*
688 @implemented
689 */
690
691 KSDDKAPI
692 NTSTATUS
693 NTAPI
694 KsHandleSizedListQuery(
695 IN PIRP Irp,
696 IN ULONG DataItemsCount,
697 IN ULONG DataItemSize,
698 IN const VOID* DataItems)
699 {
700 ULONG Size;
701 PIO_STACK_LOCATION IoStack;
702 PKSMULTIPLE_ITEM Item;
703
704 /* get current irp stack location */
705 IoStack = IoGetCurrentIrpStackLocation(Irp);
706
707 /* calculate size */
708 Size = DataItemSize * DataItemsCount + sizeof(KSMULTIPLE_ITEM);
709
710 /* get multiple item */
711 Item = (PKSMULTIPLE_ITEM)Irp->UserBuffer;
712
713 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0)
714 {
715 /* buffer too small */
716 Irp->IoStatus.Information = Size;
717
718 return STATUS_BUFFER_OVERFLOW;
719 }
720
721 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG))
722 {
723 /* store just the size */
724 Item->Size = Size;
725 Irp->IoStatus.Information = sizeof(ULONG);
726
727 return STATUS_SUCCESS;
728 }
729
730
731 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSMULTIPLE_ITEM))
732 {
733 /* buffer too small */
734 return STATUS_BUFFER_TOO_SMALL;
735 }
736
737 Item->Count = DataItemsCount;
738 Item->Size = DataItemSize;
739
740 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM))
741 {
742 /* buffer can only hold the length descriptor */
743 Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM);
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