2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/methods.c
5 * PURPOSE: KS Allocator functions
6 * PROGRAMMER: Johannes Anderwald
16 IN PIO_STATUS_BLOCK IoStatus
,
17 IN
const KSMETHOD_SET
* MethodSet
,
18 IN ULONG MethodSetCount
,
20 IN ULONG InputBufferLength
,
21 IN ULONG OutputBufferLength
,
22 OUT PVOID OutputBuffer
,
23 OUT PFNKSHANDLER
*MethodHandler
,
24 OUT PKSMETHOD_SET
* Set
)
26 ULONG Index
, ItemIndex
;
28 for(Index
= 0; Index
< MethodSetCount
; Index
++)
30 ASSERT(MethodSet
[Index
].Set
);
32 if (IsEqualGUIDAligned(&Method
->Set
, MethodSet
[Index
].Set
))
34 for(ItemIndex
= 0; ItemIndex
< MethodSet
[Index
].MethodsCount
; ItemIndex
++)
36 if (MethodSet
[Index
].MethodItem
[ItemIndex
].MethodId
== Method
->Id
)
38 if (MethodSet
[Index
].MethodItem
[ItemIndex
].MinMethod
> InputBufferLength
)
40 /* too small input buffer */
41 IoStatus
->Information
= MethodSet
[Index
].MethodItem
[ItemIndex
].MinMethod
;
42 return STATUS_INVALID_PARAMETER
;
45 if (MethodSet
[Index
].MethodItem
[ItemIndex
].MinData
> OutputBufferLength
)
47 /* too small output buffer */
48 IoStatus
->Information
= MethodSet
[Index
].MethodItem
[ItemIndex
].MinData
;
49 return STATUS_MORE_ENTRIES
;
51 if (Method
->Flags
& KSMETHOD_TYPE_BASICSUPPORT
)
54 PKSPROPERTY_DESCRIPTION Description
;
56 if (sizeof(ULONG
) > OutputBufferLength
)
58 /* too small buffer */
59 return STATUS_INVALID_PARAMETER
;
62 /* get output buffer */
63 Flags
= (PULONG
)OutputBuffer
;
66 *Flags
= MethodSet
[Index
].MethodItem
[ItemIndex
].Flags
;
68 IoStatus
->Information
= sizeof(ULONG
);
70 if (OutputBufferLength
>= sizeof(KSPROPERTY_DESCRIPTION
))
72 /* get output buffer */
73 Description
= (PKSPROPERTY_DESCRIPTION
)OutputBuffer
;
76 Description
->DescriptionSize
= sizeof(KSPROPERTY_DESCRIPTION
);
77 Description
->PropTypeSet
.Set
= KSPROPTYPESETID_General
;
78 Description
->PropTypeSet
.Id
= 0;
79 Description
->PropTypeSet
.Flags
= 0;
80 Description
->MembersListCount
= 0;
81 Description
->Reserved
= 0;
83 IoStatus
->Information
= sizeof(KSPROPERTY_DESCRIPTION
);
85 return STATUS_SUCCESS
;
87 *MethodHandler
= MethodSet
[Index
].MethodItem
[ItemIndex
].MethodHandler
;
88 *Set
= (PKSMETHOD_SET
)&MethodSet
[Index
];
89 return STATUS_SUCCESS
;
94 return STATUS_NOT_FOUND
;
99 KspMethodHandlerWithAllocator(
101 IN ULONG MethodSetsCount
,
102 IN
const KSMETHOD_SET
*MethodSet
,
103 IN PFNKSALLOCATOR Allocator OPTIONAL
,
104 IN ULONG MethodItemSize OPTIONAL
)
108 PIO_STACK_LOCATION IoStack
;
110 PFNKSHANDLER MethodHandler
= NULL
;
114 /* get current irp stack */
115 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
117 /* check if inputbuffer at least holds KSMETHOD item */
118 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSMETHOD
))
120 /* invalid parameter */
121 Irp
->IoStatus
.Information
= sizeof(KSPROPERTY
);
122 return STATUS_INVALID_BUFFER_SIZE
;
125 /* FIXME probe the input / output buffer if from user mode */
127 /* get input property request */
128 Method
= (PKSMETHOD
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
130 // DPRINT("KspMethodHandlerWithAllocator Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
133 ASSERT(MethodItemSize
== 0 || MethodItemSize
== sizeof(KSMETHOD_ITEM
));
135 /* find the method handler */
136 Status
= FindMethodHandler(&Irp
->IoStatus
, MethodSet
, MethodSetsCount
, Method
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, Irp
->UserBuffer
, &MethodHandler
, &Set
);
138 if (NT_SUCCESS(Status
) && MethodHandler
)
140 /* call method handler */
141 KSMETHOD_SET_IRP_STORAGE(Irp
) = Set
;
142 Status
= MethodHandler(Irp
, Method
, Irp
->UserBuffer
);
144 if (Status
== STATUS_BUFFER_TOO_SMALL
)
146 /* output buffer is too small */
149 /* allocate the requested amount */
150 Status
= Allocator(Irp
, (ULONG
)Irp
->IoStatus
.Information
, FALSE
);
152 /* check if the block was allocated */
153 if (!NT_SUCCESS(Status
))
156 return STATUS_INSUFFICIENT_RESOURCES
;
159 /* re-call method handler */
160 Status
= MethodHandler(Irp
, Method
, Irp
->UserBuffer
);
164 else if (IsEqualGUIDAligned(&Method
->Set
, &GUID_NULL
) && Method
->Id
== 0 && Method
->Flags
== KSMETHOD_TYPE_SETSUPPORT
)
167 Irp
->IoStatus
.Information
= sizeof(GUID
) * MethodSetsCount
;
168 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
) * MethodSetsCount
)
171 return STATUS_MORE_ENTRIES
;
175 Guid
= (LPGUID
)Irp
->UserBuffer
;
177 // copy property guids from property sets
178 for(Index
= 0; Index
< MethodSetsCount
; Index
++)
180 RtlMoveMemory(&Guid
[Index
], MethodSet
[Index
].Set
, sizeof(GUID
));
182 return STATUS_SUCCESS
;
192 _IRQL_requires_max_(PASSIVE_LEVEL
)
198 _In_ ULONG MethodSetsCount
,
199 _In_reads_(MethodSetsCount
) const KSMETHOD_SET
* MethodSet
)
201 return KspMethodHandlerWithAllocator(Irp
, MethodSetsCount
, MethodSet
, NULL
, 0);
207 _IRQL_requires_max_(PASSIVE_LEVEL
)
211 KsMethodHandlerWithAllocator(
213 _In_ ULONG MethodSetsCount
,
214 _In_reads_(MethodSetsCount
) const KSMETHOD_SET
* MethodSet
,
215 _In_opt_ PFNKSALLOCATOR Allocator
,
216 _In_opt_ ULONG MethodItemSize
)
218 return KspMethodHandlerWithAllocator(Irp
, MethodSetsCount
, MethodSet
, Allocator
, MethodItemSize
);
223 FindFastMethodHandler(
224 IN ULONG FastIoCount
,
225 IN
const KSFASTMETHOD_ITEM
* FastIoTable
,
226 IN PKSMETHOD MethodId
,
227 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
231 /* iterate through all items */
232 for(Index
= 0; Index
< FastIoCount
; Index
++)
234 if (MethodId
->Id
== FastIoTable
[Index
].MethodId
)
236 if (FastIoTable
[Index
].MethodSupported
)
238 *FastPropertyHandler
= FastIoTable
[Index
].MethodHandler
;
239 return STATUS_SUCCESS
;
244 /* no fast property handler found */
245 return STATUS_NOT_FOUND
;
256 IN PFILE_OBJECT FileObject
,
257 IN PKSMETHOD UNALIGNED Method
,
258 IN ULONG MethodLength
,
259 IN OUT PVOID UNALIGNED Data
,
261 OUT PIO_STATUS_BLOCK IoStatus
,
262 IN ULONG MethodSetsCount
,
263 IN
const KSMETHOD_SET
* MethodSet
)
265 KSMETHOD MethodRequest
;
266 KPROCESSOR_MODE Mode
;
267 NTSTATUS Status
= STATUS_SUCCESS
;
269 PFNKSFASTHANDLER FastMethodHandler
;
271 if (MethodLength
< sizeof(KSPROPERTY
))
273 /* invalid request */
277 /* get previous mode */
278 Mode
= ExGetPreviousMode();
280 if (Mode
== KernelMode
)
283 RtlMoveMemory(&MethodRequest
, Method
, sizeof(KSMETHOD
));
287 /* need to probe the buffer */
290 ProbeForRead(Method
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
291 RtlMoveMemory(&MethodRequest
, Method
, sizeof(KSMETHOD
));
293 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
295 /* Exception, get the error code */
296 Status
= _SEH2_GetExceptionCode();
299 if (!NT_SUCCESS(Status
))
303 /* are there any property sets provided */
306 /* iterate through all property sets count */
310 /* does the property id match */
311 if (IsEqualGUIDAligned(MethodSet
[Index
].Set
, &MethodRequest
.Set
))
313 /* try to find a fast property handler */
314 Status
= FindFastMethodHandler(MethodSet
[Index
].FastIoCount
, MethodSet
[Index
].FastIoTable
, &MethodRequest
, &FastMethodHandler
);
316 if (NT_SUCCESS(Status
))
318 /* call fast property handler */
319 ASSERT(MethodLength
== sizeof(KSMETHOD
)); /* FIXME check if property length is bigger -> copy params */
320 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
321 return FastMethodHandler(FileObject
, &MethodRequest
, sizeof(KSMETHOD
), Data
, DataLength
, IoStatus
);
324 /* move to next item */
326 }while(Index
< MethodSetsCount
);