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 /* SEH support with PSEH */
12 #include <pseh/pseh2.h>
17 const GUID KSPROPTYPESETID_General
= {0x97E99BA0L
, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
21 IN PIO_STATUS_BLOCK IoStatus
,
22 IN
const KSPROPERTY_SET
* PropertySet
,
23 IN ULONG PropertySetCount
,
24 IN PKSPROPERTY Property
,
25 IN ULONG InputBufferLength
,
26 IN ULONG OutputBufferLength
,
27 OUT PVOID OutputBuffer
,
28 OUT PFNKSHANDLER
*PropertyHandler
,
29 OUT PKSPROPERTY_SET
* Set
,
30 OUT PKSPROPERTY_ITEM
*PropertyItem
)
32 ULONG Index
, ItemIndex
;
34 for(Index
= 0; Index
< PropertySetCount
; Index
++)
36 ASSERT(PropertySet
[Index
].Set
);
38 if (IsEqualGUIDAligned(&Property
->Set
, PropertySet
[Index
].Set
))
40 for(ItemIndex
= 0; ItemIndex
< PropertySet
[Index
].PropertiesCount
; ItemIndex
++)
42 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].PropertyId
== Property
->Id
)
44 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
> InputBufferLength
)
46 /* too small input buffer */
47 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
;
48 return STATUS_INVALID_PARAMETER
;
51 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
> OutputBufferLength
)
53 /* too small output buffer */
54 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
;
55 return STATUS_MORE_ENTRIES
;
58 /* store property set */
59 *Set
= (PKSPROPERTY_SET
)&PropertySet
[Index
];
60 *PropertyItem
= (PKSPROPERTY_ITEM
)&PropertySet
[Index
].PropertyItem
[ItemIndex
];
62 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
64 /* store property handler */
65 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SetPropertyHandler
;
66 return STATUS_SUCCESS
;
69 if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
71 /* store property handler */
72 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].GetPropertyHandler
;
73 return STATUS_SUCCESS
;
77 if (Property
->Flags
& KSPROPERTY_TYPE_BASICSUPPORT
)
80 PKSPROPERTY_DESCRIPTION Description
;
82 if (sizeof(ULONG
) > OutputBufferLength
)
84 /* too small buffer */
85 return STATUS_INVALID_PARAMETER
;
88 /* get output buffer */
89 Flags
= (PULONG
)OutputBuffer
;
94 IoStatus
->Information
= sizeof(ULONG
);
96 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SupportHandler
)
98 /* use support handler from driver */
99 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SupportHandler
;
100 return STATUS_SUCCESS
;
103 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].GetSupported
)
104 *Flags
|= KSPROPERTY_TYPE_GET
;
106 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SetSupported
)
107 *Flags
|= KSPROPERTY_TYPE_SET
;
109 if (OutputBufferLength
>= sizeof(KSPROPERTY_DESCRIPTION
))
111 /* get output buffer */
112 Description
= (PKSPROPERTY_DESCRIPTION
)OutputBuffer
;
115 Description
->DescriptionSize
= sizeof(KSPROPERTY_DESCRIPTION
);
116 Description
->PropTypeSet
.Set
= KSPROPTYPESETID_General
;
117 Description
->PropTypeSet
.Id
= 0;
118 Description
->PropTypeSet
.Flags
= 0;
119 Description
->MembersListCount
= 0;
120 Description
->Reserved
= 0;
122 IoStatus
->Information
= sizeof(KSPROPERTY_DESCRIPTION
);
124 return STATUS_SUCCESS
;
130 return STATUS_NOT_FOUND
;
137 IN ULONG PropertySetsCount
,
138 IN
const KSPROPERTY_SET
* PropertySet
,
139 IN PFNKSALLOCATOR Allocator OPTIONAL
,
140 IN ULONG PropertyItemSize OPTIONAL
)
142 PKSPROPERTY Property
;
143 PKSPROPERTY_ITEM PropertyItem
;
145 PIO_STACK_LOCATION IoStack
;
147 PFNKSHANDLER PropertyHandler
= NULL
;
148 ULONG Index
, InputBufferLength
, OutputBufferLength
, TotalSize
;
150 //UNICODE_STRING GuidBuffer;
152 /* get current irp stack */
153 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
156 OutputBufferLength
= (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
+ 7) & ~7;
157 InputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
159 /* check for invalid buffer length size */
160 if (OutputBufferLength
< IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
162 /* unsigned overflow */
163 return STATUS_INVALID_BUFFER_SIZE
;
166 /* check for integer overflow */
167 if (InputBufferLength
+ OutputBufferLength
< IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
170 return STATUS_INVALID_BUFFER_SIZE
;
173 /* check if inputbuffer at least holds KSPROPERTY item */
174 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
176 /* invalid parameter */
177 return STATUS_INVALID_BUFFER_SIZE
;
181 TotalSize
= InputBufferLength
+ OutputBufferLength
;
183 /* get input property request */
184 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
186 /* have the parameters been checked yet */
187 if (!Irp
->AssociatedIrp
.SystemBuffer
)
189 /* is it from user mode */
190 if (Irp
->RequestorMode
== UserMode
)
192 /* probe user buffer */
193 ProbeForRead(IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, InputBufferLength
, 1);
196 /* do we have an allocator */
197 if ((Allocator
) && (Property
->Flags
& (KSPROPERTY_TYPE_GET
| KSPROPERTY_TYPE_SET
)))
200 Status
= Allocator(Irp
, TotalSize
, (Property
->Flags
& KSPROPERTY_TYPE_GET
));
202 /* check for success */
203 if (!NT_SUCCESS(Status
))
208 /* allocate buffer */
209 Irp
->AssociatedIrp
.SystemBuffer
= AllocateItem(NonPagedPool
, TotalSize
);
212 ASSERT(Irp
->AssociatedIrp
.SystemBuffer
!= NULL
);
214 /* mark irp as buffered so that changes the stream headers are propagated back */
215 Irp
->Flags
|= IRP_DEALLOCATE_BUFFER
| IRP_BUFFERED_IO
;
218 /* now copy the buffer */
219 RtlCopyMemory((PVOID
)((ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
+ OutputBufferLength
), IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, InputBufferLength
);
221 /* use new property buffer */
222 Property
= (PKSPROPERTY
)((ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
+ OutputBufferLength
);
224 /* is it a set operation */
225 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
227 /* for set operations, the output parameters need to be copied */
228 if (Irp
->RequestorMode
== UserMode
)
230 /* probe user parameter */
231 ProbeForRead(Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, 1);
234 /* copy parameters, needs un-aligned parameter length */
235 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
238 /* is there an output buffer */
239 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
241 /* is it from user mode */
242 if (Irp
->RequestorMode
== UserMode
)
244 /* probe buffer for writing */
245 ProbeForWrite(Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, 1);
248 if (!Allocator
|| !(Property
->Flags
& KSPROPERTY_TYPE_GET
))
250 /* it is an input operation */
251 Irp
->Flags
|= IRP_INPUT_OPERATION
;
257 /* use new property buffer */
258 Property
= (PKSPROPERTY
)((ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
+ OutputBufferLength
);
261 //RtlStringFromGUID(&Property->Set, &GuidBuffer);
263 //DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
264 //DPRINT("PropertyId %lu PropertyFlags %x Guid %S\n", Property->Id, Property->Flags, GuidBuffer.Buffer);
266 //RtlFreeUnicodeString(&GuidBuffer);
269 ASSERT(PropertyItemSize
== 0 || PropertyItemSize
== sizeof(KSPROPERTY_ITEM
));
271 /* find the property handler */
272 Status
= FindPropertyHandler(&Irp
->IoStatus
, PropertySet
, PropertySetsCount
, Property
, InputBufferLength
, OutputBufferLength
, Irp
->AssociatedIrp
.SystemBuffer
, &PropertyHandler
, &Set
, &PropertyItem
);
274 if (NT_SUCCESS(Status
) && PropertyHandler
)
277 KSPROPERTY_SET_IRP_STORAGE(Irp
) = Set
;
279 /* are any custom property item sizes used */
280 if (PropertyItemSize
)
282 /* store custom property item */
283 KSPROPERTY_ITEM_IRP_STORAGE(Irp
) = PropertyItem
;
288 /* call property handler */
289 Status
= PropertyHandler(Irp
, Property
, (OutputBufferLength
> 0 ? Irp
->AssociatedIrp
.SystemBuffer
: NULL
));
291 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
293 _SEH2_YIELD(return _SEH2_GetExceptionCode());
297 if (Status
== STATUS_BUFFER_TOO_SMALL
)
299 /* output buffer is too small */
302 /* allocate the requested amount */
303 Status
= Allocator(Irp
, (ULONG
)Irp
->IoStatus
.Information
, FALSE
);
305 /* check if the block was allocated */
306 if (!NT_SUCCESS(Status
))
309 return STATUS_INSUFFICIENT_RESOURCES
;
313 /* re-call property handler */
314 Status
= PropertyHandler(Irp
, Property
, Irp
->AssociatedIrp
.SystemBuffer
);
316 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
318 Status
= _SEH2_GetExceptionCode();
324 else if (IsEqualGUIDAligned(&Property
->Set
, &GUID_NULL
) && Property
->Id
== 0 && (Property
->Flags
& KSPROPERTY_TYPE_SETSUPPORT
) == KSPROPERTY_TYPE_SETSUPPORT
)
327 Irp
->IoStatus
.Information
= sizeof(GUID
) * PropertySetsCount
;
328 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
) * PropertySetsCount
)
331 return STATUS_MORE_ENTRIES
;
335 Guid
= (LPGUID
)Irp
->AssociatedIrp
.SystemBuffer
;
337 // copy property guids from property sets
338 for(Index
= 0; Index
< PropertySetsCount
; Index
++)
340 RtlMoveMemory(&Guid
[Index
], PropertySet
[Index
].Set
, sizeof(GUID
));
342 Status
= STATUS_SUCCESS
;
357 IN ULONG PropertySetsCount
,
358 IN
const KSPROPERTY_SET
* PropertySet
)
360 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, NULL
, 0);
367 _IRQL_requires_max_(PASSIVE_LEVEL
)
371 KsPropertyHandlerWithAllocator(
373 _In_ ULONG PropertySetsCount
,
374 _In_reads_(PropertySetsCount
) const KSPROPERTY_SET
* PropertySet
,
375 _In_opt_ PFNKSALLOCATOR Allocator
,
376 _In_opt_ ULONG PropertyItemSize
)
378 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, Allocator
, PropertyItemSize
);
382 FindFastPropertyHandler(
383 IN ULONG FastIoCount
,
384 IN
const KSFASTPROPERTY_ITEM
* FastIoTable
,
385 IN PKSPROPERTY PropertyId
,
386 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
390 /* iterate through all items */
391 for(Index
= 0; Index
< FastIoCount
; Index
++)
393 if (PropertyId
->Id
== FastIoTable
[Index
].PropertyId
)
395 if (PropertyId
->Flags
& KSPROPERTY_TYPE_SET
)
397 if (FastIoTable
[Index
].SetSupported
)
399 *FastPropertyHandler
= FastIoTable
[Index
].SetPropertyHandler
;
400 return STATUS_SUCCESS
;
404 if (PropertyId
->Flags
& KSPROPERTY_TYPE_GET
)
406 if (FastIoTable
[Index
].GetSupported
)
408 *FastPropertyHandler
= FastIoTable
[Index
].GetPropertyHandler
;
409 return STATUS_SUCCESS
;
415 /* no fast property handler found */
416 return STATUS_NOT_FOUND
;
426 KsFastPropertyHandler(
427 IN PFILE_OBJECT FileObject
,
428 IN PKSPROPERTY UNALIGNED Property
,
429 IN ULONG PropertyLength
,
430 IN OUT PVOID UNALIGNED Data
,
432 OUT PIO_STATUS_BLOCK IoStatus
,
433 IN ULONG PropertySetsCount
,
434 IN
const KSPROPERTY_SET
* PropertySet
)
436 KSPROPERTY PropRequest
;
437 KPROCESSOR_MODE Mode
;
438 NTSTATUS Status
= STATUS_SUCCESS
;
440 PFNKSFASTHANDLER FastPropertyHandler
;
442 if (PropertyLength
< sizeof(KSPROPERTY
))
444 /* invalid request */
448 /* get previous mode */
449 Mode
= ExGetPreviousMode();
451 if (Mode
== KernelMode
)
454 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
458 /* need to probe the buffer */
461 ProbeForRead(Property
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
462 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
464 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
466 /* Exception, get the error code */
467 Status
= _SEH2_GetExceptionCode();
470 if (!NT_SUCCESS(Status
))
474 /* are there any property sets provided */
475 if (PropertySetsCount
)
477 /* iterate through all property sets count */
481 /* does the property id match */
482 if (IsEqualGUIDAligned(PropertySet
[Index
].Set
, &PropRequest
.Set
))
484 /* try to find a fast property handler */
485 Status
= FindFastPropertyHandler(PropertySet
[Index
].FastIoCount
, PropertySet
[Index
].FastIoTable
, &PropRequest
, &FastPropertyHandler
);
487 if (NT_SUCCESS(Status
))
489 /* call fast property handler */
490 ASSERT(PropertyLength
== sizeof(KSPROPERTY
)); /* FIXME check if property length is bigger -> copy params */
491 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
492 return FastPropertyHandler(FileObject
, &PropRequest
, sizeof(KSPROPERTY
), Data
, DataLength
, IoStatus
);
495 /* move to next item */
497 }while(Index
< PropertySetsCount
);
508 KsDispatchSpecificProperty(
510 IN PFNKSHANDLER Handler
)
512 PIO_STACK_LOCATION IoStack
;
514 /* get current irp stack location */
515 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
517 return Handler(Irp
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, Irp
->UserBuffer
);