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
12 KSPIN_INTERFACE StandardPinInterface
=
14 {STATIC_KSINTERFACESETID_Standard
},
15 KSINTERFACE_STANDARD_STREAMING
,
19 KSPIN_MEDIUM StandardPinMedium
=
21 {STATIC_KSMEDIUMSETID_Standard
},
22 KSMEDIUM_TYPE_ANYINSTANCE
,
34 IN HANDLE FilterHandle
,
35 IN PKSPIN_CONNECT Connect
,
36 IN ACCESS_MASK DesiredAccess
,
37 OUT PHANDLE ConnectionHandle
)
39 UINT ConnectSize
= sizeof(KSPIN_CONNECT
);
41 PKSDATAFORMAT_WAVEFORMATEX Format
= (PKSDATAFORMAT_WAVEFORMATEX
)(Connect
+ 1);
42 if (Format
->DataFormat
.FormatSize
== sizeof(KSDATAFORMAT
) ||
43 Format
->DataFormat
.FormatSize
== sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATEX
))
45 ConnectSize
+= Format
->DataFormat
.FormatSize
;
48 return KspCreateObjectType(FilterHandle
,
62 KsValidateConnectRequest(
64 IN ULONG DescriptorsCount
,
65 IN KSPIN_DESCRIPTOR
* Descriptor
,
66 OUT PKSPIN_CONNECT
* Connect
)
68 PKSPIN_CONNECT ConnectDetails
;
69 PKSPIN_INTERFACE Interface
;
77 /* did the caller miss the connect parameter */
79 return STATUS_INVALID_PARAMETER
;
81 /* set create param size */
82 Size
= sizeof(KSPIN_CONNECT
);
84 /* fetch create parameters */
85 Status
= KspCopyCreateRequest(Irp
,
88 (PVOID
*)&ConnectDetails
);
90 /* check for success */
91 if (!NT_SUCCESS(Status
))
94 /* is pin id out of bounds */
95 if (ConnectDetails
->PinId
>= DescriptorsCount
)
96 return STATUS_INVALID_PARAMETER
;
98 /* does the pin have interface details filled in */
99 if (Descriptor
[ConnectDetails
->PinId
].InterfacesCount
&& Descriptor
[ConnectDetails
->PinId
].Interfaces
)
101 /* use provided pin interface count */
102 Count
= Descriptor
[ConnectDetails
->PinId
].InterfacesCount
;
103 Interface
= (PKSPIN_INTERFACE
)Descriptor
[ConnectDetails
->PinId
].Interfaces
;
107 /* use standard pin interface */
109 Interface
= &StandardPinInterface
;
112 /* now check the interface */
117 if (IsEqualGUIDAligned(&Interface
[Index
].Set
, &ConnectDetails
->Interface
.Set
) &&
118 Interface
[Index
].Id
== ConnectDetails
->Interface
.Id
)
120 /* found a matching interface */
124 /* iterate to next interface */
126 }while(Index
< Count
);
130 /* pin doesnt support this interface */
131 return STATUS_NO_MATCH
;
134 /* does the pin have medium details filled in */
135 if (Descriptor
[ConnectDetails
->PinId
].MediumsCount
&& Descriptor
[ConnectDetails
->PinId
].Mediums
)
137 /* use provided pin interface count */
138 Count
= Descriptor
[ConnectDetails
->PinId
].MediumsCount
;
139 Medium
= (PKSPIN_MEDIUM
)Descriptor
[ConnectDetails
->PinId
].Mediums
;
143 /* use standard pin interface */
145 Medium
= &StandardPinMedium
;
148 /* now check the interface */
153 if (IsEqualGUIDAligned(&Medium
[Index
].Set
, &ConnectDetails
->Medium
.Set
) &&
154 Medium
[Index
].Id
== ConnectDetails
->Medium
.Id
)
156 /* found a matching interface */
160 /* iterate to next medium */
162 }while(Index
< Count
);
166 /* pin doesnt support this medium */
167 return STATUS_NO_MATCH
;
171 /// implement format checking
173 *Connect
= ConnectDetails
;
174 return STATUS_SUCCESS
;
179 KspReadMediaCategory(
181 PKEY_VALUE_PARTIAL_INFORMATION
*OutInformation
)
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
;
187 OBJECT_ATTRIBUTES ObjectAttributes
;
190 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
192 /* convert the guid to string */
193 Status
= RtlStringFromGUID(Category
, &GuidString
);
194 if (!NT_SUCCESS(Status
))
197 /* allocate buffer for the registry key */
199 Path
.MaximumLength
= MediaPath
.MaximumLength
+ GuidString
.MaximumLength
;
200 Path
.Buffer
= ExAllocatePool(NonPagedPool
, Path
.MaximumLength
);
203 /* not enough memory */
204 RtlFreeUnicodeString(&GuidString
);
205 return STATUS_INSUFFICIENT_RESOURCES
;
208 RtlAppendUnicodeStringToString(&Path
, &MediaPath
);
209 RtlAppendUnicodeStringToString(&Path
, &GuidString
);
211 /* free guid string */
212 RtlFreeUnicodeString(&GuidString
);
214 /* initialize object attributes */
215 InitializeObjectAttributes(&ObjectAttributes
, &Path
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
218 Status
= ZwOpenKey(&hKey
, GENERIC_READ
, &ObjectAttributes
);
220 DPRINT("ZwOpenKey() status 0x%08lx %S\n", Status
, Path
.Buffer
);
222 /* free path buffer */
223 ExFreePool(Path
.Buffer
);
225 /* check for success */
226 if (!NT_SUCCESS(Status
))
228 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status
);
232 /* query the name size */
233 Status
= ZwQueryValueKey(hKey
, &Name
, KeyValuePartialInformation
, NULL
, 0, &Size
);
234 if (!NT_SUCCESS(Status
) && Status
!= STATUS_BUFFER_TOO_SMALL
)
236 /* failed to query for name key */
241 /* allocate buffer to read key info */
242 KeyInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
) ExAllocatePool(NonPagedPool
, Size
);
245 /* not enough memory */
247 return STATUS_INSUFFICIENT_RESOURCES
;
250 /* now read the info */
251 Status
= ZwQueryValueKey(hKey
, &Name
, KeyValuePartialInformation
, (PVOID
)KeyInfo
, Size
, &Size
);
256 if (!NT_SUCCESS(Status
))
258 /* failed to read key */
263 /* store key information */
264 *OutInformation
= KeyInfo
;
274 KsPinPropertyHandler(
276 IN PKSPROPERTY Property
,
278 IN ULONG DescriptorsCount
,
279 IN
const KSPIN_DESCRIPTOR
* Descriptor
)
282 KSMULTIPLE_ITEM
* Item
;
283 PIO_STACK_LOCATION IoStack
;
286 PKSDATARANGE_AUDIO
*WaveFormatOut
;
287 PKSDATAFORMAT_WAVEFORMATEX WaveFormatIn
;
288 PKEY_VALUE_PARTIAL_INFORMATION KeyInfo
;
289 NTSTATUS Status
= STATUS_NOT_SUPPORTED
;
291 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
292 Buffer
= Irp
->UserBuffer
;
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
);
298 case KSPROPERTY_PIN_CTYPES
:
299 (*(PULONG
)Buffer
) = DescriptorsCount
;
300 Irp
->IoStatus
.Information
= sizeof(ULONG
);
301 Status
= STATUS_SUCCESS
;
303 case KSPROPERTY_PIN_DATAFLOW
:
304 Pin
= (KSP_PIN
*)Property
;
305 if (Pin
->PinId
>= DescriptorsCount
)
307 Status
= STATUS_INVALID_PARAMETER
;
308 Irp
->IoStatus
.Information
= 0;
311 Size
= sizeof(KSPIN_DATAFLOW
);
312 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
314 Irp
->IoStatus
.Information
= Size
;
315 Status
= STATUS_BUFFER_TOO_SMALL
;
319 *((KSPIN_DATAFLOW
*)Buffer
) = Descriptor
[Pin
->PinId
].DataFlow
;
320 Irp
->IoStatus
.Information
= sizeof(KSPIN_DATAFLOW
);
321 Status
= STATUS_SUCCESS
;
324 case KSPROPERTY_PIN_DATARANGES
:
325 Pin
= (KSP_PIN
*)Property
;
326 if (Pin
->PinId
>= DescriptorsCount
)
328 Status
= STATUS_INVALID_PARAMETER
;
329 Irp
->IoStatus
.Information
= 0;
332 Size
= sizeof(KSMULTIPLE_ITEM
);
333 for (Index
= 0; Index
< Descriptor
[Pin
->PinId
].DataRangesCount
; Index
++)
335 Size
+= Descriptor
[Pin
->PinId
].DataRanges
[Index
]->FormatSize
;
338 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== 0)
340 /* buffer too small */
341 Irp
->IoStatus
.Information
= Size
;
342 Status
= STATUS_BUFFER_OVERFLOW
;
346 Item
= (KSMULTIPLE_ITEM
*)Buffer
;
348 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(ULONG
))
350 /* store the result size */
352 Irp
->IoStatus
.Information
= sizeof(ULONG
);
353 Status
= STATUS_SUCCESS
;
357 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSMULTIPLE_ITEM
))
359 /* buffer too small */
360 Status
= STATUS_BUFFER_TOO_SMALL
;
364 /* store descriptor size */
366 Item
->Count
= Descriptor
[Pin
->PinId
].DataRangesCount
;
368 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(KSMULTIPLE_ITEM
))
370 Irp
->IoStatus
.Information
= sizeof(KSMULTIPLE_ITEM
);
371 Status
= STATUS_SUCCESS
;
375 /* now copy all dataranges */
376 Data
= (PUCHAR
)(Item
+1);
377 for (Index
= 0; Index
< Descriptor
[Pin
->PinId
].DataRangesCount
; Index
++)
379 RtlMoveMemory(Data
, Descriptor
[Pin
->PinId
].DataRanges
[Index
], Descriptor
[Pin
->PinId
].DataRanges
[Index
]->FormatSize
);
380 Data
= ((PUCHAR
)Data
+ Descriptor
[Pin
->PinId
].DataRanges
[Index
]->FormatSize
);
383 Status
= STATUS_SUCCESS
;
384 Irp
->IoStatus
.Information
= Size
;
386 case KSPROPERTY_PIN_INTERFACES
:
387 Pin
= (KSP_PIN
*)Property
;
388 if (Pin
->PinId
>= DescriptorsCount
)
390 Status
= STATUS_INVALID_PARAMETER
;
391 Irp
->IoStatus
.Information
= 0;
396 Size
= sizeof(KSMULTIPLE_ITEM
);
397 Size
+= max(1, Descriptor
[Pin
->PinId
].InterfacesCount
) * sizeof(KSPIN_INTERFACE
);
399 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
401 Irp
->IoStatus
.Information
= Size
;
402 Status
= STATUS_MORE_ENTRIES
;
406 Item
= (KSMULTIPLE_ITEM
*)Buffer
;
409 if (Descriptor
[Pin
->PinId
].InterfacesCount
)
411 Item
->Count
= Descriptor
[Pin
->PinId
].InterfacesCount
;
412 RtlMoveMemory((PVOID
)(Item
+ 1), Descriptor
[Pin
->PinId
].Interfaces
, Descriptor
[Pin
->PinId
].InterfacesCount
* sizeof(KSPIN_INTERFACE
));
417 RtlMoveMemory((PVOID
)(Item
+ 1), &StandardPinInterface
, sizeof(KSPIN_INTERFACE
));
420 Status
= STATUS_SUCCESS
;
421 Irp
->IoStatus
.Information
= Size
;
423 case KSPROPERTY_PIN_MEDIUMS
:
424 Pin
= (KSP_PIN
*)Property
;
425 if (Pin
->PinId
>= DescriptorsCount
)
427 Status
= STATUS_INVALID_PARAMETER
;
428 Irp
->IoStatus
.Information
= 0;
432 if (Descriptor
[Pin
->PinId
].MediumsCount
)
434 /* use mediums provided by driver */
435 return KsHandleSizedListQuery(Irp
, Descriptor
[Pin
->PinId
].MediumsCount
, sizeof(KSPIN_MEDIUM
), Descriptor
[Pin
->PinId
].Mediums
);
439 /* use standard medium */
440 return KsHandleSizedListQuery(Irp
, 1, sizeof(KSPIN_MEDIUM
), &StandardPinMedium
);
444 case KSPROPERTY_PIN_COMMUNICATION
:
445 Pin
= (KSP_PIN
*)Property
;
446 if (Pin
->PinId
>= DescriptorsCount
)
448 Status
= STATUS_INVALID_PARAMETER
;
449 Irp
->IoStatus
.Information
= 0;
453 Size
= sizeof(KSPIN_COMMUNICATION
);
454 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
456 Irp
->IoStatus
.Information
= Size
;
457 Status
= STATUS_BUFFER_TOO_SMALL
;
461 *((KSPIN_COMMUNICATION
*)Buffer
) = Descriptor
[Pin
->PinId
].Communication
;
462 Status
= STATUS_SUCCESS
;
463 Irp
->IoStatus
.Information
= Size
;
466 case KSPROPERTY_PIN_CATEGORY
:
467 Pin
= (KSP_PIN
*)Property
;
468 if (Pin
->PinId
>= DescriptorsCount
)
470 Status
= STATUS_INVALID_PARAMETER
;
471 Irp
->IoStatus
.Information
= 0;
476 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
478 Irp
->IoStatus
.Information
= Size
;
479 Status
= STATUS_BUFFER_TOO_SMALL
;
482 if (Descriptor
[Pin
->PinId
].Category
)
484 RtlMoveMemory(Buffer
, Descriptor
[Pin
->PinId
].Category
, sizeof(GUID
));
487 Status
= STATUS_SUCCESS
;
488 Irp
->IoStatus
.Information
= Size
;
491 case KSPROPERTY_PIN_NAME
:
492 Pin
= (KSP_PIN
*)Property
;
493 if (Pin
->PinId
>= DescriptorsCount
)
495 Status
= STATUS_INVALID_PARAMETER
;
496 Irp
->IoStatus
.Information
= 0;
500 if (!Descriptor
[Pin
->PinId
].Name
)
502 Irp
->IoStatus
.Information
= 0;
503 Status
= STATUS_SUCCESS
;
507 Status
= KspReadMediaCategory((LPGUID
)Descriptor
[Pin
->PinId
].Name
, &KeyInfo
);
508 if (!NT_SUCCESS(Status
))
510 Irp
->IoStatus
.Information
= 0;
514 Irp
->IoStatus
.Information
= KeyInfo
->DataLength
+ sizeof(WCHAR
);
517 if (KeyInfo
->DataLength
+ sizeof(WCHAR
) > IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
519 Status
= STATUS_MORE_ENTRIES
;
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
);
529 case KSPROPERTY_PIN_PROPOSEDATAFORMAT
:
530 Pin
= (KSP_PIN
*)Property
;
531 if (Pin
->PinId
>= DescriptorsCount
)
533 Status
= STATUS_INVALID_PARAMETER
;
534 Irp
->IoStatus
.Information
= 0;
537 Size
= sizeof(KSDATAFORMAT
);
538 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
540 Irp
->IoStatus
.Information
= Size
;
541 Status
= STATUS_BUFFER_TOO_SMALL
;
544 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
!= sizeof(KSDATAFORMAT_WAVEFORMATEX
))
547 Status
= STATUS_NOT_IMPLEMENTED
;
548 Irp
->IoStatus
.Information
= 0;
552 WaveFormatIn
= (PKSDATAFORMAT_WAVEFORMATEX
)Buffer
;
553 if (!Descriptor
[Pin
->PinId
].DataRanges
|| !Descriptor
[Pin
->PinId
].DataRangesCount
)
555 Status
= STATUS_UNSUCCESSFUL
;
556 Irp
->IoStatus
.Information
= 0;
559 WaveFormatOut
= (PKSDATARANGE_AUDIO
*)Descriptor
[Pin
->PinId
].DataRanges
;
560 for(Index
= 0; Index
< Descriptor
[Pin
->PinId
].DataRangesCount
; Index
++)
562 if (WaveFormatOut
[Index
]->DataRange
.FormatSize
!= sizeof(KSDATARANGE_AUDIO
))
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
)
574 Irp
->IoStatus
.Status
= STATUS_NO_MATCH
;
575 Irp
->IoStatus
.Information
= 0;
576 return STATUS_NO_MATCH
;
580 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
581 Irp
->IoStatus
.Information
= 0;
582 return STATUS_SUCCESS
;
585 Status
= STATUS_NO_MATCH
;
586 Irp
->IoStatus
.Information
= 0;
589 DPRINT1("Unhandled property request %x\n", Property
->Id
);
590 Status
= STATUS_NOT_IMPLEMENTED
;
591 Irp
->IoStatus
.Information
= 0;
600 KSDDKAPI NTSTATUS NTAPI
601 KsPinDataIntersectionEx(
605 IN ULONG DescriptorsCount
,
606 IN
const KSPIN_DESCRIPTOR
* Descriptor
,
607 IN ULONG DescriptorSize
,
608 IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL
,
609 IN PVOID HandlerContext OPTIONAL
)
612 return STATUS_UNSUCCESSFUL
;
621 KsPinDataIntersection(
625 IN ULONG DescriptorsCount
,
626 IN
const KSPIN_DESCRIPTOR
* Descriptor
,
627 IN PFNKSINTERSECTHANDLER IntersectHandler
)
629 KSMULTIPLE_ITEM
* Item
;
630 KSDATARANGE
* DataRange
;
631 PIO_STACK_LOCATION IoStack
;
636 /* get current irp stack location */
637 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
639 /* calculate minimum data size */
640 Size
= sizeof(KSP_PIN
) + sizeof(KSMULTIPLE_ITEM
) + sizeof(KSDATARANGE
);
641 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< Size
)
643 /* buffer too small */
644 Irp
->IoStatus
.Information
= Size
;
645 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
646 return STATUS_BUFFER_TOO_SMALL
;
648 /* is pin id out of bounds */
649 if (Pin
->PinId
>= DescriptorsCount
)
652 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
653 Irp
->IoStatus
.Information
= 0;
654 return STATUS_INVALID_PARAMETER
;
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
++)
664 /* call intersect handler */
665 Status
= IntersectHandler(Irp
, Pin
, DataRange
, Data
);
666 if (NT_SUCCESS(Status
))
668 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< DataRange
->FormatSize
)
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
;
675 RtlMoveMemory(Irp
->UserBuffer
, DataRange
, sizeof(KSDATARANGE
));
676 Irp
->IoStatus
.Information
= sizeof(KSDATARANGE
);
677 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
678 return STATUS_SUCCESS
;
683 Irp
->IoStatus
.Information
= 0;
684 Irp
->IoStatus
.Status
= STATUS_NO_MATCH
;
685 return STATUS_NO_MATCH
;
695 KsHandleSizedListQuery(
697 IN ULONG DataItemsCount
,
698 IN ULONG DataItemSize
,
699 IN
const VOID
* DataItems
)
702 PIO_STACK_LOCATION IoStack
;
703 PKSMULTIPLE_ITEM Item
;
705 /* get current irp stack location */
706 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
709 Size
= DataItemSize
* DataItemsCount
+ sizeof(KSMULTIPLE_ITEM
);
711 /* get multiple item */
712 Item
= (PKSMULTIPLE_ITEM
)Irp
->UserBuffer
;
714 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== 0)
716 /* buffer too small */
717 Irp
->IoStatus
.Information
= Size
;
719 return STATUS_BUFFER_OVERFLOW
;
722 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(ULONG
))
724 /* store just the size */
726 Irp
->IoStatus
.Information
= sizeof(ULONG
);
728 return STATUS_SUCCESS
;
732 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSMULTIPLE_ITEM
))
734 /* buffer too small */
735 return STATUS_BUFFER_TOO_SMALL
;
738 Item
->Count
= DataItemsCount
;
739 Item
->Size
= DataItemSize
;
741 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(KSMULTIPLE_ITEM
))
743 /* buffer can only hold the length descriptor */
744 Irp
->IoStatus
.Information
= sizeof(KSMULTIPLE_ITEM
);
745 return STATUS_SUCCESS
;
748 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= Size
)
751 RtlMoveMemory((PVOID
)(Item
+ 1), DataItems
, DataItemSize
* DataItemsCount
);
753 Irp
->IoStatus
.Information
= Size
;
755 return STATUS_SUCCESS
;
759 /* buffer too small */
760 return STATUS_BUFFER_TOO_SMALL
;