Sync to trunk head (r42241)
[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 LIST_ENTRY FilterInstanceList;
25 }IKsFilterFactoryImpl;
26
27 typedef struct
28 {
29 LIST_ENTRY Entry;
30 IKsFilter *FilterInstance;
31 }FILTER_INSTANCE_ENTRY, *PFILTER_INSTANCE_ENTRY;
32
33
34
35 VOID
36 NTAPI
37 IKsFilterFactory_ItemFreeCb(
38 IN PKSOBJECT_CREATE_ITEM CreateItem)
39 {
40 /* callback when create item is freed in the device header */
41 IKsFilterFactory * iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
42
43 iface->lpVtbl->Release(iface);
44 }
45
46 NTSTATUS
47 NTAPI
48 IKsFilterFactory_Create(
49 IN PDEVICE_OBJECT DeviceObject,
50 IN PIRP Irp)
51 {
52 PKSOBJECT_CREATE_ITEM CreateItem;
53 IKsFilterFactory * iface;
54 NTSTATUS Status;
55
56 /* access the create item */
57 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
58 if (!CreateItem)
59 {
60 DPRINT1("IKsFilterFactory_Create no CreateItem\n");
61 return STATUS_UNSUCCESSFUL;
62 }
63
64 /* get filter factory interface */
65 iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
66
67 /* create a filter instance */
68 Status = KspCreateFilter(DeviceObject, Irp, iface);
69
70 DPRINT("KspCreateFilter Status %x\n", Status);
71
72 if (Status != STATUS_PENDING)
73 {
74 Irp->IoStatus.Information = 0;
75 Irp->IoStatus.Status = Status;
76 IoCompleteRequest(Irp, IO_NO_INCREMENT);
77 }
78
79 return Status;
80 }
81
82
83 NTSTATUS
84 NTAPI
85 IKsFilterFactory_fnQueryInterface(
86 IKsFilterFactory * iface,
87 IN REFIID refiid,
88 OUT PVOID* Output)
89 {
90 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
91
92 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
93 {
94 *Output = &This->lpVtbl;
95 _InterlockedIncrement(&This->ref);
96 return STATUS_SUCCESS;
97 }
98 return STATUS_UNSUCCESSFUL;
99 }
100
101 ULONG
102 NTAPI
103 IKsFilterFactory_fnAddRef(
104 IKsFilterFactory * iface)
105 {
106 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
107
108 return InterlockedIncrement(&This->ref);
109 }
110
111 ULONG
112 NTAPI
113 IKsFilterFactory_fnRelease(
114 IKsFilterFactory * iface)
115 {
116 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
117
118 InterlockedDecrement(&This->ref);
119
120 if (This->ref == 0)
121 {
122 if (!IsListEmpty(&This->SymbolicLinkList))
123 {
124 /* disable device interfaces */
125 KspSetDeviceInterfacesState(&This->SymbolicLinkList, FALSE);
126 /* free device interface strings */
127 KspFreeDeviceInterfaces(&This->SymbolicLinkList);
128 }
129
130 FreeItem(This);
131 return 0;
132 }
133 /* Return new reference count */
134 return This->ref;
135 }
136
137 KSFILTERFACTORY*
138 NTAPI
139 IKsFilterFactory_fnGetStruct(
140 IKsFilterFactory * iface)
141 {
142 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
143
144 return &This->FilterFactory;
145 }
146
147 NTSTATUS
148 NTAPI
149 IKsFilterFactory_fnSetDeviceClassesState(
150 IKsFilterFactory * iface,
151 IN BOOLEAN Enable)
152 {
153 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
154
155 return KspSetDeviceInterfacesState(&This->SymbolicLinkList, Enable);
156 }
157
158 NTSTATUS
159 NTAPI
160 IKsFilterFactory_fnInitialize(
161 IKsFilterFactory * iface,
162 IN PDEVICE_OBJECT DeviceObject,
163 IN const KSFILTER_DESCRIPTOR *Descriptor,
164 IN PWSTR RefString OPTIONAL,
165 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
166 IN ULONG CreateItemFlags,
167 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
168 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
169 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
170 {
171 UNICODE_STRING ReferenceString;
172 NTSTATUS Status;
173 PDEVICE_EXTENSION DeviceExtension;
174 KSOBJECT_CREATE_ITEM CreateItem;
175 BOOL FreeString = FALSE;
176
177 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
178
179 /* get device extension */
180 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
181
182 /* initialize filterfactory */
183 This->SleepCallback = SleepCallback;
184 This->WakeCallback = WakeCallback;
185 This->FilterFactory.FilterDescriptor = Descriptor;
186 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
187 This->Header.Type = KsObjectTypeFilterFactory;
188 This->DeviceHeader = DeviceExtension->DeviceHeader;
189
190 InitializeListHead(&This->SymbolicLinkList);
191 InitializeListHead(&This->FilterInstanceList);
192
193 /* does the device use a reference string */
194 if (RefString || !Descriptor->ReferenceGuid)
195 {
196 /* use device reference string */
197 RtlInitUnicodeString(&ReferenceString, RefString);
198 }
199 else
200 {
201 /* create reference string from descriptor guid */
202 Status = RtlStringFromGUID(Descriptor->ReferenceGuid, &ReferenceString);
203
204 /* check for success */
205 if (!NT_SUCCESS(Status))
206 {
207 /* omg, we failed */
208 return Status;
209 }
210
211 FreeString = TRUE;
212 }
213
214 /* now register the device interface */
215 Status = KspRegisterDeviceInterfaces(DeviceExtension->DeviceHeader->KsDevice.PhysicalDeviceObject,
216 Descriptor->CategoriesCount,
217 Descriptor->Categories,
218 &ReferenceString,
219 &This->SymbolicLinkList);
220 /* check for success */
221 if (!NT_SUCCESS(Status))
222 {
223 DPRINT1("KspRegisterDeviceInterfaces failed with %x\n", Status);
224
225 if (FreeString)
226 {
227 /* free unicode string */
228 RtlFreeUnicodeString(&ReferenceString);
229 }
230
231 return Status;
232 }
233
234 /* now setup the create item */
235 CreateItem.SecurityDescriptor = SecurityDescriptor;
236 CreateItem.Flags = CreateItemFlags;
237 CreateItem.Create = IKsFilterFactory_Create;
238 CreateItem.Context = (PVOID)&This->FilterFactory;
239 RtlInitUnicodeString(&CreateItem.ObjectClass, ReferenceString.Buffer);
240
241 /* insert create item to device header */
242 Status = KsAllocateObjectCreateItem((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
243
244 if (FreeString)
245 {
246 /* free unicode string */
247 RtlFreeUnicodeString(&ReferenceString);
248 }
249
250 if (FilterFactory)
251 {
252 /* return filterfactory */
253 *FilterFactory = &This->FilterFactory;
254
255 /*FIXME create object bag */
256 }
257
258
259 /* return result */
260 return Status;
261 }
262
263 NTSTATUS
264 NTAPI
265 IKsFilterFactory_fnAddFilterInstance(
266 IKsFilterFactory * iface,
267 IN IKsFilter *FilterInstance)
268 {
269 PFILTER_INSTANCE_ENTRY Entry;
270 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
271
272 /* allocate filter instance entry */
273 Entry = AllocateItem(NonPagedPool, sizeof(FILTER_INSTANCE_ENTRY));
274 if (!Entry)
275 return STATUS_INSUFFICIENT_RESOURCES;
276
277 /* initialize filter instance entry */
278 Entry->FilterInstance = FilterInstance;
279
280 /* insert entry */
281 InsertTailList(&This->FilterInstanceList, &Entry->Entry);
282 return STATUS_SUCCESS;
283 }
284
285 NTSTATUS
286 NTAPI
287 IKsFilterFactory_fnRemoveFilterInstance(
288 IKsFilterFactory * iface,
289 IN IKsFilter *FilterInstance)
290 {
291 PFILTER_INSTANCE_ENTRY InstanceEntry;
292 PLIST_ENTRY Entry;
293 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
294
295 /* point to first entry */
296 Entry = This->FilterInstanceList.Flink;
297
298 while(Entry != &This->FilterInstanceList)
299 {
300 InstanceEntry = (PFILTER_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, FILTER_INSTANCE_ENTRY, Entry);
301 if (InstanceEntry->FilterInstance == FilterInstance)
302 {
303 /* found entry */
304 RemoveEntryList(&InstanceEntry->Entry);
305 FreeItem(InstanceEntry);
306 return STATUS_SUCCESS;
307 }
308 }
309
310 /* entry not in list! */
311 return STATUS_NOT_FOUND;
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 IKsFilterFactory_fnAddFilterInstance,
323 IKsFilterFactory_fnRemoveFilterInstance
324 };
325
326
327 NTSTATUS
328 NTAPI
329 KspCreateFilterFactory(
330 IN PDEVICE_OBJECT DeviceObject,
331 IN const KSFILTER_DESCRIPTOR *Descriptor,
332 IN PWSTR RefString OPTIONAL,
333 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
334 IN ULONG CreateItemFlags,
335 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
336 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
337 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
338 {
339 IKsFilterFactoryImpl * This;
340 IKsFilterFactory * Filter;
341 NTSTATUS Status;
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
471 return STATUS_NOT_IMPLEMENTED;
472 }
473