[KS]
[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 DPRINT("KsCreateFilterFactory\n");
342
343 /* Lets allocate a filterfactory */
344 This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactoryImpl));
345 if (!This)
346 {
347 /* not enough memory */
348 return STATUS_INSUFFICIENT_RESOURCES;
349 }
350
351 /* initialize struct */
352 This->ref = 1;
353 This->lpVtbl = &vt_IKsFilterFactoryVtbl;
354
355 /* map to com object */
356 Filter = (IKsFilterFactory*)&This->lpVtbl;
357
358 /* initialize filter */
359 Status = Filter->lpVtbl->Initialize(Filter, DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
360 /* did we succeed */
361 if (!NT_SUCCESS(Status))
362 {
363 /* destroy filterfactory */
364 Filter->lpVtbl->Release(Filter);
365 }
366
367 /* return result */
368 return Status;
369 }
370
371 /*
372 @implemented
373 */
374 KSDDKAPI
375 NTSTATUS
376 NTAPI
377 KsCreateFilterFactory(
378 IN PDEVICE_OBJECT DeviceObject,
379 IN const KSFILTER_DESCRIPTOR *Descriptor,
380 IN PWSTR RefString OPTIONAL,
381 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
382 IN ULONG CreateItemFlags,
383 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
384 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
385 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
386 {
387 return KspCreateFilterFactory(DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
388
389 }
390
391 /*
392 @implemented
393 */
394 KSDDKAPI
395 NTSTATUS
396 NTAPI
397 KsFilterFactorySetDeviceClassesState(
398 IN PKSFILTERFACTORY FilterFactory,
399 IN BOOLEAN NewState)
400 {
401 IKsFilterFactory * Factory = (IKsFilterFactory*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
402
403 return Factory->lpVtbl->SetDeviceClassesState(Factory, NewState);
404 }
405
406
407 /*
408 @implemented
409 */
410 KSDDKAPI
411 PUNICODE_STRING
412 NTAPI
413 KsFilterFactoryGetSymbolicLink(
414 IN PKSFILTERFACTORY FilterFactory)
415 {
416 PSYMBOLIC_LINK_ENTRY LinkEntry;
417 IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
418
419 if (IsListEmpty(&Factory->SymbolicLinkList))
420 {
421 /* device has not registered any interfaces */
422 return NULL;
423 }
424
425 /* get first entry */
426 LinkEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Factory->SymbolicLinkList.Flink, SYMBOLIC_LINK_ENTRY, Entry);
427
428 /* return first link */
429 return &LinkEntry->SymbolicLink;
430 }
431
432 /*
433 @implemented
434 */
435 KSDDKAPI
436 NTSTATUS
437 NTAPI
438 KsFilterFactoryAddCreateItem(
439 IN PKSFILTERFACTORY FilterFactory,
440 IN PWSTR RefString,
441 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
442 IN ULONG CreateItemFlags)
443 {
444 KSOBJECT_CREATE_ITEM CreateItem;
445
446 IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
447
448 /* initialize create item */
449 CreateItem.Context = (PVOID)&Factory->FilterFactory;
450 CreateItem.Create = IKsFilterFactory_Create;
451 CreateItem.Flags = CreateItemFlags;
452 CreateItem.SecurityDescriptor = SecurityDescriptor;
453 RtlInitUnicodeString(&CreateItem.ObjectClass, RefString);
454
455 /* insert create item to device header */
456 return KsAllocateObjectCreateItem((KSDEVICE_HEADER)Factory->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
457 }
458
459 /*
460 @implemented
461 */
462 KSDDKAPI
463 NTSTATUS
464 NTAPI
465 KsFilterFactoryUpdateCacheData (
466 IN PKSFILTERFACTORY FilterFactory,
467 IN const KSFILTER_DESCRIPTOR* FilterDescriptor OPTIONAL)
468 {
469 UNIMPLEMENTED
470 DPRINT("KsFilterFactoryUpdateCacheData %p\n", FilterDescriptor);
471
472 return STATUS_SUCCESS;
473 }
474