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
, 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
;
197 IN ULONG MethodSetsCount
,
198 IN PKSMETHOD_SET MethodSet
)
200 return KspMethodHandlerWithAllocator(Irp
, MethodSetsCount
, MethodSet
, NULL
, 0);
209 KsMethodHandlerWithAllocator(
211 IN ULONG MethodSetsCount
,
212 IN PKSMETHOD_SET MethodSet
,
213 IN PFNKSALLOCATOR Allocator OPTIONAL
,
214 IN ULONG MethodItemSize OPTIONAL
)
216 return KspMethodHandlerWithAllocator(Irp
, MethodSetsCount
, MethodSet
, Allocator
, MethodItemSize
);
221 FindFastMethodHandler(
222 IN ULONG FastIoCount
,
223 IN
const KSFASTMETHOD_ITEM
* FastIoTable
,
224 IN PKSMETHOD MethodId
,
225 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
229 /* iterate through all items */
230 for(Index
= 0; Index
< FastIoCount
; Index
++)
232 if (MethodId
->Id
== FastIoTable
[Index
].MethodId
)
234 if (FastIoTable
[Index
].MethodSupported
)
236 *FastPropertyHandler
= FastIoTable
[Index
].MethodHandler
;
237 return STATUS_SUCCESS
;
242 /* no fast property handler found */
243 return STATUS_NOT_FOUND
;
254 IN PFILE_OBJECT FileObject
,
255 IN PKSMETHOD UNALIGNED Method
,
256 IN ULONG MethodLength
,
257 IN OUT PVOID UNALIGNED Data
,
259 OUT PIO_STATUS_BLOCK IoStatus
,
260 IN ULONG MethodSetsCount
,
261 IN
const KSMETHOD_SET
* MethodSet
)
263 KSMETHOD MethodRequest
;
264 KPROCESSOR_MODE Mode
;
265 NTSTATUS Status
= STATUS_SUCCESS
;
267 PFNKSFASTHANDLER FastMethodHandler
;
269 if (MethodLength
< sizeof(KSPROPERTY
))
271 /* invalid request */
275 /* get previous mode */
276 Mode
= ExGetPreviousMode();
278 if (Mode
== KernelMode
)
281 RtlMoveMemory(&MethodRequest
, Method
, sizeof(KSMETHOD
));
285 /* need to probe the buffer */
288 ProbeForRead(Method
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
289 RtlMoveMemory(&MethodRequest
, Method
, sizeof(KSMETHOD
));
291 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
293 /* Exception, get the error code */
294 Status
= _SEH2_GetExceptionCode();
297 if (!NT_SUCCESS(Status
))
301 /* are there any property sets provided */
304 /* iterate through all property sets count */
308 /* does the property id match */
309 if (IsEqualGUIDAligned(MethodSet
[Index
].Set
, &MethodRequest
.Set
))
311 /* try to find a fast property handler */
312 Status
= FindFastMethodHandler(MethodSet
[Index
].FastIoCount
, MethodSet
[Index
].FastIoTable
, &MethodRequest
, &FastMethodHandler
);
314 if (NT_SUCCESS(Status
))
316 /* call fast property handler */
317 ASSERT(MethodLength
== sizeof(KSMETHOD
)); /* FIXME check if property length is bigger -> copy params */
318 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
319 return FastMethodHandler(FileObject
, &MethodRequest
, sizeof(KSMETHOD
), Data
, DataLength
, IoStatus
);
322 /* move to next item */
324 }while(Index
< MethodSetsCount
);