- Store KSPROPERTY_SET in Irp when using KsPropertyHandler
[reactos.git] / reactos / drivers / ksfilter / ks / filterfactory.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/filterfactory.c
5 * PURPOSE: KS IKsFilterFactory interface functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9
10 #include "priv.h"
11
12 typedef struct
13 {
14 KSBASIC_HEADER Header;
15 KSFILTERFACTORY FilterFactory;
16
17 IKsFilterFactoryVtbl *lpVtbl;
18 LONG ref;
19 PKSIDEVICE_HEADER DeviceHeader;
20 PFNKSFILTERFACTORYPOWER SleepCallback;
21 PFNKSFILTERFACTORYPOWER WakeCallback;
22
23 LIST_ENTRY SymbolicLinkList;
24 }IKsFilterFactoryImpl;
25
26 VOID
27 NTAPI
28 IKsFilterFactory_ItemFreeCb(
29 IN PKSOBJECT_CREATE_ITEM CreateItem)
30 {
31 /* callback when create item is freed in the device header */
32 IKsFilterFactory * iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
33
34 iface->lpVtbl->Release(iface);
35 }
36
37 NTSTATUS
38 NTAPI
39 IKsFilterFactory_Create(
40 IN PDEVICE_OBJECT DeviceObject,
41 IN PIRP Irp)
42 {
43 PKSOBJECT_CREATE_ITEM CreateItem;
44 IKsFilterFactory * iface;
45 NTSTATUS Status;
46
47 /* access the create item */
48 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
49 if (!CreateItem)
50 {
51 DPRINT1("IKsFilterFactory_Create no CreateItem\n");
52 return STATUS_UNSUCCESSFUL;
53 }
54
55 /* get filter factory interface */
56 iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
57
58 /* create a filter instance */
59 Status = KspCreateFilter(DeviceObject, Irp, iface);
60
61 DPRINT("KspCreateFilter Status %x\n", Status);
62
63 if (Status != STATUS_PENDING)
64 {
65 Irp->IoStatus.Information = 0;
66 Irp->IoStatus.Status = Status;
67 IoCompleteRequest(Irp, IO_NO_INCREMENT);
68 }
69
70 return Status;
71 }
72
73
74 NTSTATUS
75 NTAPI
76 IKsFilterFactory_fnQueryInterface(
77 IKsFilterFactory * iface,
78 IN REFIID refiid,
79 OUT PVOID* Output)
80 {
81 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
82
83 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
84 {
85 *Output = &This->lpVtbl;
86 _InterlockedIncrement(&This->ref);
87 return STATUS_SUCCESS;
88 }
89 return STATUS_UNSUCCESSFUL;
90 }
91
92 ULONG
93 NTAPI
94 IKsFilterFactory_fnAddRef(
95 IKsFilterFactory * iface)
96 {
97 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
98
99 return InterlockedIncrement(&This->ref);
100 }
101
102 ULONG
103 NTAPI
104 IKsFilterFactory_fnRelease(
105 IKsFilterFactory * iface)
106 {
107 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
108
109 InterlockedDecrement(&This->ref);
110
111 if (This->ref == 0)
112 {
113 if (!IsListEmpty(&This->SymbolicLinkList))
114 {
115 /* disable device interfaces */
116 KspSetDeviceInterfacesState(&This->SymbolicLinkList, FALSE);
117 /* free device interface strings */
118 KspFreeDeviceInterfaces(&This->SymbolicLinkList);
119 }
120
121 FreeItem(This);
122 return 0;
123 }
124 /* Return new reference count */
125 return This->ref;
126 }
127
128 KSFILTERFACTORY*
129 NTAPI
130 IKsFilterFactory_fnGetStruct(
131 IKsFilterFactory * iface)
132 {
133 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
134
135 return &This->FilterFactory;
136 }
137
138 NTSTATUS
139 NTAPI
140 IKsFilterFactory_fnSetDeviceClassesState(
141 IKsFilterFactory * iface,
142 IN BOOLEAN Enable)
143 {
144 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
145
146 return KspSetDeviceInterfacesState(&This->SymbolicLinkList, Enable);
147 }
148
149 VOID
150 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(
151 IKsFilterFactoryImpl * This,
152 PKSIDEVICE_HEADER DeviceHeader)
153 {
154 PKSBASIC_HEADER BasicHeader;
155 PKSFILTERFACTORY FilterFactory;
156
157 if (DeviceHeader->BasicHeader.FirstChild.FilterFactory == NULL)
158 {
159 /* first attached filter factory */
160 DeviceHeader->BasicHeader.FirstChild.FilterFactory = &This->FilterFactory;
161 return;
162 }
163
164 /* set to first entry */
165 FilterFactory = DeviceHeader->BasicHeader.FirstChild.FilterFactory;
166
167 do
168 {
169 /* get basic header */
170 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
171 /* sanity check */
172 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
173
174 if (BasicHeader->Next.FilterFactory)
175 {
176 /* iterate to next filter factory */
177 FilterFactory = BasicHeader->Next.FilterFactory;
178 }
179 else
180 {
181 /* found last entry */
182 break;
183 }
184 }while(FilterFactory);
185
186 /* attach filter factory */
187 BasicHeader->Next.FilterFactory = &This->FilterFactory;
188 }
189
190 NTSTATUS
191 NTAPI
192 IKsFilterFactory_fnInitialize(
193 IKsFilterFactory * iface,
194 IN PDEVICE_OBJECT DeviceObject,
195 IN const KSFILTER_DESCRIPTOR *Descriptor,
196 IN PWSTR RefString OPTIONAL,
197 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
198 IN ULONG CreateItemFlags,
199 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
200 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
201 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
202 {
203 UNICODE_STRING ReferenceString;
204 NTSTATUS Status;
205 PDEVICE_EXTENSION DeviceExtension;
206 KSOBJECT_CREATE_ITEM CreateItem;
207 BOOL FreeString = FALSE;
208 IKsDevice * KsDevice;
209
210 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
211
212 /* get device extension */
213 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
214
215 /* initialize filterfactory */
216 This->SleepCallback = SleepCallback;
217 This->WakeCallback = WakeCallback;
218 This->FilterFactory.FilterDescriptor = Descriptor;
219 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
220 This->Header.Type = KsObjectTypeFilterFactory;
221 This->Header.Parent.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
222 This->DeviceHeader = DeviceExtension->DeviceHeader;
223
224 /* unused fields */
225 KeInitializeMutex(&This->Header.ControlMutex, 0);
226 InitializeListHead(&This->Header.EventList);
227 KeInitializeSpinLock(&This->Header.EventListLock);
228
229
230 InitializeListHead(&This->SymbolicLinkList);
231
232 /* initialize filter factory control mutex */
233 KeInitializeMutex(&This->Header.ControlMutex, 0);
234
235 /* does the device use a reference string */
236 if (RefString || !Descriptor->ReferenceGuid)
237 {
238 /* use device reference string */
239 RtlInitUnicodeString(&ReferenceString, RefString);
240 }
241 else
242 {
243 /* create reference string from descriptor guid */
244 Status = RtlStringFromGUID(Descriptor->ReferenceGuid, &ReferenceString);
245
246 /* check for success */
247 if (!NT_SUCCESS(Status))
248 {
249 /* omg, we failed */
250 return Status;
251 }
252
253 FreeString = TRUE;
254 }
255
256 /* now register the device interface */
257 Status = KspRegisterDeviceInterfaces(DeviceExtension->DeviceHeader->KsDevice.PhysicalDeviceObject,
258 Descriptor->CategoriesCount,
259 Descriptor->Categories,
260 &ReferenceString,
261 &This->SymbolicLinkList);
262 /* check for success */
263 if (!NT_SUCCESS(Status))
264 {
265 DPRINT1("KspRegisterDeviceInterfaces failed with %x\n", Status);
266
267 if (FreeString)
268 {
269 /* free unicode string */
270 RtlFreeUnicodeString(&ReferenceString);
271 }
272
273 return Status;
274 }
275
276 /* now setup the create item */
277 CreateItem.SecurityDescriptor = SecurityDescriptor;
278 CreateItem.Flags = CreateItemFlags;
279 CreateItem.Create = IKsFilterFactory_Create;
280 CreateItem.Context = (PVOID)&This->FilterFactory;
281 RtlInitUnicodeString(&CreateItem.ObjectClass, ReferenceString.Buffer);
282
283 /* insert create item to device header */
284 Status = KsAllocateObjectCreateItem((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
285
286 if (FreeString)
287 {
288 /* free unicode string */
289 RtlFreeUnicodeString(&ReferenceString);
290 }
291
292 if (FilterFactory)
293 {
294 /* return filterfactory */
295 *FilterFactory = &This->FilterFactory;
296
297 /* create a object bag for the filter factory */
298 This->FilterFactory.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
299 if (This->FilterFactory.Bag)
300 {
301 /* initialize object bag */
302 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
303 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->FilterFactory.Bag, NULL);
304 }
305 }
306
307 /* attach filterfactory to device header */
308 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(This, DeviceExtension->DeviceHeader);
309
310 /* return result */
311 return Status;
312 }
313
314 static IKsFilterFactoryVtbl vt_IKsFilterFactoryVtbl =
315 {
316 IKsFilterFactory_fnQueryInterface,
317 IKsFilterFactory_fnAddRef,
318 IKsFilterFactory_fnRelease,
319 IKsFilterFactory_fnGetStruct,
320 IKsFilterFactory_fnSetDeviceClassesState,
321 IKsFilterFactory_fnInitialize
322 };
323
324
325 NTSTATUS
326 NTAPI
327 KspCreateFilterFactory(
328 IN PDEVICE_OBJECT DeviceObject,
329 IN const KSFILTER_DESCRIPTOR *Descriptor,
330 IN PWSTR RefString OPTIONAL,
331 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
332 IN ULONG CreateItemFlags,
333 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
334 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
335 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
336 {
337 IKsFilterFactoryImpl * This;
338 IKsFilterFactory * Filter;
339 NTSTATUS Status;
340
341 /* Lets allocate a filterfactory */
342 This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactoryImpl));
343 if (!This)
344 {
345 /* not enough memory */
346 return STATUS_INSUFFICIENT_RESOURCES;
347 }
348
349 /* initialize struct */
350 This->ref = 1;
351 This->lpVtbl = &vt_IKsFilterFactoryVtbl;
352
353 /* map to com object */
354 Filter = (IKsFilterFactory*)&This->lpVtbl;
355
356 /* initialize filter */
357 Status = Filter->lpVtbl->Initialize(Filter, DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
358 /* did we succeed */
359 if (!NT_SUCCESS(Status))
360 {
361 /* destroy filterfactory */
362 Filter->lpVtbl->Release(Filter);
363 }
364
365 /* return result */
366 return Status;
367 }
368
369 /*
370 @implemented
371 */
372 KSDDKAPI
373 NTSTATUS
374 NTAPI
375 KsCreateFilterFactory(
376 IN PDEVICE_OBJECT DeviceObject,
377 IN const KSFILTER_DESCRIPTOR *Descriptor,
378 IN PWSTR RefString OPTIONAL,
379 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
380 IN ULONG CreateItemFlags,
381 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
382 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
383 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
384 {
385 return KspCreateFilterFactory(DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
386
387 }
388
389 /*
390 @implemented
391 */
392 KSDDKAPI
393 NTSTATUS
394 NTAPI
395 KsFilterFactorySetDeviceClassesState(
396 IN PKSFILTERFACTORY FilterFactory,
397 IN BOOLEAN NewState)
398 {
399 IKsFilterFactory * Factory = (IKsFilterFactory*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
400
401 return Factory->lpVtbl->SetDeviceClassesState(Factory, NewState);
402 }
403
404
405 /*
406 @implemented
407 */
408 KSDDKAPI
409 PUNICODE_STRING
410 NTAPI
411 KsFilterFactoryGetSymbolicLink(
412 IN PKSFILTERFACTORY FilterFactory)
413 {
414 PSYMBOLIC_LINK_ENTRY LinkEntry;
415 IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
416
417 if (IsListEmpty(&Factory->SymbolicLinkList))
418 {
419 /* device has not registered any interfaces */
420 return NULL;
421 }
422
423 /* get first entry */
424 LinkEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Factory->SymbolicLinkList.Flink, SYMBOLIC_LINK_ENTRY, Entry);
425
426 /* return first link */
427 return &LinkEntry->SymbolicLink;
428 }
429
430 /*
431 @implemented
432 */
433 KSDDKAPI
434 NTSTATUS
435 NTAPI
436 KsFilterFactoryAddCreateItem(
437 IN PKSFILTERFACTORY FilterFactory,
438 IN PWSTR RefString,
439 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
440 IN ULONG CreateItemFlags)
441 {
442 KSOBJECT_CREATE_ITEM CreateItem;
443
444 IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
445
446 /* initialize create item */
447 CreateItem.Context = (PVOID)&Factory->FilterFactory;
448 CreateItem.Create = IKsFilterFactory_Create;
449 CreateItem.Flags = CreateItemFlags;
450 CreateItem.SecurityDescriptor = SecurityDescriptor;
451 RtlInitUnicodeString(&CreateItem.ObjectClass, RefString);
452
453 /* insert create item to device header */
454 return KsAllocateObjectCreateItem((KSDEVICE_HEADER)Factory->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
455 }
456
457 /*
458 @implemented
459 */
460 KSDDKAPI
461 NTSTATUS
462 NTAPI
463 KsFilterFactoryUpdateCacheData (
464 IN PKSFILTERFACTORY FilterFactory,
465 IN const KSFILTER_DESCRIPTOR* FilterDescriptor OPTIONAL)
466 {
467 UNIMPLEMENTED
468
469 return STATUS_NOT_IMPLEMENTED;
470 }
471