2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/event.c
5 * PURPOSE: KS property handling functions
6 * PROGRAMMER: Johannes Anderwald
14 IN PIO_STATUS_BLOCK IoStatus
,
15 IN
const KSPROPERTY_SET
* PropertySet
,
16 IN ULONG PropertySetCount
,
17 IN PKSPROPERTY Property
,
18 IN ULONG InputBufferLength
,
19 IN ULONG OutputBufferLength
,
20 OUT PVOID OutputBuffer
,
21 OUT PFNKSHANDLER
*PropertyHandler
)
23 ULONG Index
, ItemIndex
;
26 for(Index
= 0; Index
< PropertySetCount
; Index
++)
28 ASSERT(PropertySet
[Index
].Set
);
30 if (IsEqualGUIDAligned(&Property
->Set
, PropertySet
[Index
].Set
))
32 for(ItemIndex
= 0; ItemIndex
< PropertySet
[Index
].PropertiesCount
; ItemIndex
++)
34 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].PropertyId
== Property
->Id
)
36 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
> InputBufferLength
)
38 /* too small input buffer */
39 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
;
40 return STATUS_INVALID_PARAMETER
;
43 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
> OutputBufferLength
)
45 /* too small output buffer */
46 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
;
47 return STATUS_MORE_ENTRIES
;
50 if (Property
->Flags
& KSPROPERTY_TYPE_BASICSUPPORT
)
52 if (sizeof(ULONG
) > OutputBufferLength
)
54 /* too small buffer */
55 return STATUS_INVALID_PARAMETER
;
58 /* get output buffer */
59 Flags
= (PULONG
)OutputBuffer
;
62 *Flags
= KSPROPERTY_TYPE_BASICSUPPORT
;
64 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].GetSupported
)
65 *Flags
|= KSPROPERTY_TYPE_GET
;
67 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SetSupported
)
68 *Flags
|= KSPROPERTY_TYPE_SET
;
70 IoStatus
->Information
= sizeof(ULONG
);
72 if (OutputBufferLength
>= sizeof(KSPROPERTY_DESCRIPTION
))
74 /* get output buffer */
75 Description
= (PKSPROPERTY_DESCRIPTION
)OutputBuffer
;
78 Description
->DescriptionSize
= sizeof(KSPROPERTY_DESCRIPTION
);
79 Description
->PropTypeSet
.Set
= KSPROPTYPESETID_General
;
80 Description
->PropTypeSet
.Id
= 0;
81 Description
->PropTypeSet
.Flags
= 0;
82 Description
->MembersListCount
= 0;
83 Description
->Reserved
= 0;
85 IoStatus
->Information
= sizeof(KSPROPERTY_DESCRIPTION
);
90 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
91 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SetPropertyHandler
;
93 if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
94 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].GetPropertyHandler
;
96 return STATUS_SUCCESS
;
101 return STATUS_NOT_FOUND
;
108 IN ULONG PropertySetsCount
,
109 IN
const KSPROPERTY_SET
* PropertySet
,
110 IN PFNKSALLOCATOR Allocator OPTIONAL
,
111 IN ULONG PropertyItemSize OPTIONAL
)
113 PKSPROPERTY Property
;
114 PIO_STACK_LOCATION IoStack
;
116 PFNKSHANDLER PropertyHandler
= NULL
;
120 /* get current irp stack */
121 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
123 /* check if inputbuffer at least holds KSPROPERTY item */
124 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
126 /* invalid parameter */
127 Irp
->IoStatus
.Information
= sizeof(KSPROPERTY
);
128 return STATUS_INVALID_BUFFER_SIZE
;
131 /* FIXME probe the input / output buffer if from user mode */
133 /* get input property request */
134 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
136 DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp
, PropertySetsCount
, PropertySet
, Allocator
, PropertyItemSize
, sizeof(KSPROPERTY_ITEM
));
139 ASSERT(PropertyItemSize
== 0 || PropertyItemSize
== sizeof(KSPROPERTY_ITEM
));
141 /* find the property handler */
142 Status
= FindPropertyHandler(&Irp
->IoStatus
, PropertySet
, PropertySetsCount
, Property
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, Irp
->UserBuffer
, &PropertyHandler
);
144 if (NT_SUCCESS(Status
) && PropertyHandler
)
146 /* call property handler */
147 Status
= PropertyHandler(Irp
, Property
, Irp
->UserBuffer
);
149 if (Status
== STATUS_BUFFER_TOO_SMALL
)
151 /* output buffer is too small */
154 /* allocate the requested amount */
155 Status
= Allocator(Irp
, Irp
->IoStatus
.Information
, FALSE
);
157 /* check if the block was allocated */
158 if (!NT_SUCCESS(Status
))
161 return STATUS_INSUFFICIENT_RESOURCES
;
164 /* re-call property handler */
165 Status
= PropertyHandler(Irp
, Property
, Irp
->UserBuffer
);
169 else if (IsEqualGUIDAligned(&Property
->Set
, &GUID_NULL
) && Property
->Id
== 0 && Property
->Flags
== KSPROPERTY_TYPE_SETSUPPORT
)
172 Irp
->IoStatus
.Information
= sizeof(GUID
) * PropertySetsCount
;
173 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
) * PropertySetsCount
)
176 return STATUS_BUFFER_OVERFLOW
;
180 Guid
= (LPGUID
)Irp
->UserBuffer
;
182 // copy property guids from property sets
183 for(Index
= 0; Index
< PropertySetsCount
; Index
++)
185 RtlMoveMemory(&Guid
[Index
], PropertySet
[Index
].Set
, sizeof(GUID
));
187 return STATUS_SUCCESS
;
202 IN ULONG PropertySetsCount
,
203 IN
const KSPROPERTY_SET
* PropertySet
)
205 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, NULL
, 0);
215 KsPropertyHandlerWithAllocator(
217 IN ULONG PropertySetsCount
,
218 IN PKSPROPERTY_SET PropertySet
,
219 IN PFNKSALLOCATOR Allocator OPTIONAL
,
220 IN ULONG PropertyItemSize OPTIONAL
)
222 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, Allocator
, PropertyItemSize
);
226 FindFastPropertyHandler(
227 IN ULONG FastIoCount
,
228 IN
const KSFASTPROPERTY_ITEM
* FastIoTable
,
229 IN PKSPROPERTY PropertyId
,
230 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
234 /* iterate through all items */
235 for(Index
= 0; Index
< FastIoCount
; Index
++)
237 if (PropertyId
->Id
== FastIoTable
[Index
].PropertyId
)
239 if (PropertyId
->Flags
& KSPROPERTY_TYPE_SET
)
241 if (FastIoTable
[Index
].SetSupported
)
243 *FastPropertyHandler
= FastIoTable
[Index
].SetPropertyHandler
;
244 return STATUS_SUCCESS
;
248 if (PropertyId
->Flags
& KSPROPERTY_TYPE_GET
)
250 if (FastIoTable
[Index
].GetSupported
)
252 *FastPropertyHandler
= FastIoTable
[Index
].GetPropertyHandler
;
253 return STATUS_SUCCESS
;
259 /* no fast property handler found */
260 return STATUS_NOT_FOUND
;
270 KsFastPropertyHandler(
271 IN PFILE_OBJECT FileObject
,
272 IN PKSPROPERTY UNALIGNED Property
,
273 IN ULONG PropertyLength
,
274 IN OUT PVOID UNALIGNED Data
,
276 OUT PIO_STATUS_BLOCK IoStatus
,
277 IN ULONG PropertySetsCount
,
278 IN
const KSPROPERTY_SET
* PropertySet
)
280 KSPROPERTY PropRequest
;
281 KPROCESSOR_MODE Mode
;
282 NTSTATUS Status
= STATUS_SUCCESS
;
284 PFNKSFASTHANDLER FastPropertyHandler
;
286 if (PropertyLength
< sizeof(KSPROPERTY
))
288 /* invalid request */
292 /* get previous mode */
293 Mode
= ExGetPreviousMode();
295 if (Mode
== KernelMode
)
298 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
302 /* need to probe the buffer */
305 ProbeForRead(Property
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
306 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
308 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
310 /* Exception, get the error code */
311 Status
= _SEH2_GetExceptionCode();
314 if (!NT_SUCCESS(Status
))
318 /* are there any property sets provided */
319 if (PropertySetsCount
)
321 /* iterate through all property sets count */
325 /* does the property id match */
326 if (IsEqualGUIDAligned(PropertySet
[Index
].Set
, &PropRequest
.Set
))
328 /* try to find a fast property handler */
329 Status
= FindFastPropertyHandler(PropertySet
[Index
].FastIoCount
, PropertySet
[Index
].FastIoTable
, &PropRequest
, &FastPropertyHandler
);
331 if (NT_SUCCESS(Status
))
333 /* call fast property handler */
334 ASSERT(PropertyLength
== sizeof(KSPROPERTY
)); /* FIXME check if property length is bigger -> copy params */
335 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
336 return FastPropertyHandler(FileObject
, &PropRequest
, sizeof(KSPROPERTY
), Data
, DataLength
, IoStatus
);
339 /* move to next item */
341 }while(Index
< PropertySetsCount
);
352 KsDispatchSpecificProperty(
354 IN PFNKSHANDLER Handler
)
356 PIO_STACK_LOCATION IoStack
;
358 /* get current irp stack location */
359 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
361 return Handler(Irp
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, Irp
->UserBuffer
);