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 PKSPROPERTY_DESCRIPTION Description
;
36 for(Index
= 0; Index
< PropertySetCount
; Index
++)
38 ASSERT(PropertySet
[Index
].Set
);
40 if (IsEqualGUIDAligned(&Property
->Set
, PropertySet
[Index
].Set
))
42 for(ItemIndex
= 0; ItemIndex
< PropertySet
[Index
].PropertiesCount
; ItemIndex
++)
45 /* store property set */
46 *Set
= (PKSPROPERTY_SET
)&PropertySet
[Index
];
47 *PropertyItem
= (PKSPROPERTY_ITEM
)&PropertySet
[Index
].PropertyItem
[ItemIndex
];
50 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].PropertyId
== Property
->Id
)
52 if (Property
->Flags
& KSPROPERTY_TYPE_BASICSUPPORT
)
54 if (sizeof(ULONG
) > OutputBufferLength
)
56 /* too small buffer */
57 return STATUS_INVALID_PARAMETER
;
60 /* get output buffer */
61 Flags
= (PULONG
)OutputBuffer
;
66 IoStatus
->Information
= sizeof(ULONG
);
68 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SupportHandler
)
70 /* use support handler from driver */
71 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SupportHandler
;
72 return STATUS_SUCCESS
;
75 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].GetSupported
)
76 *Flags
|= KSPROPERTY_TYPE_GET
;
78 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SetSupported
)
79 *Flags
|= KSPROPERTY_TYPE_SET
;
81 if (OutputBufferLength
>= sizeof(KSPROPERTY_DESCRIPTION
))
83 /* get output buffer */
84 Description
= (PKSPROPERTY_DESCRIPTION
)OutputBuffer
;
87 Description
->DescriptionSize
= sizeof(KSPROPERTY_DESCRIPTION
);
88 Description
->PropTypeSet
.Set
= KSPROPTYPESETID_General
;
89 Description
->PropTypeSet
.Id
= 0;
90 Description
->PropTypeSet
.Flags
= 0;
91 Description
->MembersListCount
= 0;
92 Description
->Reserved
= 0;
94 IoStatus
->Information
= sizeof(KSPROPERTY_DESCRIPTION
);
96 return STATUS_SUCCESS
;
99 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
> InputBufferLength
)
101 /* too small input buffer */
102 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
;
103 return STATUS_INVALID_PARAMETER
;
106 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
> OutputBufferLength
)
108 /* too small output buffer */
109 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
;
110 return STATUS_MORE_ENTRIES
;
114 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
116 /* store property handler */
117 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SetPropertyHandler
;
118 return STATUS_SUCCESS
;
121 if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
123 /* store property handler */
124 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].GetPropertyHandler
;
125 return STATUS_SUCCESS
;
133 return STATUS_NOT_FOUND
;
140 IN ULONG PropertySetsCount
,
141 IN
const KSPROPERTY_SET
* PropertySet
,
142 IN PFNKSALLOCATOR Allocator OPTIONAL
,
143 IN ULONG PropertyItemSize OPTIONAL
)
145 PKSPROPERTY Property
;
146 PKSPROPERTY_ITEM PropertyItem
;
148 PIO_STACK_LOCATION IoStack
;
150 PFNKSHANDLER PropertyHandler
= NULL
;
151 ULONG Index
, InputBufferLength
, OutputBufferLength
, TotalSize
;
153 //UNICODE_STRING GuidBuffer;
155 /* get current irp stack */
156 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
159 OutputBufferLength
= (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
+ 7) & ~7;
160 InputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
162 /* check for invalid buffer length size */
163 if (OutputBufferLength
< IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
165 /* unsigned overflow */
166 return STATUS_INVALID_BUFFER_SIZE
;
169 /* check for integer overflow */
170 if (InputBufferLength
+ OutputBufferLength
< IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
173 return STATUS_INVALID_BUFFER_SIZE
;
176 /* check if inputbuffer at least holds KSPROPERTY item */
177 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
179 /* invalid parameter */
180 return STATUS_INVALID_BUFFER_SIZE
;
184 TotalSize
= InputBufferLength
+ OutputBufferLength
;
186 /* get input property request */
187 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
189 /* have the parameters been checked yet */
190 if (!Irp
->AssociatedIrp
.SystemBuffer
)
192 /* is it from user mode */
193 if (Irp
->RequestorMode
== UserMode
)
195 /* probe user buffer */
196 ProbeForRead(IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, InputBufferLength
, 1);
199 /* do we have an allocator */
200 if ((Allocator
) && (Property
->Flags
& (KSPROPERTY_TYPE_GET
| KSPROPERTY_TYPE_SET
)))
203 Status
= Allocator(Irp
, TotalSize
, (Property
->Flags
& KSPROPERTY_TYPE_GET
));
205 /* check for success */
206 if (!NT_SUCCESS(Status
))
211 /* allocate buffer */
212 Irp
->AssociatedIrp
.SystemBuffer
= AllocateItem(NonPagedPool
, TotalSize
);
215 ASSERT(Irp
->AssociatedIrp
.SystemBuffer
!= NULL
);
217 /* mark irp as buffered so that changes the stream headers are propagated back */
218 Irp
->Flags
|= IRP_DEALLOCATE_BUFFER
| IRP_BUFFERED_IO
;
221 /* now copy the buffer */
222 RtlCopyMemory((PVOID
)((ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
+ OutputBufferLength
), IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, InputBufferLength
);
224 /* use new property buffer */
225 Property
= (PKSPROPERTY
)((ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
+ OutputBufferLength
);
227 /* is it a set operation */
228 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
230 /* for set operations, the output parameters need to be copied */
231 if (Irp
->RequestorMode
== UserMode
)
233 /* probe user parameter */
234 ProbeForRead(Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, 1);
237 /* copy parameters, needs un-aligned parameter length */
238 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
241 /* is there an output buffer */
242 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
244 /* is it from user mode */
245 if (Irp
->RequestorMode
== UserMode
)
247 /* probe buffer for writing */
248 ProbeForWrite(Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, 1);
251 if (!Allocator
|| !(Property
->Flags
& KSPROPERTY_TYPE_GET
))
253 /* it is an input operation */
254 Irp
->Flags
|= IRP_INPUT_OPERATION
;
260 /* use new property buffer */
261 Property
= (PKSPROPERTY
)((ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
+ OutputBufferLength
);
264 //RtlStringFromGUID(&Property->Set, &GuidBuffer);
266 //DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
267 //DPRINT("PropertyId %lu PropertyFlags %x Guid %S\n", Property->Id, Property->Flags, GuidBuffer.Buffer);
269 //RtlFreeUnicodeString(&GuidBuffer);
272 ASSERT(PropertyItemSize
== 0 || PropertyItemSize
== sizeof(KSPROPERTY_ITEM
));
274 /* find the property handler */
275 Status
= FindPropertyHandler(&Irp
->IoStatus
, PropertySet
, PropertySetsCount
, Property
, InputBufferLength
, OutputBufferLength
, Irp
->AssociatedIrp
.SystemBuffer
, &PropertyHandler
, &Set
, &PropertyItem
);
277 if (NT_SUCCESS(Status
) && PropertyHandler
)
280 KSPROPERTY_SET_IRP_STORAGE(Irp
) = Set
;
282 /* are any custom property item sizes used */
283 if (PropertyItemSize
)
285 /* store custom property item */
286 KSPROPERTY_ITEM_IRP_STORAGE(Irp
) = PropertyItem
;
291 /* call property handler */
292 Status
= PropertyHandler(Irp
, Property
, (OutputBufferLength
> 0 ? Irp
->AssociatedIrp
.SystemBuffer
: NULL
));
294 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
296 _SEH2_YIELD(return _SEH2_GetExceptionCode());
300 if (Status
== STATUS_BUFFER_TOO_SMALL
)
302 /* output buffer is too small */
305 /* allocate the requested amount */
306 Status
= Allocator(Irp
, (ULONG
)Irp
->IoStatus
.Information
, FALSE
);
308 /* check if the block was allocated */
309 if (!NT_SUCCESS(Status
))
312 return STATUS_INSUFFICIENT_RESOURCES
;
316 /* re-call property handler */
317 Status
= PropertyHandler(Irp
, Property
, Irp
->AssociatedIrp
.SystemBuffer
);
319 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
321 Status
= _SEH2_GetExceptionCode();
327 else if (IsEqualGUIDAligned(&Property
->Set
, &GUID_NULL
) && Property
->Id
== 0 && (Property
->Flags
& KSPROPERTY_TYPE_SETSUPPORT
) == KSPROPERTY_TYPE_SETSUPPORT
)
330 Irp
->IoStatus
.Information
= sizeof(GUID
) * PropertySetsCount
;
331 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
) * PropertySetsCount
)
334 return STATUS_MORE_ENTRIES
;
338 Guid
= (LPGUID
)Irp
->AssociatedIrp
.SystemBuffer
;
340 // copy property guids from property sets
341 for(Index
= 0; Index
< PropertySetsCount
; Index
++)
343 RtlMoveMemory(&Guid
[Index
], PropertySet
[Index
].Set
, sizeof(GUID
));
345 Status
= STATUS_SUCCESS
;
360 IN ULONG PropertySetsCount
,
361 IN
const KSPROPERTY_SET
* PropertySet
)
363 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, NULL
, 0);
370 _IRQL_requires_max_(PASSIVE_LEVEL
)
374 KsPropertyHandlerWithAllocator(
376 _In_ ULONG PropertySetsCount
,
377 _In_reads_(PropertySetsCount
) const KSPROPERTY_SET
* PropertySet
,
378 _In_opt_ PFNKSALLOCATOR Allocator
,
379 _In_opt_ ULONG PropertyItemSize
)
381 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, Allocator
, PropertyItemSize
);
385 FindFastPropertyHandler(
386 IN ULONG FastIoCount
,
387 IN
const KSFASTPROPERTY_ITEM
* FastIoTable
,
388 IN PKSPROPERTY PropertyId
,
389 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
393 /* iterate through all items */
394 for(Index
= 0; Index
< FastIoCount
; Index
++)
396 if (PropertyId
->Id
== FastIoTable
[Index
].PropertyId
)
398 if (PropertyId
->Flags
& KSPROPERTY_TYPE_SET
)
400 if (FastIoTable
[Index
].SetSupported
)
402 *FastPropertyHandler
= FastIoTable
[Index
].SetPropertyHandler
;
403 return STATUS_SUCCESS
;
407 if (PropertyId
->Flags
& KSPROPERTY_TYPE_GET
)
409 if (FastIoTable
[Index
].GetSupported
)
411 *FastPropertyHandler
= FastIoTable
[Index
].GetPropertyHandler
;
412 return STATUS_SUCCESS
;
418 /* no fast property handler found */
419 return STATUS_NOT_FOUND
;
429 KsFastPropertyHandler(
430 IN PFILE_OBJECT FileObject
,
431 IN PKSPROPERTY UNALIGNED Property
,
432 IN ULONG PropertyLength
,
433 IN OUT PVOID UNALIGNED Data
,
435 OUT PIO_STATUS_BLOCK IoStatus
,
436 IN ULONG PropertySetsCount
,
437 IN
const KSPROPERTY_SET
* PropertySet
)
439 KSPROPERTY PropRequest
;
440 KPROCESSOR_MODE Mode
;
441 NTSTATUS Status
= STATUS_SUCCESS
;
443 PFNKSFASTHANDLER FastPropertyHandler
;
445 if (PropertyLength
< sizeof(KSPROPERTY
))
447 /* invalid request */
451 /* get previous mode */
452 Mode
= ExGetPreviousMode();
454 if (Mode
== KernelMode
)
457 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
461 /* need to probe the buffer */
464 ProbeForRead(Property
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
465 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
467 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
469 /* Exception, get the error code */
470 Status
= _SEH2_GetExceptionCode();
473 if (!NT_SUCCESS(Status
))
477 /* are there any property sets provided */
478 if (PropertySetsCount
)
480 /* iterate through all property sets count */
484 /* does the property id match */
485 if (IsEqualGUIDAligned(PropertySet
[Index
].Set
, &PropRequest
.Set
))
487 /* try to find a fast property handler */
488 Status
= FindFastPropertyHandler(PropertySet
[Index
].FastIoCount
, PropertySet
[Index
].FastIoTable
, &PropRequest
, &FastPropertyHandler
);
490 if (NT_SUCCESS(Status
))
492 /* call fast property handler */
493 ASSERT(PropertyLength
== sizeof(KSPROPERTY
)); /* FIXME check if property length is bigger -> copy params */
494 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
495 return FastPropertyHandler(FileObject
, &PropRequest
, sizeof(KSPROPERTY
), Data
, DataLength
, IoStatus
);
498 /* move to next item */
500 }while(Index
< PropertySetsCount
);
511 KsDispatchSpecificProperty(
513 IN PFNKSHANDLER Handler
)
515 PIO_STACK_LOCATION IoStack
;
517 /* get current irp stack location */
518 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
520 return Handler(Irp
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, Irp
->UserBuffer
);