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