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
,
22 OUT PKSPROPERTY_SET
* Set
)
24 ULONG Index
, ItemIndex
;
27 for(Index
= 0; Index
< PropertySetCount
; Index
++)
29 ASSERT(PropertySet
[Index
].Set
);
31 if (IsEqualGUIDAligned(&Property
->Set
, PropertySet
[Index
].Set
))
33 for(ItemIndex
= 0; ItemIndex
< PropertySet
[Index
].PropertiesCount
; ItemIndex
++)
35 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].PropertyId
== Property
->Id
)
37 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
> InputBufferLength
)
39 /* too small input buffer */
40 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
;
41 return STATUS_INVALID_PARAMETER
;
44 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
> OutputBufferLength
)
46 /* too small output buffer */
47 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
;
48 return STATUS_MORE_ENTRIES
;
51 if (Property
->Flags
& KSPROPERTY_TYPE_BASICSUPPORT
)
53 if (sizeof(ULONG
) > OutputBufferLength
)
55 /* too small buffer */
56 return STATUS_INVALID_PARAMETER
;
59 /* get output buffer */
60 Flags
= (PULONG
)OutputBuffer
;
63 *Flags
= KSPROPERTY_TYPE_BASICSUPPORT
;
65 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].GetSupported
)
66 *Flags
|= KSPROPERTY_TYPE_GET
;
68 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SetSupported
)
69 *Flags
|= KSPROPERTY_TYPE_SET
;
71 IoStatus
->Information
= sizeof(ULONG
);
73 if (OutputBufferLength
>= sizeof(KSPROPERTY_DESCRIPTION
))
75 /* get output buffer */
76 Description
= (PKSPROPERTY_DESCRIPTION
)OutputBuffer
;
79 Description
->DescriptionSize
= sizeof(KSPROPERTY_DESCRIPTION
);
80 Description
->PropTypeSet
.Set
= KSPROPTYPESETID_General
;
81 Description
->PropTypeSet
.Id
= 0;
82 Description
->PropTypeSet
.Flags
= 0;
83 Description
->MembersListCount
= 0;
84 Description
->Reserved
= 0;
86 IoStatus
->Information
= sizeof(KSPROPERTY_DESCRIPTION
);
91 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
92 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SetPropertyHandler
;
94 if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
95 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].GetPropertyHandler
;
97 *Set
= (PKSPROPERTY_SET
)&PropertySet
[Index
];
98 return STATUS_SUCCESS
;
103 return STATUS_NOT_FOUND
;
110 IN ULONG PropertySetsCount
,
111 IN
const KSPROPERTY_SET
* PropertySet
,
112 IN PFNKSALLOCATOR Allocator OPTIONAL
,
113 IN ULONG PropertyItemSize OPTIONAL
)
115 PKSPROPERTY Property
;
117 PIO_STACK_LOCATION IoStack
;
119 PFNKSHANDLER PropertyHandler
= NULL
;
123 /* get current irp stack */
124 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
126 /* check if inputbuffer at least holds KSPROPERTY item */
127 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
129 /* invalid parameter */
130 Irp
->IoStatus
.Information
= sizeof(KSPROPERTY
);
131 return STATUS_INVALID_BUFFER_SIZE
;
134 /* FIXME probe the input / output buffer if from user mode */
136 /* get input property request */
137 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
139 DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp
, PropertySetsCount
, PropertySet
, Allocator
, PropertyItemSize
, sizeof(KSPROPERTY_ITEM
));
142 ASSERT(PropertyItemSize
== 0 || PropertyItemSize
== sizeof(KSPROPERTY_ITEM
));
144 /* find the property handler */
145 Status
= FindPropertyHandler(&Irp
->IoStatus
, PropertySet
, PropertySetsCount
, Property
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, Irp
->UserBuffer
, &PropertyHandler
, &Set
);
147 if (NT_SUCCESS(Status
) && PropertyHandler
)
149 /* call property handler */
150 KSPROPERTY_SET_IRP_STORAGE(Irp
) = Set
;
151 Status
= PropertyHandler(Irp
, Property
, Irp
->UserBuffer
);
153 if (Status
== STATUS_BUFFER_TOO_SMALL
)
155 /* output buffer is too small */
158 /* allocate the requested amount */
159 Status
= Allocator(Irp
, Irp
->IoStatus
.Information
, FALSE
);
161 /* check if the block was allocated */
162 if (!NT_SUCCESS(Status
))
165 return STATUS_INSUFFICIENT_RESOURCES
;
168 /* re-call property handler */
169 Status
= PropertyHandler(Irp
, Property
, Irp
->UserBuffer
);
173 else if (IsEqualGUIDAligned(&Property
->Set
, &GUID_NULL
) && Property
->Id
== 0 && Property
->Flags
== KSPROPERTY_TYPE_SETSUPPORT
)
176 Irp
->IoStatus
.Information
= sizeof(GUID
) * PropertySetsCount
;
177 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
) * PropertySetsCount
)
180 return STATUS_BUFFER_OVERFLOW
;
184 Guid
= (LPGUID
)Irp
->UserBuffer
;
186 // copy property guids from property sets
187 for(Index
= 0; Index
< PropertySetsCount
; Index
++)
189 RtlMoveMemory(&Guid
[Index
], PropertySet
[Index
].Set
, sizeof(GUID
));
191 return STATUS_SUCCESS
;
206 IN ULONG PropertySetsCount
,
207 IN
const KSPROPERTY_SET
* PropertySet
)
209 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, NULL
, 0);
219 KsPropertyHandlerWithAllocator(
221 IN ULONG PropertySetsCount
,
222 IN PKSPROPERTY_SET PropertySet
,
223 IN PFNKSALLOCATOR Allocator OPTIONAL
,
224 IN ULONG PropertyItemSize OPTIONAL
)
226 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, Allocator
, PropertyItemSize
);
230 FindFastPropertyHandler(
231 IN ULONG FastIoCount
,
232 IN
const KSFASTPROPERTY_ITEM
* FastIoTable
,
233 IN PKSPROPERTY PropertyId
,
234 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
238 /* iterate through all items */
239 for(Index
= 0; Index
< FastIoCount
; Index
++)
241 if (PropertyId
->Id
== FastIoTable
[Index
].PropertyId
)
243 if (PropertyId
->Flags
& KSPROPERTY_TYPE_SET
)
245 if (FastIoTable
[Index
].SetSupported
)
247 *FastPropertyHandler
= FastIoTable
[Index
].SetPropertyHandler
;
248 return STATUS_SUCCESS
;
252 if (PropertyId
->Flags
& KSPROPERTY_TYPE_GET
)
254 if (FastIoTable
[Index
].GetSupported
)
256 *FastPropertyHandler
= FastIoTable
[Index
].GetPropertyHandler
;
257 return STATUS_SUCCESS
;
263 /* no fast property handler found */
264 return STATUS_NOT_FOUND
;
274 KsFastPropertyHandler(
275 IN PFILE_OBJECT FileObject
,
276 IN PKSPROPERTY UNALIGNED Property
,
277 IN ULONG PropertyLength
,
278 IN OUT PVOID UNALIGNED Data
,
280 OUT PIO_STATUS_BLOCK IoStatus
,
281 IN ULONG PropertySetsCount
,
282 IN
const KSPROPERTY_SET
* PropertySet
)
284 KSPROPERTY PropRequest
;
285 KPROCESSOR_MODE Mode
;
286 NTSTATUS Status
= STATUS_SUCCESS
;
288 PFNKSFASTHANDLER FastPropertyHandler
;
290 if (PropertyLength
< sizeof(KSPROPERTY
))
292 /* invalid request */
296 /* get previous mode */
297 Mode
= ExGetPreviousMode();
299 if (Mode
== KernelMode
)
302 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
306 /* need to probe the buffer */
309 ProbeForRead(Property
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
310 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
312 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
314 /* Exception, get the error code */
315 Status
= _SEH2_GetExceptionCode();
318 if (!NT_SUCCESS(Status
))
322 /* are there any property sets provided */
323 if (PropertySetsCount
)
325 /* iterate through all property sets count */
329 /* does the property id match */
330 if (IsEqualGUIDAligned(PropertySet
[Index
].Set
, &PropRequest
.Set
))
332 /* try to find a fast property handler */
333 Status
= FindFastPropertyHandler(PropertySet
[Index
].FastIoCount
, PropertySet
[Index
].FastIoTable
, &PropRequest
, &FastPropertyHandler
);
335 if (NT_SUCCESS(Status
))
337 /* call fast property handler */
338 ASSERT(PropertyLength
== sizeof(KSPROPERTY
)); /* FIXME check if property length is bigger -> copy params */
339 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
340 return FastPropertyHandler(FileObject
, &PropRequest
, sizeof(KSPROPERTY
), Data
, DataLength
, IoStatus
);
343 /* move to next item */
345 }while(Index
< PropertySetsCount
);
356 KsDispatchSpecificProperty(
358 IN PFNKSHANDLER Handler
)
360 PIO_STACK_LOCATION IoStack
;
362 /* get current irp stack location */
363 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
365 return Handler(Irp
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, Irp
->UserBuffer
);