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
;
50 if (Property
->Flags
& KSPROPERTY_TYPE_BASICSUPPORT
)
53 PKSPROPERTY_DESCRIPTION Description
;
55 if (sizeof(ULONG
) > OutputBufferLength
)
57 /* too small buffer */
58 return STATUS_INVALID_PARAMETER
;
61 /* get output buffer */
62 Flags
= (PULONG
)OutputBuffer
;
67 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].GetSupported
)
68 *Flags
|= KSPROPERTY_TYPE_GET
;
70 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SetSupported
)
71 *Flags
|= KSPROPERTY_TYPE_SET
;
73 IoStatus
->Information
= sizeof(ULONG
);
75 if (OutputBufferLength
>= sizeof(KSPROPERTY_DESCRIPTION
))
77 /* get output buffer */
78 Description
= (PKSPROPERTY_DESCRIPTION
)OutputBuffer
;
81 Description
->DescriptionSize
= sizeof(KSPROPERTY_DESCRIPTION
);
82 Description
->PropTypeSet
.Set
= KSPROPTYPESETID_General
;
83 Description
->PropTypeSet
.Id
= 0;
84 Description
->PropTypeSet
.Flags
= 0;
85 Description
->MembersListCount
= 0;
86 Description
->Reserved
= 0;
88 IoStatus
->Information
= sizeof(KSPROPERTY_DESCRIPTION
);
90 return STATUS_SUCCESS
;
92 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
93 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SetPropertyHandler
;
95 if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
96 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].GetPropertyHandler
;
98 *Set
= (PKSPROPERTY_SET
)&PropertySet
[Index
];
99 return STATUS_SUCCESS
;
104 return STATUS_NOT_FOUND
;
111 IN ULONG PropertySetsCount
,
112 IN
const KSPROPERTY_SET
* PropertySet
,
113 IN PFNKSALLOCATOR Allocator OPTIONAL
,
114 IN ULONG PropertyItemSize OPTIONAL
)
116 PKSPROPERTY Property
;
118 PIO_STACK_LOCATION IoStack
;
120 PFNKSHANDLER PropertyHandler
= NULL
;
124 /* get current irp stack */
125 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
127 /* check if inputbuffer at least holds KSPROPERTY item */
128 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
130 /* invalid parameter */
131 Irp
->IoStatus
.Information
= sizeof(KSPROPERTY
);
132 return STATUS_INVALID_BUFFER_SIZE
;
135 /* FIXME probe the input / output buffer if from user mode */
137 /* get input property request */
138 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
140 // DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
143 ASSERT(PropertyItemSize
== 0 || PropertyItemSize
== sizeof(KSPROPERTY_ITEM
));
145 /* find the property handler */
146 Status
= FindPropertyHandler(&Irp
->IoStatus
, PropertySet
, PropertySetsCount
, Property
, IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, Irp
->UserBuffer
, &PropertyHandler
, &Set
);
148 if (NT_SUCCESS(Status
) && PropertyHandler
)
150 /* call property handler */
151 KSPROPERTY_SET_IRP_STORAGE(Irp
) = Set
;
152 Status
= PropertyHandler(Irp
, Property
, Irp
->UserBuffer
);
154 if (Status
== STATUS_BUFFER_TOO_SMALL
)
156 /* output buffer is too small */
159 /* allocate the requested amount */
160 Status
= Allocator(Irp
, Irp
->IoStatus
.Information
, FALSE
);
162 /* check if the block was allocated */
163 if (!NT_SUCCESS(Status
))
166 return STATUS_INSUFFICIENT_RESOURCES
;
169 /* re-call property handler */
170 Status
= PropertyHandler(Irp
, Property
, Irp
->UserBuffer
);
174 else if (IsEqualGUIDAligned(&Property
->Set
, &GUID_NULL
) && Property
->Id
== 0 && Property
->Flags
== KSPROPERTY_TYPE_SETSUPPORT
)
177 Irp
->IoStatus
.Information
= sizeof(GUID
) * PropertySetsCount
;
178 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
) * PropertySetsCount
)
181 return STATUS_MORE_ENTRIES
;
185 Guid
= (LPGUID
)Irp
->UserBuffer
;
187 // copy property guids from property sets
188 for(Index
= 0; Index
< PropertySetsCount
; Index
++)
190 RtlMoveMemory(&Guid
[Index
], PropertySet
[Index
].Set
, sizeof(GUID
));
192 return STATUS_SUCCESS
;
207 IN ULONG PropertySetsCount
,
208 IN
const KSPROPERTY_SET
* PropertySet
)
210 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, NULL
, 0);
220 KsPropertyHandlerWithAllocator(
222 IN ULONG PropertySetsCount
,
223 IN PKSPROPERTY_SET PropertySet
,
224 IN PFNKSALLOCATOR Allocator OPTIONAL
,
225 IN ULONG PropertyItemSize OPTIONAL
)
227 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, Allocator
, PropertyItemSize
);
231 FindFastPropertyHandler(
232 IN ULONG FastIoCount
,
233 IN
const KSFASTPROPERTY_ITEM
* FastIoTable
,
234 IN PKSPROPERTY PropertyId
,
235 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
239 /* iterate through all items */
240 for(Index
= 0; Index
< FastIoCount
; Index
++)
242 if (PropertyId
->Id
== FastIoTable
[Index
].PropertyId
)
244 if (PropertyId
->Flags
& KSPROPERTY_TYPE_SET
)
246 if (FastIoTable
[Index
].SetSupported
)
248 *FastPropertyHandler
= FastIoTable
[Index
].SetPropertyHandler
;
249 return STATUS_SUCCESS
;
253 if (PropertyId
->Flags
& KSPROPERTY_TYPE_GET
)
255 if (FastIoTable
[Index
].GetSupported
)
257 *FastPropertyHandler
= FastIoTable
[Index
].GetPropertyHandler
;
258 return STATUS_SUCCESS
;
264 /* no fast property handler found */
265 return STATUS_NOT_FOUND
;
275 KsFastPropertyHandler(
276 IN PFILE_OBJECT FileObject
,
277 IN PKSPROPERTY UNALIGNED Property
,
278 IN ULONG PropertyLength
,
279 IN OUT PVOID UNALIGNED Data
,
281 OUT PIO_STATUS_BLOCK IoStatus
,
282 IN ULONG PropertySetsCount
,
283 IN
const KSPROPERTY_SET
* PropertySet
)
285 KSPROPERTY PropRequest
;
286 KPROCESSOR_MODE Mode
;
287 NTSTATUS Status
= STATUS_SUCCESS
;
289 PFNKSFASTHANDLER FastPropertyHandler
;
291 if (PropertyLength
< sizeof(KSPROPERTY
))
293 /* invalid request */
297 /* get previous mode */
298 Mode
= ExGetPreviousMode();
300 if (Mode
== KernelMode
)
303 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
307 /* need to probe the buffer */
310 ProbeForRead(Property
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
311 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
313 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
315 /* Exception, get the error code */
316 Status
= _SEH2_GetExceptionCode();
319 if (!NT_SUCCESS(Status
))
323 /* are there any property sets provided */
324 if (PropertySetsCount
)
326 /* iterate through all property sets count */
330 /* does the property id match */
331 if (IsEqualGUIDAligned(PropertySet
[Index
].Set
, &PropRequest
.Set
))
333 /* try to find a fast property handler */
334 Status
= FindFastPropertyHandler(PropertySet
[Index
].FastIoCount
, PropertySet
[Index
].FastIoTable
, &PropRequest
, &FastPropertyHandler
);
336 if (NT_SUCCESS(Status
))
338 /* call fast property handler */
339 ASSERT(PropertyLength
== sizeof(KSPROPERTY
)); /* FIXME check if property length is bigger -> copy params */
340 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
341 return FastPropertyHandler(FileObject
, &PropRequest
, sizeof(KSPROPERTY
), Data
, DataLength
, IoStatus
);
344 /* move to next item */
346 }while(Index
< PropertySetsCount
);
357 KsDispatchSpecificProperty(
359 IN PFNKSHANDLER Handler
)
361 PIO_STACK_LOCATION IoStack
;
363 /* get current irp stack location */
364 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
366 return Handler(Irp
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, Irp
->UserBuffer
);