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
,
24 OUT PKSPROPERTY_ITEM
*PropertyItem
)
26 ULONG Index
, ItemIndex
;
28 for(Index
= 0; Index
< PropertySetCount
; Index
++)
30 ASSERT(PropertySet
[Index
].Set
);
32 if (IsEqualGUIDAligned(&Property
->Set
, PropertySet
[Index
].Set
))
34 for(ItemIndex
= 0; ItemIndex
< PropertySet
[Index
].PropertiesCount
; ItemIndex
++)
36 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].PropertyId
== Property
->Id
)
38 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
> InputBufferLength
)
40 /* too small input buffer */
41 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinProperty
;
42 return STATUS_INVALID_PARAMETER
;
45 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
> OutputBufferLength
)
47 /* too small output buffer */
48 IoStatus
->Information
= PropertySet
[Index
].PropertyItem
[ItemIndex
].MinData
;
49 return STATUS_MORE_ENTRIES
;
52 /* store property set */
53 *Set
= (PKSPROPERTY_SET
)&PropertySet
[Index
];
54 *PropertyItem
= (PKSPROPERTY_ITEM
)&PropertySet
[Index
].PropertyItem
[ItemIndex
];
56 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
58 /* store property handler */
59 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SetPropertyHandler
;
60 return STATUS_SUCCESS
;
63 if (Property
->Flags
& KSPROPERTY_TYPE_GET
)
65 /* store property handler */
66 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].GetPropertyHandler
;
67 return STATUS_SUCCESS
;
71 if (Property
->Flags
& KSPROPERTY_TYPE_BASICSUPPORT
)
74 PKSPROPERTY_DESCRIPTION Description
;
76 if (sizeof(ULONG
) > OutputBufferLength
)
78 /* too small buffer */
79 return STATUS_INVALID_PARAMETER
;
82 /* get output buffer */
83 Flags
= (PULONG
)OutputBuffer
;
88 IoStatus
->Information
= sizeof(ULONG
);
90 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SupportHandler
)
92 /* use support handler from driver */
93 *PropertyHandler
= PropertySet
[Index
].PropertyItem
[ItemIndex
].SupportHandler
;
94 return STATUS_SUCCESS
;
97 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].GetSupported
)
98 *Flags
|= KSPROPERTY_TYPE_GET
;
100 if (PropertySet
[Index
].PropertyItem
[ItemIndex
].SetSupported
)
101 *Flags
|= KSPROPERTY_TYPE_SET
;
103 if (OutputBufferLength
>= sizeof(KSPROPERTY_DESCRIPTION
))
105 /* get output buffer */
106 Description
= (PKSPROPERTY_DESCRIPTION
)OutputBuffer
;
109 Description
->DescriptionSize
= sizeof(KSPROPERTY_DESCRIPTION
);
110 Description
->PropTypeSet
.Set
= KSPROPTYPESETID_General
;
111 Description
->PropTypeSet
.Id
= 0;
112 Description
->PropTypeSet
.Flags
= 0;
113 Description
->MembersListCount
= 0;
114 Description
->Reserved
= 0;
116 IoStatus
->Information
= sizeof(KSPROPERTY_DESCRIPTION
);
118 return STATUS_SUCCESS
;
124 return STATUS_NOT_FOUND
;
131 IN ULONG PropertySetsCount
,
132 IN
const KSPROPERTY_SET
* PropertySet
,
133 IN PFNKSALLOCATOR Allocator OPTIONAL
,
134 IN ULONG PropertyItemSize OPTIONAL
)
136 PKSPROPERTY Property
;
137 PKSPROPERTY_ITEM PropertyItem
;
139 PIO_STACK_LOCATION IoStack
;
141 PFNKSHANDLER PropertyHandler
= NULL
;
142 ULONG Index
, InputBufferLength
, OutputBufferLength
, TotalSize
;
144 //UNICODE_STRING GuidBuffer;
146 /* get current irp stack */
147 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
150 OutputBufferLength
= (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
+ 7) & ~7;
151 InputBufferLength
= IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
;
153 /* check for invalid buffer length size */
154 if (OutputBufferLength
< IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
156 /* unsigned overflow */
157 return STATUS_INVALID_BUFFER_SIZE
;
160 /* check for integer overflow */
161 if (InputBufferLength
+ OutputBufferLength
< IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
164 return STATUS_INVALID_BUFFER_SIZE
;
167 /* check if inputbuffer at least holds KSPROPERTY item */
168 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSPROPERTY
))
170 /* invalid parameter */
171 return STATUS_INVALID_BUFFER_SIZE
;
175 TotalSize
= InputBufferLength
+ OutputBufferLength
;
177 /* get input property request */
178 Property
= (PKSPROPERTY
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
180 /* have the parameters been checked yet */
181 if (!Irp
->AssociatedIrp
.SystemBuffer
)
183 /* is it from user mode */
184 if (Irp
->RequestorMode
== UserMode
)
186 /* probe user buffer */
187 ProbeForRead(IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, InputBufferLength
, 1);
190 /* do we have an allocator */
191 if ((Allocator
) && (Property
->Flags
& (KSPROPERTY_TYPE_GET
| KSPROPERTY_TYPE_SET
)))
194 Status
= Allocator(Irp
, TotalSize
, (Property
->Flags
& KSPROPERTY_TYPE_GET
));
196 /* check for success */
197 if (!NT_SUCCESS(Status
))
202 /* allocate buffer */
203 Irp
->AssociatedIrp
.SystemBuffer
= AllocateItem(NonPagedPool
, TotalSize
);
206 ASSERT(Irp
->AssociatedIrp
.SystemBuffer
!= NULL
);
208 /* mark irp as buffered so that changes the stream headers are propagated back */
209 Irp
->Flags
|= IRP_DEALLOCATE_BUFFER
| IRP_BUFFERED_IO
;
212 /* now copy the buffer */
213 RtlCopyMemory((PVOID
)((ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
+ OutputBufferLength
), IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, InputBufferLength
);
215 /* use new property buffer */
216 Property
= (PKSPROPERTY
)((ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
+ OutputBufferLength
);
218 /* is it a set operation */
219 if (Property
->Flags
& KSPROPERTY_TYPE_SET
)
221 /* for set operations, the output parameters need to be copied */
222 if (Irp
->RequestorMode
== UserMode
)
224 /* probe user parameter */
225 ProbeForRead(Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, 1);
228 /* copy parameters, needs un-aligned parameter length */
229 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
);
232 /* is there an output buffer */
233 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
)
235 /* is it from user mode */
236 if (Irp
->RequestorMode
== UserMode
)
238 /* probe buffer for writing */
239 ProbeForWrite(Irp
->UserBuffer
, IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
, 1);
242 if (!Allocator
|| !(Property
->Flags
& KSPROPERTY_TYPE_GET
))
244 /* it is an input operation */
245 Irp
->Flags
|= IRP_INPUT_OPERATION
;
251 /* use new property buffer */
252 Property
= (PKSPROPERTY
)((ULONG_PTR
)Irp
->AssociatedIrp
.SystemBuffer
+ OutputBufferLength
);
255 //RtlStringFromGUID(&Property->Set, &GuidBuffer);
257 //DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
258 //DPRINT("PropertyId %lu PropertyFlags %x Guid %S\n", Property->Id, Property->Flags, GuidBuffer.Buffer);
260 //RtlFreeUnicodeString(&GuidBuffer);
263 ASSERT(PropertyItemSize
== 0 || PropertyItemSize
== sizeof(KSPROPERTY_ITEM
));
265 /* find the property handler */
266 Status
= FindPropertyHandler(&Irp
->IoStatus
, PropertySet
, PropertySetsCount
, Property
, InputBufferLength
, OutputBufferLength
, Irp
->AssociatedIrp
.SystemBuffer
, &PropertyHandler
, &Set
, &PropertyItem
);
268 if (NT_SUCCESS(Status
) && PropertyHandler
)
271 KSPROPERTY_SET_IRP_STORAGE(Irp
) = Set
;
273 /* are any custom property item sizes used */
274 if (PropertyItemSize
)
276 /* store custom property item */
277 KSPROPERTY_ITEM_IRP_STORAGE(Irp
) = PropertyItem
;
280 /* call property handler */
281 Status
= PropertyHandler(Irp
, Property
, (OutputBufferLength
> 0 ? Irp
->AssociatedIrp
.SystemBuffer
: NULL
));
283 if (Status
== STATUS_BUFFER_TOO_SMALL
)
285 /* output buffer is too small */
288 /* allocate the requested amount */
289 Status
= Allocator(Irp
, Irp
->IoStatus
.Information
, FALSE
);
291 /* check if the block was allocated */
292 if (!NT_SUCCESS(Status
))
295 return STATUS_INSUFFICIENT_RESOURCES
;
298 /* re-call property handler */
299 Status
= PropertyHandler(Irp
, Property
, Irp
->AssociatedIrp
.SystemBuffer
);
303 else if (IsEqualGUIDAligned(&Property
->Set
, &GUID_NULL
) && Property
->Id
== 0 && (Property
->Flags
& KSPROPERTY_TYPE_SETSUPPORT
) == KSPROPERTY_TYPE_SETSUPPORT
)
306 Irp
->IoStatus
.Information
= sizeof(GUID
) * PropertySetsCount
;
307 if (IoStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(GUID
) * PropertySetsCount
)
310 return STATUS_MORE_ENTRIES
;
314 Guid
= (LPGUID
)Irp
->AssociatedIrp
.SystemBuffer
;
316 // copy property guids from property sets
317 for(Index
= 0; Index
< PropertySetsCount
; Index
++)
319 RtlMoveMemory(&Guid
[Index
], PropertySet
[Index
].Set
, sizeof(GUID
));
321 Status
= STATUS_SUCCESS
;
336 IN ULONG PropertySetsCount
,
337 IN
const KSPROPERTY_SET
* PropertySet
)
339 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, NULL
, 0);
349 KsPropertyHandlerWithAllocator(
351 IN ULONG PropertySetsCount
,
352 IN PKSPROPERTY_SET PropertySet
,
353 IN PFNKSALLOCATOR Allocator OPTIONAL
,
354 IN ULONG PropertyItemSize OPTIONAL
)
356 return KspPropertyHandler(Irp
, PropertySetsCount
, PropertySet
, Allocator
, PropertyItemSize
);
360 FindFastPropertyHandler(
361 IN ULONG FastIoCount
,
362 IN
const KSFASTPROPERTY_ITEM
* FastIoTable
,
363 IN PKSPROPERTY PropertyId
,
364 OUT PFNKSFASTHANDLER
* FastPropertyHandler
)
368 /* iterate through all items */
369 for(Index
= 0; Index
< FastIoCount
; Index
++)
371 if (PropertyId
->Id
== FastIoTable
[Index
].PropertyId
)
373 if (PropertyId
->Flags
& KSPROPERTY_TYPE_SET
)
375 if (FastIoTable
[Index
].SetSupported
)
377 *FastPropertyHandler
= FastIoTable
[Index
].SetPropertyHandler
;
378 return STATUS_SUCCESS
;
382 if (PropertyId
->Flags
& KSPROPERTY_TYPE_GET
)
384 if (FastIoTable
[Index
].GetSupported
)
386 *FastPropertyHandler
= FastIoTable
[Index
].GetPropertyHandler
;
387 return STATUS_SUCCESS
;
393 /* no fast property handler found */
394 return STATUS_NOT_FOUND
;
404 KsFastPropertyHandler(
405 IN PFILE_OBJECT FileObject
,
406 IN PKSPROPERTY UNALIGNED Property
,
407 IN ULONG PropertyLength
,
408 IN OUT PVOID UNALIGNED Data
,
410 OUT PIO_STATUS_BLOCK IoStatus
,
411 IN ULONG PropertySetsCount
,
412 IN
const KSPROPERTY_SET
* PropertySet
)
414 KSPROPERTY PropRequest
;
415 KPROCESSOR_MODE Mode
;
416 NTSTATUS Status
= STATUS_SUCCESS
;
418 PFNKSFASTHANDLER FastPropertyHandler
;
420 if (PropertyLength
< sizeof(KSPROPERTY
))
422 /* invalid request */
426 /* get previous mode */
427 Mode
= ExGetPreviousMode();
429 if (Mode
== KernelMode
)
432 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
436 /* need to probe the buffer */
439 ProbeForRead(Property
, sizeof(KSPROPERTY
), sizeof(UCHAR
));
440 RtlMoveMemory(&PropRequest
, Property
, sizeof(KSPROPERTY
));
442 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
444 /* Exception, get the error code */
445 Status
= _SEH2_GetExceptionCode();
448 if (!NT_SUCCESS(Status
))
452 /* are there any property sets provided */
453 if (PropertySetsCount
)
455 /* iterate through all property sets count */
459 /* does the property id match */
460 if (IsEqualGUIDAligned(PropertySet
[Index
].Set
, &PropRequest
.Set
))
462 /* try to find a fast property handler */
463 Status
= FindFastPropertyHandler(PropertySet
[Index
].FastIoCount
, PropertySet
[Index
].FastIoTable
, &PropRequest
, &FastPropertyHandler
);
465 if (NT_SUCCESS(Status
))
467 /* call fast property handler */
468 ASSERT(PropertyLength
== sizeof(KSPROPERTY
)); /* FIXME check if property length is bigger -> copy params */
469 ASSERT(Mode
== KernelMode
); /* FIXME need to probe usermode output buffer */
470 return FastPropertyHandler(FileObject
, &PropRequest
, sizeof(KSPROPERTY
), Data
, DataLength
, IoStatus
);
473 /* move to next item */
475 }while(Index
< PropertySetsCount
);
486 KsDispatchSpecificProperty(
488 IN PFNKSHANDLER Handler
)
490 PIO_STACK_LOCATION IoStack
;
492 /* get current irp stack location */
493 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
495 return Handler(Irp
, IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, Irp
->UserBuffer
);