- Implement KsGetFirstChild, KsGetNextSibling
[reactos.git] / reactos / drivers / ksfilter / ks / property.c
1 /*
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
7 */
8
9 #include "priv.h"
10
11
12 NTSTATUS
13 FindPropertyHandler(
14 IN PIO_STATUS_BLOCK IoStatus,
15 IN const KSPROPERTY_SET* PropertySet,
16 IN ULONG PropertySetCount,
17 IN PKSPROPERTY Property,
18 IN ULONG InputBufferLength,
19 IN ULONG OutputBufferLength,
20 OUT PFNKSHANDLER *PropertyHandler)
21 {
22 ULONG Index, ItemIndex;
23
24 for(Index = 0; Index < PropertySetCount; Index++)
25 {
26 if (IsEqualGUIDAligned(&Property->Set, PropertySet[Index].Set))
27 {
28 for(ItemIndex = 0; ItemIndex < PropertySet[Index].PropertiesCount; ItemIndex++)
29 {
30 if (PropertySet[Index].PropertyItem[ItemIndex].PropertyId == Property->Id)
31 {
32 if (PropertySet[Index].PropertyItem[ItemIndex].MinProperty > InputBufferLength)
33 {
34 /* too small input buffer */
35 IoStatus->Information = PropertySet[Index].PropertyItem[ItemIndex].MinProperty;
36 return STATUS_INVALID_PARAMETER;
37 }
38
39 if (PropertySet[Index].PropertyItem[ItemIndex].MinData > OutputBufferLength)
40 {
41 /* too small output buffer */
42 IoStatus->Information = PropertySet[Index].PropertyItem[ItemIndex].MinData;
43 return STATUS_BUFFER_TOO_SMALL;
44 }
45
46 if (Property->Flags & KSPROPERTY_TYPE_SET)
47 *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
48
49 if (Property->Flags & KSPROPERTY_TYPE_GET)
50 *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
51
52 return STATUS_SUCCESS;
53 }
54 }
55 }
56 }
57 return STATUS_NOT_FOUND;
58 }
59
60
61 NTSTATUS
62 KspPropertyHandler(
63 IN PIRP Irp,
64 IN ULONG PropertySetsCount,
65 IN const KSPROPERTY_SET* PropertySet,
66 IN PFNKSALLOCATOR Allocator OPTIONAL,
67 IN ULONG PropertyItemSize OPTIONAL)
68 {
69 PKSPROPERTY Property;
70 PIO_STACK_LOCATION IoStack;
71 NTSTATUS Status;
72 PFNKSHANDLER PropertyHandler;
73
74 /* get current irp stack */
75 IoStack = IoGetCurrentIrpStackLocation(Irp);
76
77 /* check if inputbuffer at least holds KSPROPERTY item */
78 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
79 {
80 /* invalid parameter */
81 Irp->IoStatus.Information = sizeof(KSPROPERTY);
82 return STATUS_INVALID_BUFFER_SIZE;
83 }
84
85 /* FIXME probe the input / output buffer if from user mode */
86
87
88 /* get input property request */
89 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
90
91 /* sanity check */
92 ASSERT(PropertyItemSize == 0 || PropertyItemSize == sizeof(KSPROPERTY_ITEM));
93 if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Topology))
94 {
95 /* use KsTopologyPropertyHandler for this business */
96 return STATUS_INVALID_PARAMETER;
97 }
98
99 /* find the property handler */
100 Status = FindPropertyHandler(&Irp->IoStatus, PropertySet, PropertySetsCount, Property, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, &PropertyHandler);
101
102 if (NT_SUCCESS(Status))
103 {
104 /* call property handler */
105 Status = PropertyHandler(Irp, Property, Irp->UserBuffer);
106
107 if (Status == STATUS_BUFFER_TOO_SMALL)
108 {
109 /* output buffer is too small */
110 if (Allocator)
111 {
112 /* allocate the requested amount */
113 Status = Allocator(Irp, Irp->IoStatus.Information, FALSE);
114
115 /* check if the block was allocated */
116 if (!NT_SUCCESS(Status))
117 {
118 /* no memory */
119 return STATUS_INSUFFICIENT_RESOURCES;
120 }
121
122 /* re-call property handler */
123 Status = PropertyHandler(Irp, Property, Irp->UserBuffer);
124 }
125 }
126 }
127
128 /* done */
129 return Status;
130 }
131
132 /*
133 @implemented
134 */
135 KSDDKAPI
136 NTSTATUS
137 NTAPI
138 KsPropertyHandler(
139 IN PIRP Irp,
140 IN ULONG PropertySetsCount,
141 IN const KSPROPERTY_SET* PropertySet)
142 {
143 return KspPropertyHandler(Irp, PropertySetsCount, PropertySet, NULL, 0);
144 }
145
146
147 /*
148 @implemented
149 */
150 KSDDKAPI
151 NTSTATUS
152 NTAPI
153 KsPropertyHandlerWithAllocator(
154 IN PIRP Irp,
155 IN ULONG PropertySetsCount,
156 IN PKSPROPERTY_SET PropertySet,
157 IN PFNKSALLOCATOR Allocator OPTIONAL,
158 IN ULONG PropertyItemSize OPTIONAL)
159 {
160 return KspPropertyHandler(Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize);
161 }
162
163 NTSTATUS
164 FindFastPropertyHandler(
165 IN ULONG FastIoCount,
166 IN const KSFASTPROPERTY_ITEM * FastIoTable,
167 IN PKSPROPERTY PropertyId,
168 OUT PFNKSFASTHANDLER * FastPropertyHandler)
169 {
170 ULONG Index;
171
172 /* iterate through all items */
173 for(Index = 0; Index < FastIoCount; Index++)
174 {
175 if (PropertyId->Id == FastIoTable[Index].PropertyId)
176 {
177 if (PropertyId->Flags & KSPROPERTY_TYPE_SET)
178 {
179 if (FastIoTable[Index].SetSupported)
180 {
181 *FastPropertyHandler = FastIoTable[Index].SetPropertyHandler;
182 return STATUS_SUCCESS;
183 }
184 }
185
186 if (PropertyId->Flags & KSPROPERTY_TYPE_GET)
187 {
188 if (FastIoTable[Index].GetSupported)
189 {
190 *FastPropertyHandler = FastIoTable[Index].GetPropertyHandler;
191 return STATUS_SUCCESS;
192 }
193 }
194 }
195
196 }
197 /* no fast property handler found */
198 return STATUS_NOT_FOUND;
199 }
200
201
202 /*
203 @implemented
204 */
205 KSDDKAPI
206 BOOLEAN
207 NTAPI
208 KsFastPropertyHandler(
209 IN PFILE_OBJECT FileObject,
210 IN PKSPROPERTY UNALIGNED Property,
211 IN ULONG PropertyLength,
212 IN OUT PVOID UNALIGNED Data,
213 IN ULONG DataLength,
214 OUT PIO_STATUS_BLOCK IoStatus,
215 IN ULONG PropertySetsCount,
216 IN const KSPROPERTY_SET* PropertySet)
217 {
218 KSPROPERTY PropRequest;
219 KPROCESSOR_MODE Mode;
220 NTSTATUS Status = STATUS_SUCCESS;
221 ULONG Index;
222 PFNKSFASTHANDLER FastPropertyHandler;
223
224 if (PropertyLength < sizeof(KSPROPERTY))
225 {
226 /* invalid request */
227 return FALSE;
228 }
229
230 /* get previous mode */
231 Mode = ExGetPreviousMode();
232
233 if (Mode == KernelMode)
234 {
235 /* just copy it */
236 RtlMoveMemory(&PropRequest, Property, sizeof(KSPROPERTY));
237 }
238 else
239 {
240 /* need to probe the buffer */
241 _SEH2_TRY
242 {
243 ProbeForRead(Property, sizeof(KSPROPERTY), sizeof(UCHAR));
244 RtlMoveMemory(&PropRequest, Property, sizeof(KSPROPERTY));
245 }
246 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
247 {
248 /* Exception, get the error code */
249 Status = _SEH2_GetExceptionCode();
250 }_SEH2_END;
251
252 if (!NT_SUCCESS(Status))
253 return FALSE;
254 }
255
256 /* are there any property sets provided */
257 if (PropertySetsCount)
258 {
259 /* iterate through all property sets count */
260 Index = 0;
261 do
262 {
263 /* does the property id match */
264 if (IsEqualGUIDAligned(PropertySet[Index].Set, &PropRequest.Set))
265 {
266 /* try to find a fast property handler */
267 Status = FindFastPropertyHandler(PropertySet[Index].FastIoCount, PropertySet[Index].FastIoTable, &PropRequest, &FastPropertyHandler);
268
269 if (NT_SUCCESS(Status))
270 {
271 /* call fast property handler */
272 ASSERT(PropertyLength == sizeof(KSPROPERTY)); /* FIXME check if property length is bigger -> copy params */
273 ASSERT(Mode == KernelMode); /* FIXME need to probe usermode output buffer */
274 return FastPropertyHandler(FileObject, &PropRequest, sizeof(KSPROPERTY), Data, DataLength, IoStatus);
275 }
276 }
277 /* move to next item */
278 Index++;
279 }while(Index < PropertySetsCount);
280 }
281 return FALSE;
282 }
283
284 /*
285 @implemented
286 */
287 KSDDKAPI
288 NTSTATUS
289 NTAPI
290 KsDispatchSpecificProperty(
291 IN PIRP Irp,
292 IN PFNKSHANDLER Handler)
293 {
294 PIO_STACK_LOCATION IoStack;
295
296 /* get current irp stack location */
297 IoStack = IoGetCurrentIrpStackLocation(Irp);
298
299 return Handler(Irp, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, Irp->UserBuffer);
300 }
301