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