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
13 IN PIO_STATUS_BLOCK IoStatus
,
14 IN
const KSMETHOD_SET
* MethodSet
,
15 IN ULONG MethodSetCount
,
17 IN ULONG InputBufferLength
,
18 IN ULONG OutputBufferLength
,
19 OUT PVOID OutputBuffer
,
20 OUT PFNKSHANDLER
*MethodHandler
,
21 OUT PKSMETHOD_SET
* Set
)
23 ULONG Index
, ItemIndex
;
25 for(Index
= 0; Index
< MethodSetCount
; Index
++)
27 ASSERT(MethodSet
[Index
].Set
);
29 if (IsEqualGUIDAligned(&Method
->Set
, MethodSet
[Index
].Set
))
31 for(ItemIndex
= 0; ItemIndex
< MethodSet
[Index
].MethodsCount
; ItemIndex
++)
33 if (MethodSet
[Index
].MethodItem
[ItemIndex
].MethodId
== Method
->Id
)
35 if (MethodSet
[Index
].MethodItem
[ItemIndex
].MinMethod
> InputBufferLength
)
37 /* too small input buffer */
38 IoStatus
->Information
= MethodSet
[Index
].MethodItem
[ItemIndex
].MinMethod
;
39 return STATUS_INVALID_PARAMETER
;
42 if (MethodSet
[Index
].MethodItem
[ItemIndex
].MinData
> OutputBufferLength
)
44 /* too small output buffer */
45 IoStatus
->Information
= MethodSet
[Index
].MethodItem
[ItemIndex
].MinData
;
46 return STATUS_MORE_ENTRIES
;
48 if (Method
->Flags
& KSMETHOD_TYPE_BASICSUPPORT
)
51 PKSPROPERTY_DESCRIPTION Description
;
53 if (sizeof(ULONG
) > OutputBufferLength
)
55 /* too small buffer */
56 return STATUS_INVALID_PARAMETER
;
59 /* get output buffer */
60 Flags
= (PULONG
)OutputBuffer
;
63 *Flags
= MethodSet
[Index
].MethodItem
[ItemIndex
].Flags
;
65 IoStatus
->Information
= sizeof(ULONG
);
67 if (OutputBufferLength
>= sizeof(KSPROPERTY_DESCRIPTION
))
69 /* get output buffer */
70 Description
= (PKSPROPERTY_DESCRIPTION
)OutputBuffer
;
73 Description
->DescriptionSize
= sizeof(KSPROPERTY_DESCRIPTION
);
74 Description
->PropTypeSet
.Set
= KSPROPTYPESETID_General
;
75 Description
->PropTypeSet
.Id
= 0;
76 Description
->PropTypeSet
.Flags
= 0;
77 Description
->MembersListCount
= 0;
78 Description
->Reserved
= 0;
80 IoStatus
->Information
= sizeof(KSPROPERTY_DESCRIPTION
);
82 return STATUS_SUCCESS
;
84 *MethodHandler
= MethodSet
[Index
].MethodItem
[ItemIndex
].MethodHandler
;
85 *Set
= (PKSMETHOD_SET
)&MethodSet
[Index
];
86 return STATUS_SUCCESS
;
91 return STATUS_NOT_FOUND
;
96 KspMethodHandlerWithAllocator(
98 IN ULONG MethodSetsCount
,
99 IN
const KSMETHOD_SET
*MethodSet
,
100 IN PFNKSALLOCATOR Allocator OPTIONAL
,
101 IN ULONG MethodItemSize OPTIONAL
)
105 PIO_STACK_LOCATION IoStack
;
107 PFNKSHANDLER MethodHandler
= NULL
;
111 /* get current irp stack */
112 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
114 /* check if inputbuffer at least holds KSMETHOD item */
115 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSMETHOD
))
117 /* invalid parameter */
118 Irp
->IoStatus
.Information
= sizeof(KSPROPERTY
);
119 return STATUS_INVALID_BUFFER_SIZE
;
122 /* FIXME probe the input / output buffer if from user mode */
124 /* get input property request */
125 Method
= (PKSMETHOD
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
127 // DPRINT("KspMethodHandlerWithAllocator Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
130 ASSERT(MethodItemSize
== 0 || MethodItemSize
== sizeof(KSMETHOD_ITEM
));
132 /* find the method handler */
133 Status
= FindMethodHandler(&Irp
->IoStatus
, MethodSet
, MethodSetsCount
, Method
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, Irp
->UserBuffer
, &MethodHandler
, &Set
);
135 if (NT_SUCCESS(Status
) && MethodHandler
)
137 /* call method handler */
138 KSMETHOD_SET_IRP_STORAGE(Irp
) = Set
;
139 Status
= MethodHandler(Irp
, Method
, Irp
->UserBuffer
);
141 if (Status
== STATUS_BUFFER_TOO_SMALL
)
143 /* output buffer is too small */
146 /* allocate the requested amount */
147 Status
= Allocator(Irp
, Irp
->IoStatus
.Information
, FALSE
);
149 /* check if the block was allocated */
150 if (!NT_SUCCESS(Status
))
153 return STATUS_INSUFFICIENT_RESOURCES
;
156 /* re-call method handler */
157 Status
= MethodHandler(Irp
, Method
, Irp
->UserBuffer
);
161 else if (IsEqualGUIDAligned(&Method
->Set
, &GUID_NULL
) && Method
->Id
== 0 && Method
->Flags
== KSMETHOD_TYPE_SETSUPPORT
)
164 Irp
->IoStatus
.Information
= sizeof(GUID
) * MethodSetsCount
;
165 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
) * MethodSetsCount
)
168 return STATUS_MORE_ENTRIES
;
172 Guid
= (LPGUID
)Irp
->UserBuffer
;
174 // copy property guids from property sets
175 for(Index
= 0; Index
< MethodSetsCount
; Index
++)
177 RtlMoveMemory(&Guid
[Index
], MethodSet
[Index
].Set
, sizeof(GUID
));
179 return STATUS_SUCCESS
;
194 IN ULONG MethodSetsCount
,
195 IN PKSMETHOD_SET MethodSet
)
197 return KspMethodHandlerWithAllocator(Irp
, MethodSetsCount
, MethodSet
, NULL
, 0);
206 KsMethodHandlerWithAllocator(
208 IN ULONG MethodSetsCount
,
209 IN PKSMETHOD_SET MethodSet
,
210 IN PFNKSALLOCATOR Allocator OPTIONAL
,
211 IN ULONG MethodItemSize OPTIONAL
)
213 return KspMethodHandlerWithAllocator(Irp
, MethodSetsCount
, MethodSet
, Allocator
, MethodItemSize
);
218 FindFastMethodHandler(
219 IN ULONG FastIoCount
,
220 IN
const KSFASTMETHOD_ITEM
* FastIoTable
,
221 IN PKSMETHOD MethodId
,
222 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
226 /* iterate through all items */
227 for(Index
= 0; Index
< FastIoCount
; Index
++)
229 if (MethodId
->Id
== FastIoTable
[Index
].MethodId
)
231 if (FastIoTable
[Index
].MethodSupported
)
233 *FastPropertyHandler
= FastIoTable
[Index
].MethodHandler
;
234 return STATUS_SUCCESS
;
239 /* no fast property handler found */
240 return STATUS_NOT_FOUND
;
251 IN PFILE_OBJECT FileObject
,
252 IN PKSMETHOD UNALIGNED Method
,
253 IN ULONG MethodLength
,
254 IN OUT PVOID UNALIGNED Data
,
256 OUT PIO_STATUS_BLOCK IoStatus
,
257 IN ULONG MethodSetsCount
,
258 IN
const KSMETHOD_SET
* MethodSet
)
260 KSMETHOD MethodRequest
;
261 KPROCESSOR_MODE Mode
;
262 NTSTATUS Status
= STATUS_SUCCESS
;
264 PFNKSFASTHANDLER FastMethodHandler
;
266 if (MethodLength
< sizeof(KSPROPERTY
))
268 /* invalid request */
272 /* get previous mode */
273 Mode
= ExGetPreviousMode();
275 if (Mode
== KernelMode
)
278 RtlMoveMemory(&MethodRequest
, Method
, sizeof(KSMETHOD
));
282 /* need to probe the buffer */
285 ProbeForRead(Method
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
286 RtlMoveMemory(&MethodRequest
, Method
, sizeof(KSMETHOD
));
288 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
290 /* Exception, get the error code */
291 Status
= _SEH2_GetExceptionCode();
294 if (!NT_SUCCESS(Status
))
298 /* are there any property sets provided */
301 /* iterate through all property sets count */
305 /* does the property id match */
306 if (IsEqualGUIDAligned(MethodSet
[Index
].Set
, &MethodRequest
.Set
))
308 /* try to find a fast property handler */
309 Status
= FindFastMethodHandler(MethodSet
[Index
].FastIoCount
, MethodSet
[Index
].FastIoTable
, &MethodRequest
, &FastMethodHandler
);
311 if (NT_SUCCESS(Status
))
313 /* call fast property handler */
314 ASSERT(MethodLength
== sizeof(KSMETHOD
)); /* FIXME check if property length is bigger -> copy params */
315 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
316 return FastMethodHandler(FileObject
, &MethodRequest
, sizeof(KSMETHOD
), Data
, DataLength
, IoStatus
);
319 /* move to next item */
321 }while(Index
< MethodSetsCount
);