-Import tkreuzer's time implementation from AMD64 branch
[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 IKsDevice * KsDevice;
177
178 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
179
180 /* get device extension */
181 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
182
183 /* initialize filterfactory */
184 This->SleepCallback = SleepCallback;
185 This->WakeCallback = WakeCallback;
186 This->FilterFactory.FilterDescriptor = Descriptor;
187 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
188 This->Header.Type = KsObjectTypeFilterFactory;
189 This->Header.Parent.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
190 This->DeviceHeader = DeviceExtension->DeviceHeader;
191
192 /* unused fields */
193 KeInitializeMutex(&This->Header.ControlMutex, 0);
194 InitializeListHead(&This->Header.EventList);
195 KeInitializeSpinLock(&This->Header.EventListLock);
196
197
198 InitializeListHead(&This->SymbolicLinkList);
199 InitializeListHead(&This->FilterInstanceList);
200
201 /* initialize filter factory control mutex */
202 KeInitializeMutex(&This->Header.ControlMutex, 0);
203
204 /* does the device use a reference string */
205 if (RefString || !Descriptor->ReferenceGuid)
206 {
207 /* use device reference string */
208 RtlInitUnicodeString(&ReferenceString, RefString);
209 }
210 else
211 {
212 /* create reference string from descriptor guid */
213 Status = RtlStringFromGUID(Descriptor->ReferenceGuid, &ReferenceString);
214
215 /* check for success */
216 if (!NT_SUCCESS(Status))
217 {
218 /* omg, we failed */
219 return Status;
220 }
221
222 FreeString = TRUE;
223 }
224
225 /* now register the device interface */
226 Status = KspRegisterDeviceInterfaces(DeviceExtension->DeviceHeader->KsDevice.PhysicalDeviceObject,
227 Descriptor->CategoriesCount,
228 Descriptor->Categories,
229 &ReferenceString,
230 &This->SymbolicLinkList);
231 /* check for success */
232 if (!NT_SUCCESS(Status))
233 {
234 DPRINT1("KspRegisterDeviceInterfaces failed with %x\n", Status);
235
236 if (FreeString)
237 {
238 /* free unicode string */
239 RtlFreeUnicodeString(&ReferenceString);
240 }
241
242 return Status;
243 }
244
245 /* now setup the create item */
246 CreateItem.SecurityDescriptor = SecurityDescriptor;
247 CreateItem.Flags = CreateItemFlags;
248 CreateItem.Create = IKsFilterFactory_Create;
249 CreateItem.Context = (PVOID)&This->FilterFactory;
250 RtlInitUnicodeString(&CreateItem.ObjectClass, ReferenceString.Buffer);
251
252 /* insert create item to device header */
253 Status = KsAllocateObjectCreateItem((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
254
255 if (FreeString)
256 {
257 /* free unicode string */
258 RtlFreeUnicodeString(&ReferenceString);
259 }
260
261 if (FilterFactory)
262 {
263 /* return filterfactory */
264 *FilterFactory = &This->FilterFactory;
265
266 /* create a object bag for the filter factory */
267 This->FilterFactory.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
268 if (This->FilterFactory.Bag)
269 {
270 /* initialize object bag */
271 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
272 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->FilterFactory.Bag, NULL);
273 }
274 }
275
276
277 /* return result */
278 return Status;
279 }
280
281 NTSTATUS
282 NTAPI
283 IKsFilterFactory_fnAddFilterInstance(
284 IKsFilterFactory * iface,
285 IN IKsFilter *FilterInstance)
286 {
287 PFILTER_INSTANCE_ENTRY Entry;
288 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
289
290 /* allocate filter instance entry */
291 Entry = AllocateItem(NonPagedPool, sizeof(FILTER_INSTANCE_ENTRY));
292 if (!Entry)
293 return STATUS_INSUFFICIENT_RESOURCES;
294
295 /* initialize filter instance entry */
296 Entry->FilterInstance = FilterInstance;
297
298 /* insert entry */
299 InsertTailList(&This->FilterInstanceList, &Entry->Entry);
300 return STATUS_SUCCESS;
301 }
302
303 NTSTATUS
304 NTAPI
305 IKsFilterFactory_fnRemoveFilterInstance(
306 IKsFilterFactory * iface,
307 IN IKsFilter *FilterInstance)
308 {
309 PFILTER_INSTANCE_ENTRY InstanceEntry;
310 PLIST_ENTRY Entry;
311 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
312
313 /* point to first entry */
314 Entry = This->FilterInstanceList.Flink;
315
316 while(Entry != &This->FilterInstanceList)
317 {
318 InstanceEntry = (PFILTER_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, FILTER_INSTANCE_ENTRY, Entry);
319 if (InstanceEntry->FilterInstance == FilterInstance)
320 {
321 /* found entry */
322 RemoveEntryList(&InstanceEntry->Entry);
323 FreeItem(InstanceEntry);
324 return STATUS_SUCCESS;
325 }
326 }
327
328 /* entry not in list! */
329 return STATUS_NOT_FOUND;
330 }
331
332 static IKsFilterFactoryVtbl vt_IKsFilterFactoryVtbl =
333 {
334 IKsFilterFactory_fnQueryInterface,
335 IKsFilterFactory_fnAddRef,
336 IKsFilterFactory_fnRelease,
337 IKsFilterFactory_fnGetStruct,
338 IKsFilterFactory_fnSetDeviceClassesState,
339 IKsFilterFactory_fnInitialize,
340 IKsFilterFactory_fnAddFilterInstance,
341 IKsFilterFactory_fnRemoveFilterInstance
342 };
343
344
345 NTSTATUS
346 NTAPI
347 KspCreateFilterFactory(
348 IN PDEVICE_OBJECT DeviceObject,
349 IN const KSFILTER_DESCRIPTOR *Descriptor,
350 IN PWSTR RefString OPTIONAL,
351 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
352 IN ULONG CreateItemFlags,
353 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
354 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
355 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
356 {
357 IKsFilterFactoryImpl * This;
358 IKsFilterFactory * Filter;
359 NTSTATUS Status;
360
361 /* Lets allocate a filterfactory */
362 This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactoryImpl));
363 if (!This)
364 {
365 /* not enough memory */
366 return STATUS_INSUFFICIENT_RESOURCES;
367 }
368
369 /* initialize struct */
370 This->ref = 1;
371 This->lpVtbl = &vt_IKsFilterFactoryVtbl;
372
373 /* map to com object */
374 Filter = (IKsFilterFactory*)&This->lpVtbl;
375
376 /* initialize filter */
377 Status = Filter->lpVtbl->Initialize(Filter, DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
378 /* did we succeed */
379 if (!NT_SUCCESS(Status))
380 {
381 /* destroy filterfactory */
382 Filter->lpVtbl->Release(Filter);
383 }
384
385 /* return result */
386 return Status;
387 }
388
389 /*
390 @implemented
391 */
392 KSDDKAPI
393 NTSTATUS
394 NTAPI
395 KsCreateFilterFactory(
396 IN PDEVICE_OBJECT DeviceObject,
397 IN const KSFILTER_DESCRIPTOR *Descriptor,
398 IN PWSTR RefString OPTIONAL,
399 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
400 IN ULONG CreateItemFlags,
401 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
402 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
403 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
404 {
405 return KspCreateFilterFactory(DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
406
407 }
408
409 /*
410 @implemented
411 */
412 KSDDKAPI
413 NTSTATUS
414 NTAPI
415 KsFilterFactorySetDeviceClassesState(
416 IN PKSFILTERFACTORY FilterFactory,
417 IN BOOLEAN NewState)
418 {
419 IKsFilterFactory * Factory = (IKsFilterFactory*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
420
421 return Factory->lpVtbl->SetDeviceClassesState(Factory, NewState);
422 }
423
424
425 /*
426 @implemented
427 */
428 KSDDKAPI
429 PUNICODE_STRING
430 NTAPI
431 KsFilterFactoryGetSymbolicLink(
432 IN PKSFILTERFACTORY FilterFactory)
433 {
434 PSYMBOLIC_LINK_ENTRY LinkEntry;
435 IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
436
437 if (IsListEmpty(&Factory->SymbolicLinkList))
438 {
439 /* device has not registered any interfaces */
440 return NULL;
441 }
442
443 /* get first entry */
444 LinkEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Factory->SymbolicLinkList.Flink, SYMBOLIC_LINK_ENTRY, Entry);
445
446 /* return first link */
447 return &LinkEntry->SymbolicLink;
448 }
449
450 /*
451 @implemented
452 */
453 KSDDKAPI
454 NTSTATUS
455 NTAPI
456 KsFilterFactoryAddCreateItem(
457 IN PKSFILTERFACTORY FilterFactory,
458 IN PWSTR RefString,
459 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
460 IN ULONG CreateItemFlags)
461 {
462 KSOBJECT_CREATE_ITEM CreateItem;
463
464 IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
465
466 /* initialize create item */
467 CreateItem.Context = (PVOID)&Factory->FilterFactory;
468 CreateItem.Create = IKsFilterFactory_Create;
469 CreateItem.Flags = CreateItemFlags;
470 CreateItem.SecurityDescriptor = SecurityDescriptor;
471 RtlInitUnicodeString(&CreateItem.ObjectClass, RefString);
472
473 /* insert create item to device header */
474 return KsAllocateObjectCreateItem((KSDEVICE_HEADER)Factory->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
475 }
476
477 /*
478 @implemented
479 */
480 KSDDKAPI
481 NTSTATUS
482 NTAPI
483 KsFilterFactoryUpdateCacheData (
484 IN PKSFILTERFACTORY FilterFactory,
485 IN const KSFILTER_DESCRIPTOR* FilterDescriptor OPTIONAL)
486 {
487 UNIMPLEMENTED
488
489 return STATUS_NOT_IMPLEMENTED;
490 }
491