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;
515 Irp
->IoStatus
.Information
= KeyInfo
->DataLength
+ sizeof(WCHAR
);
517 if (KeyInfo
->DataLength
+ sizeof(WCHAR
) > IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
519 Status
= STATUS_BUFFER_OVERFLOW
;
524 RtlMoveMemory(Irp
->UserBuffer
, &KeyInfo
->Data
, KeyInfo
->DataLength
);
525 ((LPWSTR
)Irp
->UserBuffer
)[KeyInfo
->DataLength
/ sizeof(WCHAR
)] = L
'\0';
528 case KSPROPERTY_PIN_PROPOSEDATAFORMAT
:
529 Pin
= (KSP_PIN
*)Property
;
530 if (Pin
->PinId
>= DescriptorsCount
)
532 Status
= STATUS_INVALID_PARAMETER
;
533 Irp
->IoStatus
.Information
= 0;
536 Size
= sizeof(KSDATAFORMAT
);
537 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< Size
)
539 Irp
->IoStatus
.Information
= Size
;
540 Status
= STATUS_BUFFER_TOO_SMALL
;
543 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
!= sizeof(KSDATAFORMAT_WAVEFORMATEX
))
546 Status
= STATUS_NOT_IMPLEMENTED
;
547 Irp
->IoStatus
.Information
= 0;
551 WaveFormatIn
= (PKSDATAFORMAT_WAVEFORMATEX
)Buffer
;
552 if (!Descriptor
[Pin
->PinId
].DataRanges
|| !Descriptor
[Pin
->PinId
].DataRangesCount
)
554 Status
= STATUS_UNSUCCESSFUL
;
555 Irp
->IoStatus
.Information
= 0;
558 WaveFormatOut
= (PKSDATARANGE_AUDIO
*)Descriptor
[Pin
->PinId
].DataRanges
;
559 for(Index
= 0; Index
< Descriptor
[Pin
->PinId
].DataRangesCount
; Index
++)
561 if (WaveFormatOut
[Index
]->DataRange
.FormatSize
!= sizeof(KSDATARANGE_AUDIO
))
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
)
573 Irp
->IoStatus
.Status
= STATUS_NO_MATCH
;
574 Irp
->IoStatus
.Information
= 0;
575 return STATUS_NO_MATCH
;
579 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
580 Irp
->IoStatus
.Information
= 0;
581 return STATUS_SUCCESS
;
584 Status
= STATUS_NO_MATCH
;
585 Irp
->IoStatus
.Information
= 0;
588 DPRINT1("Unhandled property request %x\n", Property
->Id
);
589 Status
= STATUS_NOT_IMPLEMENTED
;
590 Irp
->IoStatus
.Information
= 0;
599 KSDDKAPI NTSTATUS NTAPI
600 KsPinDataIntersectionEx(
604 IN ULONG DescriptorsCount
,
605 IN
const KSPIN_DESCRIPTOR
* Descriptor
,
606 IN ULONG DescriptorSize
,
607 IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL
,
608 IN PVOID HandlerContext OPTIONAL
)
611 return STATUS_UNSUCCESSFUL
;
620 KsPinDataIntersection(
624 IN ULONG DescriptorsCount
,
625 IN
const KSPIN_DESCRIPTOR
* Descriptor
,
626 IN PFNKSINTERSECTHANDLER IntersectHandler
)
628 KSMULTIPLE_ITEM
* Item
;
629 KSDATARANGE
* DataRange
;
630 PIO_STACK_LOCATION IoStack
;
635 /* get current irp stack location */
636 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
638 /* calculate minimum data size */
639 Size
= sizeof(KSP_PIN
) + sizeof(KSMULTIPLE_ITEM
) + sizeof(KSDATARANGE
);
640 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< Size
)
642 /* buffer too small */
643 Irp
->IoStatus
.Information
= Size
;
644 Irp
->IoStatus
.Status
= STATUS_BUFFER_TOO_SMALL
;
645 return STATUS_BUFFER_TOO_SMALL
;
647 /* is pin id out of bounds */
648 if (Pin
->PinId
>= DescriptorsCount
)
651 Irp
->IoStatus
.Status
= STATUS_INVALID_PARAMETER
;
652 Irp
->IoStatus
.Information
= 0;
653 return STATUS_INVALID_PARAMETER
;
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
++)
663 /* call intersect handler */
664 Status
= IntersectHandler(Irp
, Pin
, DataRange
, Data
);
665 if (NT_SUCCESS(Status
))
667 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< DataRange
->FormatSize
)
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
;
674 RtlMoveMemory(Irp
->UserBuffer
, DataRange
, sizeof(KSDATARANGE
));
675 Irp
->IoStatus
.Information
= sizeof(KSDATARANGE
);
676 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
677 return STATUS_SUCCESS
;
682 Irp
->IoStatus
.Information
= 0;
683 Irp
->IoStatus
.Status
= STATUS_NO_MATCH
;
684 return STATUS_NO_MATCH
;
694 KsHandleSizedListQuery(
696 IN ULONG DataItemsCount
,
697 IN ULONG DataItemSize
,
698 IN
const VOID
* DataItems
)
701 PIO_STACK_LOCATION IoStack
;
702 PKSMULTIPLE_ITEM Item
;
704 /* get current irp stack location */
705 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
708 Size
= DataItemSize
* DataItemsCount
+ sizeof(KSMULTIPLE_ITEM
);
710 /* get multiple item */
711 Item
= (PKSMULTIPLE_ITEM
)Irp
->UserBuffer
;
713 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== 0)
715 /* buffer too small */
716 Irp
->IoStatus
.Information
= Size
;
718 return STATUS_BUFFER_OVERFLOW
;
721 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(ULONG
))
723 /* store just the size */
725 Irp
->IoStatus
.Information
= sizeof(ULONG
);
727 return STATUS_SUCCESS
;
731 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(KSMULTIPLE_ITEM
))
733 /* buffer too small */
734 return STATUS_BUFFER_TOO_SMALL
;
737 Item
->Count
= DataItemsCount
;
738 Item
->Size
= DataItemSize
;
740 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
== sizeof(KSMULTIPLE_ITEM
))
742 /* buffer can only hold the length descriptor */
743 Irp
->IoStatus
.Information
= sizeof(KSMULTIPLE_ITEM
);
744 return STATUS_SUCCESS
;
747 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
>= Size
)
750 RtlMoveMemory((PVOID
)(Item
+ 1), DataItems
, DataItemSize
* DataItemsCount
);
752 Irp
->IoStatus
.Information
= Size
;
754 return STATUS_SUCCESS
;
758 /* buffer too small */
759 return STATUS_BUFFER_TOO_SMALL
;