0e15bb76f3c04892b1ac81aad4d97bd0df6bfe7d
[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 KMUTEX ControlMutex;
25
26 }IKsFilterFactoryImpl;
27
28 VOID
29 NTAPI
30 IKsFilterFactory_ItemFreeCb(
31 IN PKSOBJECT_CREATE_ITEM CreateItem)
32 {
33 /* callback when create item is freed in the device header */
34 IKsFilterFactory * iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
35
36 iface->lpVtbl->Release(iface);
37 }
38
39 NTSTATUS
40 NTAPI
41 IKsFilterFactory_Create(
42 IN PDEVICE_OBJECT DeviceObject,
43 IN PIRP Irp)
44 {
45 PKSOBJECT_CREATE_ITEM CreateItem;
46 IKsFilterFactoryImpl * Factory;
47 IKsFilterFactory * iface;
48 NTSTATUS Status;
49
50 /* access the create item */
51 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
52 if (!CreateItem)
53 {
54 DPRINT1("IKsFilterFactory_Create no CreateItem\n");
55 return STATUS_UNSUCCESSFUL;
56 }
57
58 /* get filter factory interface */
59 Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
60
61 /* get interface */
62 iface = (IKsFilterFactory*)&Factory->lpVtbl;
63
64 /* create a filter instance */
65 Status = KspCreateFilter(DeviceObject, Irp, iface);
66
67 DPRINT("KspCreateFilter Status %x\n", Status);
68
69 if (Status != STATUS_PENDING)
70 {
71 Irp->IoStatus.Information = 0;
72 Irp->IoStatus.Status = Status;
73 IoCompleteRequest(Irp, IO_NO_INCREMENT);
74 }
75
76 return Status;
77 }
78
79
80 NTSTATUS
81 NTAPI
82 IKsFilterFactory_fnQueryInterface(
83 IKsFilterFactory * iface,
84 IN REFIID refiid,
85 OUT PVOID* Output)
86 {
87 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
88
89 if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
90 {
91 *Output = &This->lpVtbl;
92 _InterlockedIncrement(&This->ref);
93 return STATUS_SUCCESS;
94 }
95 return STATUS_UNSUCCESSFUL;
96 }
97
98 ULONG
99 NTAPI
100 IKsFilterFactory_fnAddRef(
101 IKsFilterFactory * iface)
102 {
103 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
104
105 return InterlockedIncrement(&This->ref);
106 }
107
108 ULONG
109 NTAPI
110 IKsFilterFactory_fnRelease(
111 IKsFilterFactory * iface)
112 {
113 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
114
115 InterlockedDecrement(&This->ref);
116
117 if (This->ref == 0)
118 {
119 if (!IsListEmpty(&This->SymbolicLinkList))
120 {
121 /* disable device interfaces */
122 KspSetDeviceInterfacesState(&This->SymbolicLinkList, FALSE);
123 /* free device interface strings */
124 KspFreeDeviceInterfaces(&This->SymbolicLinkList);
125 }
126
127 FreeItem(This);
128 return 0;
129 }
130 /* Return new reference count */
131 return This->ref;
132 }
133
134 KSFILTERFACTORY*
135 NTAPI
136 IKsFilterFactory_fnGetStruct(
137 IKsFilterFactory * iface)
138 {
139 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
140
141 return &This->FilterFactory;
142 }
143
144 NTSTATUS
145 NTAPI
146 IKsFilterFactory_fnSetDeviceClassesState(
147 IKsFilterFactory * iface,
148 IN BOOLEAN Enable)
149 {
150 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
151
152 return KspSetDeviceInterfacesState(&This->SymbolicLinkList, Enable);
153 }
154
155 VOID
156 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(
157 IKsFilterFactoryImpl * This,
158 PKSIDEVICE_HEADER DeviceHeader)
159 {
160 PKSBASIC_HEADER BasicHeader;
161 PKSFILTERFACTORY FilterFactory;
162
163 if (DeviceHeader->BasicHeader.FirstChild.FilterFactory == NULL)
164 {
165 /* first attached filter factory */
166 DeviceHeader->BasicHeader.FirstChild.FilterFactory = &This->FilterFactory;
167 return;
168 }
169
170 /* set to first entry */
171 FilterFactory = DeviceHeader->BasicHeader.FirstChild.FilterFactory;
172
173 do
174 {
175 /* get basic header */
176 BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)FilterFactory - sizeof(KSBASIC_HEADER));
177 /* sanity check */
178 ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory);
179
180 if (BasicHeader->Next.FilterFactory)
181 {
182 /* iterate to next filter factory */
183 FilterFactory = BasicHeader->Next.FilterFactory;
184 }
185 else
186 {
187 /* found last entry */
188 break;
189 }
190 }while(FilterFactory);
191
192 /* attach filter factory */
193 BasicHeader->Next.FilterFactory = &This->FilterFactory;
194 }
195
196 NTSTATUS
197 NTAPI
198 IKsFilterFactory_fnInitialize(
199 IKsFilterFactory * iface,
200 IN PDEVICE_OBJECT DeviceObject,
201 IN const KSFILTER_DESCRIPTOR *Descriptor,
202 IN PWSTR RefString OPTIONAL,
203 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
204 IN ULONG CreateItemFlags,
205 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
206 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
207 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
208 {
209 UNICODE_STRING ReferenceString;
210 NTSTATUS Status;
211 PDEVICE_EXTENSION DeviceExtension;
212 KSOBJECT_CREATE_ITEM CreateItem;
213 BOOL FreeString = FALSE;
214 IKsDevice * KsDevice;
215
216 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(iface, IKsFilterFactoryImpl, lpVtbl);
217
218 /* get device extension */
219 DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
220
221 /* initialize filterfactory */
222 This->SleepCallback = SleepCallback;
223 This->WakeCallback = WakeCallback;
224 This->FilterFactory.FilterDescriptor = Descriptor;
225 This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
226 This->Header.Type = KsObjectTypeFilterFactory;
227 This->Header.Parent.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
228 This->DeviceHeader = DeviceExtension->DeviceHeader;
229
230 /* initialize filter factory control mutex */
231 This->Header.ControlMutex = &This->ControlMutex;
232 KeInitializeMutex(This->Header.ControlMutex, 0);
233
234 /* unused fields */
235 InitializeListHead(&This->Header.EventList);
236 KeInitializeSpinLock(&This->Header.EventListLock);
237
238 InitializeListHead(&This->SymbolicLinkList);
239
240 /* does the device use a reference string */
241 if (RefString || !Descriptor->ReferenceGuid)
242 {
243 /* use device reference string */
244 RtlInitUnicodeString(&ReferenceString, RefString);
245 }
246 else
247 {
248 /* create reference string from descriptor guid */
249 Status = RtlStringFromGUID(Descriptor->ReferenceGuid, &ReferenceString);
250
251 /* check for success */
252 if (!NT_SUCCESS(Status))
253 {
254 /* omg, we failed */
255 return Status;
256 }
257
258 FreeString = TRUE;
259 }
260
261 DPRINT("IKsFilterFactory_fnInitialize CategoriesCount %u ReferenceString '%S'\n", Descriptor->CategoriesCount,ReferenceString.Buffer);
262
263 /* now register the device interface */
264 Status = KspRegisterDeviceInterfaces(DeviceExtension->DeviceHeader->KsDevice.PhysicalDeviceObject,
265 Descriptor->CategoriesCount,
266 Descriptor->Categories,
267 &ReferenceString,
268 &This->SymbolicLinkList);
269 /* check for success */
270 if (!NT_SUCCESS(Status))
271 {
272 DPRINT1("KspRegisterDeviceInterfaces failed with %x\n", Status);
273
274 if (FreeString)
275 {
276 /* free unicode string */
277 RtlFreeUnicodeString(&ReferenceString);
278 }
279
280 return Status;
281 }
282
283 /* now setup the create item */
284 CreateItem.SecurityDescriptor = SecurityDescriptor;
285 CreateItem.Flags = CreateItemFlags;
286 CreateItem.Create = IKsFilterFactory_Create;
287 CreateItem.Context = (PVOID)&This->FilterFactory;
288 RtlInitUnicodeString(&CreateItem.ObjectClass, ReferenceString.Buffer);
289
290 /* insert create item to device header */
291 Status = KsAllocateObjectCreateItem((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
292
293 if (FreeString)
294 {
295 /* free unicode string */
296 RtlFreeUnicodeString(&ReferenceString);
297 }
298
299 if (FilterFactory)
300 {
301 /* return filterfactory */
302 *FilterFactory = &This->FilterFactory;
303
304 /* create a object bag for the filter factory */
305 This->FilterFactory.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
306 if (This->FilterFactory.Bag)
307 {
308 /* initialize object bag */
309 KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
310 KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->FilterFactory.Bag, NULL);
311 }
312 }
313
314 /* attach filterfactory to device header */
315 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(This, DeviceExtension->DeviceHeader);
316
317 /* return result */
318 return Status;
319 }
320
321 static IKsFilterFactoryVtbl vt_IKsFilterFactoryVtbl =
322 {
323 IKsFilterFactory_fnQueryInterface,
324 IKsFilterFactory_fnAddRef,
325 IKsFilterFactory_fnRelease,
326 IKsFilterFactory_fnGetStruct,
327 IKsFilterFactory_fnSetDeviceClassesState,
328 IKsFilterFactory_fnInitialize
329 };
330
331
332 NTSTATUS
333 NTAPI
334 KspCreateFilterFactory(
335 IN PDEVICE_OBJECT DeviceObject,
336 IN const KSFILTER_DESCRIPTOR *Descriptor,
337 IN PWSTR RefString OPTIONAL,
338 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
339 IN ULONG CreateItemFlags,
340 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
341 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
342 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
343 {
344 IKsFilterFactoryImpl * This;
345 IKsFilterFactory * Filter;
346 NTSTATUS Status;
347
348 DPRINT("KsCreateFilterFactory\n");
349
350 /* Lets allocate a filterfactory */
351 This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactoryImpl));
352 if (!This)
353 {
354 /* not enough memory */
355 return STATUS_INSUFFICIENT_RESOURCES;
356 }
357
358 /* initialize struct */
359 This->ref = 1;
360 This->lpVtbl = &vt_IKsFilterFactoryVtbl;
361
362 /* map to com object */
363 Filter = (IKsFilterFactory*)&This->lpVtbl;
364
365 /* initialize filter */
366 Status = Filter->lpVtbl->Initialize(Filter, DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
367 /* did we succeed */
368 if (!NT_SUCCESS(Status))
369 {
370 /* destroy filterfactory */
371 Filter->lpVtbl->Release(Filter);
372 }
373
374 /* return result */
375 DPRINT("KsCreateFilterFactory %x\n", Status);
376 /* sanity check */
377 ASSERT(Status == STATUS_SUCCESS);
378
379 return Status;
380 }
381
382 /*
383 @implemented
384 */
385 KSDDKAPI
386 NTSTATUS
387 NTAPI
388 KsCreateFilterFactory(
389 IN PDEVICE_OBJECT DeviceObject,
390 IN const KSFILTER_DESCRIPTOR *Descriptor,
391 IN PWSTR RefString OPTIONAL,
392 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
393 IN ULONG CreateItemFlags,
394 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL,
395 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL,
396 OUT PKSFILTERFACTORY *FilterFactory OPTIONAL)
397 {
398 return KspCreateFilterFactory(DeviceObject, Descriptor, RefString, SecurityDescriptor, CreateItemFlags, SleepCallback, WakeCallback, FilterFactory);
399
400 }
401
402 /*
403 @implemented
404 */
405 KSDDKAPI
406 NTSTATUS
407 NTAPI
408 KsFilterFactorySetDeviceClassesState(
409 IN PKSFILTERFACTORY FilterFactory,
410 IN BOOLEAN NewState)
411 {
412 IKsFilterFactory * Factory;
413 IKsFilterFactoryImpl * This = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
414
415 Factory = (IKsFilterFactory*)&This->lpVtbl;
416 return Factory->lpVtbl->SetDeviceClassesState(Factory, NewState);
417 }
418
419
420 /*
421 @implemented
422 */
423 KSDDKAPI
424 PUNICODE_STRING
425 NTAPI
426 KsFilterFactoryGetSymbolicLink(
427 IN PKSFILTERFACTORY FilterFactory)
428 {
429 PSYMBOLIC_LINK_ENTRY LinkEntry;
430 IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
431
432 if (IsListEmpty(&Factory->SymbolicLinkList))
433 {
434 /* device has not registered any interfaces */
435 return NULL;
436 }
437
438 /* get first entry */
439 LinkEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Factory->SymbolicLinkList.Flink, SYMBOLIC_LINK_ENTRY, Entry);
440
441 /* return first link */
442 return &LinkEntry->SymbolicLink;
443 }
444
445 /*
446 @implemented
447 */
448 KSDDKAPI
449 NTSTATUS
450 NTAPI
451 KsFilterFactoryAddCreateItem(
452 IN PKSFILTERFACTORY FilterFactory,
453 IN PWSTR RefString,
454 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
455 IN ULONG CreateItemFlags)
456 {
457 KSOBJECT_CREATE_ITEM CreateItem;
458
459 IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
460
461 /* initialize create item */
462 CreateItem.Context = (PVOID)&Factory->FilterFactory;
463 CreateItem.Create = IKsFilterFactory_Create;
464 CreateItem.Flags = CreateItemFlags;
465 CreateItem.SecurityDescriptor = SecurityDescriptor;
466 RtlInitUnicodeString(&CreateItem.ObjectClass, RefString);
467
468 /* insert create item to device header */
469 return KsAllocateObjectCreateItem((KSDEVICE_HEADER)Factory->DeviceHeader, &CreateItem, TRUE, IKsFilterFactory_ItemFreeCb);
470 }
471
472 ULONG
473 KspCacheAddData(
474 PKSPCACHE_DESCRIPTOR Descriptor,
475 LPCVOID Data,
476 ULONG Length)
477 {
478 ULONG Index;
479
480 for(Index = 0; Index < Descriptor->DataOffset; Index++)
481 {
482 if (RtlCompareMemory(Descriptor->DataCache, Data, Length) == Length)
483 {
484 if (Index + Length > Descriptor->DataOffset)
485 {
486 /* adjust used space */
487 Descriptor->DataOffset = Index + Length;
488 /* return absolute offset */
489 return Descriptor->DataLength + Index;
490 }
491 }
492 }
493
494 /* sanity check */
495 ASSERT(Descriptor->DataOffset + Length < Descriptor->DataLength);
496
497 /* copy to data blob */
498 RtlMoveMemory((Descriptor->DataCache + Descriptor->DataOffset), Data, Length);
499
500 /* backup offset */
501 Index = Descriptor->DataOffset;
502
503 /* adjust used space */
504 Descriptor->DataOffset += Length;
505
506 /* return absolute offset */
507 return Descriptor->DataLength + Index;
508 }
509
510 /*
511 @implemented
512 */
513 KSDDKAPI
514 NTSTATUS
515 NTAPI
516 KsFilterFactoryUpdateCacheData(
517 IN PKSFILTERFACTORY FilterFactory,
518 IN const KSFILTER_DESCRIPTOR* FilterDescriptor OPTIONAL)
519 {
520 KSPCACHE_DESCRIPTOR Descriptor;
521 PKSPCACHE_FILTER_HEADER FilterHeader;
522 UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
523 PKSPCACHE_PIN_HEADER PinHeader;
524 ULONG Index, SubIndex;
525 PLIST_ENTRY Entry;
526 PSYMBOLIC_LINK_ENTRY SymEntry;
527 BOOLEAN Found;
528 HKEY hKey;
529 NTSTATUS Status = STATUS_SUCCESS;
530
531 IKsFilterFactoryImpl * Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(FilterFactory, IKsFilterFactoryImpl, FilterFactory);
532
533 DPRINT("KsFilterFactoryUpdateCacheData %p\n", FilterDescriptor);
534
535 if (!FilterDescriptor)
536 FilterDescriptor = Factory->FilterFactory.FilterDescriptor;
537
538 ASSERT(FilterDescriptor);
539
540 /* initialize cache descriptor */
541 RtlZeroMemory(&Descriptor, sizeof(KSPCACHE_DESCRIPTOR));
542
543 /* calculate filter data size */
544 Descriptor.FilterLength = sizeof(KSPCACHE_FILTER_HEADER);
545
546 /* FIXME support variable size pin descriptors */
547 ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
548
549 for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
550 {
551 /* add filter descriptor */
552 Descriptor.FilterLength += sizeof(KSPCACHE_PIN_HEADER);
553
554 if (FilterDescriptor->PinDescriptors[Index].PinDescriptor.Category)
555 {
556 /* add extra ULONG for offset to category */
557 Descriptor.FilterLength += sizeof(ULONG);
558
559 /* add size for clsid */
560 Descriptor.DataLength += sizeof(CLSID);
561 }
562
563 /* add space for formats */
564 Descriptor.FilterLength += FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRangesCount * sizeof(KSPCACHE_DATARANGE);
565
566 /* add space for MajorFormat / MinorFormat */
567 Descriptor.DataLength += FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRangesCount * sizeof(CLSID) * 2;
568
569 /* add space for mediums */
570 Descriptor.FilterLength += FilterDescriptor->PinDescriptors[Index].PinDescriptor.MediumsCount * sizeof(ULONG);
571
572 /* add space for the data */
573 Descriptor.DataLength += FilterDescriptor->PinDescriptors[Index].PinDescriptor.MediumsCount * sizeof(KSPCACHE_MEDIUM);
574 }
575
576 /* now allocate the space */
577 Descriptor.FilterData = (PUCHAR)AllocateItem(NonPagedPool, Descriptor.DataLength + Descriptor.FilterLength);
578 if (!Descriptor.FilterData)
579 {
580 /* no memory */
581 return STATUS_INSUFFICIENT_RESOURCES;
582 }
583
584 /* initialize data cache */
585 Descriptor.DataCache = (PUCHAR)((ULONG_PTR)Descriptor.FilterData + Descriptor.FilterLength);
586
587 /* setup filter header */
588 FilterHeader = (PKSPCACHE_FILTER_HEADER)Descriptor.FilterData;
589
590 FilterHeader->dwVersion = 2;
591 FilterHeader->dwMerit = MERIT_DO_NOT_USE;
592 FilterHeader->dwUnused = 0;
593 FilterHeader->dwPins = FilterDescriptor->PinDescriptorsCount;
594
595 Descriptor.FilterOffset = sizeof(KSPCACHE_FILTER_HEADER);
596
597 /* write pin headers */
598 for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++)
599 {
600 /* get offset to pin */
601 PinHeader = (PKSPCACHE_PIN_HEADER)((ULONG_PTR)Descriptor.FilterData + Descriptor.FilterOffset);
602
603 /* write pin header */
604 PinHeader->Signature = 0x33697030 + Index;
605 PinHeader->Flags = 0;
606 PinHeader->Instances = FilterDescriptor->PinDescriptors[Index].InstancesPossible;
607 if (PinHeader->Instances > 1)
608 PinHeader->Flags |= REG_PINFLAG_B_MANY;
609
610
611 PinHeader->MediaTypes = FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRangesCount;
612 PinHeader->Mediums = FilterDescriptor->PinDescriptors[Index].PinDescriptor.MediumsCount;
613 PinHeader->Category = (FilterDescriptor->PinDescriptors[Index].PinDescriptor.Category ? TRUE : FALSE);
614
615 Descriptor.FilterOffset += sizeof(KSPCACHE_PIN_HEADER);
616
617 if (PinHeader->Category)
618 {
619 /* get category offset */
620 PULONG Category = (PULONG)(PinHeader + 1);
621
622 /* write category offset */
623 *Category = KspCacheAddData(&Descriptor, FilterDescriptor->PinDescriptors[Index].PinDescriptor.Category, sizeof(CLSID));
624
625 /* adjust offset */
626 Descriptor.FilterOffset += sizeof(ULONG);
627 }
628
629 /* add dataranges */
630 for(SubIndex = 0; SubIndex < FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRangesCount; SubIndex++)
631 {
632 /* get datarange offset */
633 PKSPCACHE_DATARANGE DataRange = (PKSPCACHE_DATARANGE)((ULONG_PTR)Descriptor.FilterData + Descriptor.FilterOffset);
634
635 /* initialize data range */
636 DataRange->Signature = 0x33797430 + SubIndex;
637 DataRange->dwUnused = 0;
638 DataRange->OffsetMajor = KspCacheAddData(&Descriptor, &FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRanges[SubIndex]->MajorFormat, sizeof(CLSID));
639 DataRange->OffsetMinor = KspCacheAddData(&Descriptor, &FilterDescriptor->PinDescriptors[Index].PinDescriptor.DataRanges[SubIndex]->SubFormat, sizeof(CLSID));
640
641 /* adjust offset */
642 Descriptor.FilterOffset += sizeof(KSPCACHE_DATARANGE);
643 }
644
645 /* add mediums */
646 for(SubIndex = 0; SubIndex < FilterDescriptor->PinDescriptors[Index].PinDescriptor.MediumsCount; SubIndex++)
647 {
648 KSPCACHE_MEDIUM Medium;
649 PULONG MediumOffset;
650
651 /* get pin medium offset */
652 MediumOffset = (PULONG)((ULONG_PTR)Descriptor.FilterData + Descriptor.FilterOffset);
653
654 /* copy medium guid */
655 RtlMoveMemory(&Medium.Medium, &FilterDescriptor->PinDescriptors[Index].PinDescriptor.Mediums[SubIndex].Set, sizeof(GUID));
656 Medium.dw1 = FilterDescriptor->PinDescriptors[Index].PinDescriptor.Mediums[SubIndex].Id; /* FIXME verify */
657 Medium.dw2 = 0;
658
659 *MediumOffset = KspCacheAddData(&Descriptor, &Medium, sizeof(KSPCACHE_MEDIUM));
660
661 /* adjust offset */
662 Descriptor.FilterOffset += sizeof(ULONG);
663 }
664 }
665
666 /* sanity checks */
667 ASSERT(Descriptor.FilterOffset == Descriptor.FilterLength);
668 ASSERT(Descriptor.DataOffset <= Descriptor.DataLength);
669
670
671 /* now go through all entries and update 'FilterData' key */
672 for(Index = 0; Index < FilterDescriptor->CategoriesCount; Index++)
673 {
674 /* get first entry */
675 Entry = Factory->SymbolicLinkList.Flink;
676
677 /* set status to not found */
678 Found = FALSE;
679 /* loop list until the the current category is found */
680 while(Entry != &Factory->SymbolicLinkList)
681 {
682 /* fetch symbolic link entry */
683 SymEntry = (PSYMBOLIC_LINK_ENTRY)CONTAINING_RECORD(Entry, SYMBOLIC_LINK_ENTRY, Entry);
684
685 if (IsEqualGUIDAligned(&SymEntry->DeviceInterfaceClass, &FilterDescriptor->Categories[Index]))
686 {
687 /* found category */
688 Found = TRUE;
689 break;
690 }
691
692 /* move to next entry */
693 Entry = Entry->Flink;
694 }
695
696 if (!Found)
697 {
698 /* filter category is not present */
699 Status = STATUS_INVALID_PARAMETER;
700 break;
701 }
702
703 /* now open device interface */
704 Status = IoOpenDeviceInterfaceRegistryKey(&SymEntry->SymbolicLink, KEY_WRITE, &hKey);
705 if (!NT_SUCCESS(Status))
706 {
707 /* failed to open interface key */
708 break;
709 }
710
711 /* update filterdata key */
712 Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Descriptor.FilterData, Descriptor.FilterLength + Descriptor.DataOffset);
713
714 /* close filterdata key */
715 ZwClose(hKey);
716
717 if (!NT_SUCCESS(Status))
718 {
719 /* failed to set key value */
720 break;
721 }
722 }
723 /* free filter data */
724 FreeItem(Descriptor.FilterData);
725
726 /* done */
727 return Status;
728 }
729