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
11 const GUID KSPROPTYPESETID_General
= {0x97E99BA0L
, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
15 IN PIO_STATUS_BLOCK IoStatus
,
16 IN
const KSPROPERTY_SET
* PropertySet
,
17 IN ULONG PropertySetCount
,
18 IN PKSPROPERTY Property
,
19 IN ULONG InputBufferLength
,
20 IN ULONG OutputBufferLength
,
21 OUT PVOID OutputBuffer
,
22 OUT PFNKSHANDLER
*PropertyHandler
,
23 OUT PKSPROPERTY_SET
* Set
)
25 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 /* store property set */
52 *Set
= (PKSPROPERTY_SET
)&PropertySet
[Index
];
54 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
56 /* store property handler */
57 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SetPropertyHandler
;
58 return STATUS_SUCCESS
;
61 if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
63 /* store property handler */
64 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].GetPropertyHandler
;
65 return STATUS_SUCCESS
;
69 if (Property
->Flags
& KSPROPERTY_TYPE_BASICSUPPORT
)
72 PKSPROPERTY_DESCRIPTION Description
;
74 if (sizeof(ULONG
) > OutputBufferLength
)
76 /* too small buffer */
77 return STATUS_INVALID_PARAMETER
;
80 /* get output buffer */
81 Flags
= (PULONG
)OutputBuffer
;
86 IoStatus
->Information
= sizeof(ULONG
);
88 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SupportHandler
)
90 /* use support handler from driver */
91 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SupportHandler
;
92 return STATUS_SUCCESS
;
95 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].GetSupported
)
96 *Flags
|= KSPROPERTY_TYPE_GET
;
98 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SetSupported
)
99 *Flags
|= KSPROPERTY_TYPE_SET
;
101 if (OutputBufferLength
>= sizeof(KSPROPERTY_DESCRIPTION
))
103 /* get output buffer */
104 Description
= (PKSPROPERTY_DESCRIPTION
)OutputBuffer
;
107 Description
->DescriptionSize
= sizeof(KSPROPERTY_DESCRIPTION
);
108 Description
->PropTypeSet
.Set
= KSPROPTYPESETID_General
;
109 Description
->PropTypeSet
.Id
= 0;
110 Description
->PropTypeSet
.Flags
= 0;
111 Description
->MembersListCount
= 0;
112 Description
->Reserved
= 0;
114 IoStatus
->Information
= sizeof(KSPROPERTY_DESCRIPTION
);
116 return STATUS_SUCCESS
;
122 return STATUS_NOT_FOUND
;
129 IN ULONG PropertySetsCount
,
130 IN
const KSPROPERTY_SET
* PropertySet
,
131 IN PFNKSALLOCATOR Allocator OPTIONAL
,
132 IN ULONG PropertyItemSize OPTIONAL
)
134 PKSPROPERTY Property
;
136 PIO_STACK_LOCATION IoStack
;
138 PFNKSHANDLER PropertyHandler
= NULL
;
142 /* get current irp stack */
143 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
145 /* check if inputbuffer at least holds KSPROPERTY item */
146 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
148 /* invalid parameter */
149 Irp
->IoStatus
.Information
= sizeof(KSPROPERTY
);
150 return STATUS_INVALID_BUFFER_SIZE
;
153 /* FIXME probe the input / output buffer if from user mode */
155 /* get input property request */
156 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
158 // DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
161 ASSERT(PropertyItemSize
== 0 || PropertyItemSize
== sizeof(KSPROPERTY_ITEM
));
163 /* find the property handler */
164 Status
= FindPropertyHandler(&Irp
->IoStatus
, PropertySet
, PropertySetsCount
, Property
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, Irp
->UserBuffer
, &PropertyHandler
, &Set
);
166 if (NT_SUCCESS(Status
) && PropertyHandler
)
168 /* call property handler */
169 KSPROPERTY_SET_IRP_STORAGE(Irp
) = Set
;
170 Status
= PropertyHandler(Irp
, Property
, Irp
->UserBuffer
);
172 if (Status
== STATUS_BUFFER_TOO_SMALL
)
174 /* output buffer is too small */
177 /* allocate the requested amount */
178 Status
= Allocator(Irp
, Irp
->IoStatus
.Information
, FALSE
);
180 /* check if the block was allocated */
181 if (!NT_SUCCESS(Status
))
184 return STATUS_INSUFFICIENT_RESOURCES
;
187 /* re-call property handler */
188 Status
= PropertyHandler(Irp
, Property
, Irp
->UserBuffer
);
192 else if (IsEqualGUIDAligned(&Property
->Set
, &GUID_NULL
) && Property
->Id
== 0 && (Property
->Flags
& KSPROPERTY_TYPE_SETSUPPORT
) == KSPROPERTY_TYPE_SETSUPPORT
)
195 Irp
->IoStatus
.Information
= sizeof(GUID
) * PropertySetsCount
;
196 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
) * PropertySetsCount
)
199 return STATUS_MORE_ENTRIES
;
203 Guid
= (LPGUID
)Irp
->UserBuffer
;
205 // copy property guids from property sets
206 for(Index
= 0; Index
< PropertySetsCount
; Index
++)
208 RtlMoveMemory(&Guid
[Index
], PropertySet
[Index
].Set
, sizeof(GUID
));
210 Status
= STATUS_SUCCESS
;
225 IN ULONG PropertySetsCount
,
226 IN
const KSPROPERTY_SET
* PropertySet
)
228 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, NULL
, 0);
238 KsPropertyHandlerWithAllocator(
240 IN ULONG PropertySetsCount
,
241 IN PKSPROPERTY_SET PropertySet
,
242 IN PFNKSALLOCATOR Allocator OPTIONAL
,
243 IN ULONG PropertyItemSize OPTIONAL
)
245 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, Allocator
, PropertyItemSize
);
249 FindFastPropertyHandler(
250 IN ULONG FastIoCount
,
251 IN
const KSFASTPROPERTY_ITEM
* FastIoTable
,
252 IN PKSPROPERTY PropertyId
,
253 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
257 /* iterate through all items */
258 for(Index
= 0; Index
< FastIoCount
; Index
++)
260 if (PropertyId
->Id
== FastIoTable
[Index
].PropertyId
)
262 if (PropertyId
->Flags
& KSPROPERTY_TYPE_SET
)
264 if (FastIoTable
[Index
].SetSupported
)
266 *FastPropertyHandler
= FastIoTable
[Index
].SetPropertyHandler
;
267 return STATUS_SUCCESS
;
271 if (PropertyId
->Flags
& KSPROPERTY_TYPE_GET
)
273 if (FastIoTable
[Index
].GetSupported
)
275 *FastPropertyHandler
= FastIoTable
[Index
].GetPropertyHandler
;
276 return STATUS_SUCCESS
;
282 /* no fast property handler found */
283 return STATUS_NOT_FOUND
;
293 KsFastPropertyHandler(
294 IN PFILE_OBJECT FileObject
,
295 IN PKSPROPERTY UNALIGNED Property
,
296 IN ULONG PropertyLength
,
297 IN OUT PVOID UNALIGNED Data
,
299 OUT PIO_STATUS_BLOCK IoStatus
,
300 IN ULONG PropertySetsCount
,
301 IN
const KSPROPERTY_SET
* PropertySet
)
303 KSPROPERTY PropRequest
;
304 KPROCESSOR_MODE Mode
;
305 NTSTATUS Status
= STATUS_SUCCESS
;
307 PFNKSFASTHANDLER FastPropertyHandler
;
309 if (PropertyLength
< sizeof(KSPROPERTY
))
311 /* invalid request */
315 /* get previous mode */
316 Mode
= ExGetPreviousMode();
318 if (Mode
== KernelMode
)
321 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
325 /* need to probe the buffer */
328 ProbeForRead(Property
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
329 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
331 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
333 /* Exception, get the error code */
334 Status
= _SEH2_GetExceptionCode();
337 if (!NT_SUCCESS(Status
))
341 /* are there any property sets provided */
342 if (PropertySetsCount
)
344 /* iterate through all property sets count */
348 /* does the property id match */
349 if (IsEqualGUIDAligned(PropertySet
[Index
].Set
, &PropRequest
.Set
))
351 /* try to find a fast property handler */
352 Status
= FindFastPropertyHandler(PropertySet
[Index
].FastIoCount
, PropertySet
[Index
].FastIoTable
, &PropRequest
, &FastPropertyHandler
);
354 if (NT_SUCCESS(Status
))
356 /* call fast property handler */
357 ASSERT(PropertyLength
== sizeof(KSPROPERTY
)); /* FIXME check if property length is bigger -> copy params */
358 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
359 return FastPropertyHandler(FileObject
, &PropRequest
, sizeof(KSPROPERTY
), Data
, DataLength
, IoStatus
);
362 /* move to next item */
364 }while(Index
< PropertySetsCount
);
375 KsDispatchSpecificProperty(
377 IN PFNKSHANDLER Handler
)
379 PIO_STACK_LOCATION IoStack
;
381 /* get current irp stack location */
382 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
384 return Handler(Irp
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, Irp
->UserBuffer
);