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
16 KSBASIC_HEADER Header
;
17 KSFILTERFACTORY FilterFactory
;
20 PKSIDEVICE_HEADER DeviceHeader
;
21 PFNKSFILTERFACTORYPOWER SleepCallback
;
22 PFNKSFILTERFACTORYPOWER WakeCallback
;
24 LIST_ENTRY SymbolicLinkList
;
27 }IKsFilterFactoryImpl
;
31 IKsFilterFactory_ItemFreeCb(
32 IN PKSOBJECT_CREATE_ITEM CreateItem
)
34 /* callback when create item is freed in the device header */
35 IKsFilterFactory
* iface
= (IKsFilterFactory
*)CONTAINING_RECORD(CreateItem
->Context
, IKsFilterFactoryImpl
, FilterFactory
);
37 iface
->lpVtbl
->Release(iface
);
42 IKsFilterFactory_Create(
43 IN PDEVICE_OBJECT DeviceObject
,
46 PKSOBJECT_CREATE_ITEM CreateItem
;
47 IKsFilterFactoryImpl
* Factory
;
48 IKsFilterFactory
* iface
;
51 /* access the create item */
52 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
55 DPRINT1("IKsFilterFactory_Create no CreateItem\n");
56 return STATUS_UNSUCCESSFUL
;
59 /* get filter factory interface */
60 Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(CreateItem
->Context
, IKsFilterFactoryImpl
, FilterFactory
);
63 iface
= (IKsFilterFactory
*)&Factory
->Header
.OuterUnknown
;
65 /* create a filter instance */
66 Status
= KspCreateFilter(DeviceObject
, Irp
, iface
);
68 DPRINT("KspCreateFilter Status %x\n", Status
);
70 if (Status
!= STATUS_PENDING
)
72 Irp
->IoStatus
.Information
= 0;
73 Irp
->IoStatus
.Status
= Status
;
74 CompleteRequest(Irp
, IO_NO_INCREMENT
);
83 IKsFilterFactory_fnQueryInterface(
84 IKsFilterFactory
* iface
,
90 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
92 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
94 *Output
= &This
->Header
.OuterUnknown
;
95 _InterlockedIncrement(&This
->ref
);
96 return STATUS_SUCCESS
;
99 if (This
->Header
.ClientAggregate
)
101 /* using client aggregate */
102 Status
= This
->Header
.ClientAggregate
->lpVtbl
->QueryInterface(This
->Header
.ClientAggregate
, refiid
, Output
);
104 if (NT_SUCCESS(Status
))
106 /* client aggregate supports interface */
111 DPRINT("IKsFilterFactory_fnQueryInterface no interface\n");
112 return STATUS_NOT_SUPPORTED
;
117 IKsFilterFactory_fnAddRef(
118 IKsFilterFactory
* iface
)
120 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
122 return InterlockedIncrement(&This
->ref
);
127 IKsFilterFactory_fnRelease(
128 IKsFilterFactory
* iface
)
130 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
132 InterlockedDecrement(&This
->ref
);
136 if (!IsListEmpty(&This
->SymbolicLinkList
))
138 /* disable device interfaces */
139 KspSetDeviceInterfacesState(&This
->SymbolicLinkList
, FALSE
);
140 /* free device interface strings */
141 KspFreeDeviceInterfaces(&This
->SymbolicLinkList
);
147 /* Return new reference count */
153 IKsFilterFactory_fnGetStruct(
154 IKsFilterFactory
* iface
)
156 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
158 return &This
->FilterFactory
;
163 IKsFilterFactory_fnSetDeviceClassesState(
164 IKsFilterFactory
* iface
,
167 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
169 return KspSetDeviceInterfacesState(&This
->SymbolicLinkList
, Enable
);
173 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(
174 IKsFilterFactoryImpl
* This
,
175 PKSIDEVICE_HEADER DeviceHeader
)
177 PKSBASIC_HEADER BasicHeader
;
178 PKSFILTERFACTORY FilterFactory
;
180 if (DeviceHeader
->BasicHeader
.FirstChild
.FilterFactory
== NULL
)
182 /* first attached filter factory */
183 DeviceHeader
->BasicHeader
.FirstChild
.FilterFactory
= &This
->FilterFactory
;
187 /* set to first entry */
188 FilterFactory
= DeviceHeader
->BasicHeader
.FirstChild
.FilterFactory
;
192 /* get basic header */
193 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)FilterFactory
- sizeof(KSBASIC_HEADER
));
195 ASSERT(BasicHeader
->Type
== KsObjectTypeFilterFactory
);
197 if (BasicHeader
->Next
.FilterFactory
)
199 /* iterate to next filter factory */
200 FilterFactory
= BasicHeader
->Next
.FilterFactory
;
204 /* found last entry */
207 }while(FilterFactory
);
209 /* attach filter factory */
210 BasicHeader
->Next
.FilterFactory
= &This
->FilterFactory
;
215 IKsFilterFactory_fnInitialize(
216 IKsFilterFactory
* iface
,
217 IN PDEVICE_OBJECT DeviceObject
,
218 IN
const KSFILTER_DESCRIPTOR
*Descriptor
,
219 IN PWSTR RefString OPTIONAL
,
220 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
221 IN ULONG CreateItemFlags
,
222 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL
,
223 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL
,
224 OUT PKSFILTERFACTORY
*FilterFactory OPTIONAL
)
226 UNICODE_STRING ReferenceString
;
228 PDEVICE_EXTENSION DeviceExtension
;
229 KSOBJECT_CREATE_ITEM CreateItem
;
230 BOOL FreeString
= FALSE
;
231 IKsDevice
* KsDevice
;
233 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
235 /* get device extension */
236 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
238 /* initialize filterfactory */
239 This
->SleepCallback
= SleepCallback
;
240 This
->WakeCallback
= WakeCallback
;
241 This
->Header
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
242 This
->Header
.Type
= KsObjectTypeFilterFactory
;
243 This
->Header
.Parent
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
244 This
->DeviceHeader
= DeviceExtension
->DeviceHeader
;
246 /* copy descriptor */
247 This
->FilterFactory
.FilterDescriptor
= AllocateItem(NonPagedPool
, sizeof(KSFILTER_DESCRIPTOR
));
248 if (!This
->FilterFactory
.FilterDescriptor
)
250 DPRINT("out of memory");
251 return STATUS_INSUFFICIENT_RESOURCES
;
253 RtlMoveMemory((PVOID
)This
->FilterFactory
.FilterDescriptor
, (PVOID
)Descriptor
, sizeof(KSFILTER_DESCRIPTOR
));
255 /* initialize filter factory control mutex */
256 This
->Header
.ControlMutex
= &This
->ControlMutex
;
257 KeInitializeMutex(This
->Header
.ControlMutex
, 0);
260 InitializeListHead(&This
->Header
.EventList
);
261 KeInitializeSpinLock(&This
->Header
.EventListLock
);
263 InitializeListHead(&This
->SymbolicLinkList
);
265 /* does the device use a reference string */
266 if (RefString
|| !Descriptor
->ReferenceGuid
)
268 /* use device reference string */
269 RtlInitUnicodeString(&ReferenceString
, RefString
);
273 /* create reference string from descriptor guid */
274 Status
= RtlStringFromGUID(Descriptor
->ReferenceGuid
, &ReferenceString
);
276 /* check for success */
277 if (!NT_SUCCESS(Status
))
286 DPRINT("IKsFilterFactory_fnInitialize CategoriesCount %u ReferenceString '%S'\n", Descriptor
->CategoriesCount
,ReferenceString
.Buffer
);
288 /* now register the device interface */
289 Status
= KspRegisterDeviceInterfaces(DeviceExtension
->DeviceHeader
->KsDevice
.PhysicalDeviceObject
,
290 Descriptor
->CategoriesCount
,
291 Descriptor
->Categories
,
293 &This
->SymbolicLinkList
);
294 /* check for success */
295 if (!NT_SUCCESS(Status
))
297 DPRINT1("KspRegisterDeviceInterfaces failed with %x\n", Status
);
301 /* free unicode string */
302 RtlFreeUnicodeString(&ReferenceString
);
308 /* now setup the create item */
309 CreateItem
.SecurityDescriptor
= SecurityDescriptor
;
310 CreateItem
.Flags
= CreateItemFlags
;
311 CreateItem
.Create
= IKsFilterFactory_Create
;
312 CreateItem
.Context
= (PVOID
)&This
->FilterFactory
;
313 RtlInitUnicodeString(&CreateItem
.ObjectClass
, ReferenceString
.Buffer
);
315 /* insert create item to device header */
316 Status
= KsAllocateObjectCreateItem((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
, &CreateItem
, TRUE
, IKsFilterFactory_ItemFreeCb
);
320 /* free unicode string */
321 RtlFreeUnicodeString(&ReferenceString
);
324 /* create a object bag for the filter factory */
325 This
->FilterFactory
.Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
326 if (This
->FilterFactory
.Bag
)
328 /* initialize object bag */
329 KsDevice
= (IKsDevice
*)&DeviceExtension
->DeviceHeader
->BasicHeader
.OuterUnknown
;
330 KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, (PKSIOBJECT_BAG
)This
->FilterFactory
.Bag
, NULL
);
335 /* return filterfactory */
336 *FilterFactory
= &This
->FilterFactory
;
339 /* attach filterfactory to device header */
340 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(This
, DeviceExtension
->DeviceHeader
);
346 static IKsFilterFactoryVtbl vt_IKsFilterFactoryVtbl
=
348 IKsFilterFactory_fnQueryInterface
,
349 IKsFilterFactory_fnAddRef
,
350 IKsFilterFactory_fnRelease
,
351 IKsFilterFactory_fnGetStruct
,
352 IKsFilterFactory_fnSetDeviceClassesState
,
353 IKsFilterFactory_fnInitialize
359 KspCreateFilterFactory(
360 IN PDEVICE_OBJECT DeviceObject
,
361 IN
const KSFILTER_DESCRIPTOR
*Descriptor
,
362 IN PWSTR RefString OPTIONAL
,
363 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
364 IN ULONG CreateItemFlags
,
365 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL
,
366 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL
,
367 OUT PKSFILTERFACTORY
*FilterFactory OPTIONAL
)
369 IKsFilterFactoryImpl
* This
;
370 IKsFilterFactory
* Filter
;
373 DPRINT("KsCreateFilterFactory\n");
375 /* Lets allocate a filterfactory */
376 This
= AllocateItem(NonPagedPool
, sizeof(IKsFilterFactoryImpl
));
379 /* not enough memory */
380 return STATUS_INSUFFICIENT_RESOURCES
;
383 /* initialize struct */
385 This
->Header
.OuterUnknown
= (PUNKNOWN
)&vt_IKsFilterFactoryVtbl
;
387 /* map to com object */
388 Filter
= (IKsFilterFactory
*)&This
->Header
.OuterUnknown
;
390 /* initialize filter */
391 Status
= Filter
->lpVtbl
->Initialize(Filter
, DeviceObject
, Descriptor
, RefString
, SecurityDescriptor
, CreateItemFlags
, SleepCallback
, WakeCallback
, FilterFactory
);
393 if (!NT_SUCCESS(Status
))
395 /* destroy filterfactory */
396 Filter
->lpVtbl
->Release(Filter
);
400 DPRINT("KsCreateFilterFactory %x\n", Status
);
402 ASSERT(Status
== STATUS_SUCCESS
);
413 KsCreateFilterFactory(
414 IN PDEVICE_OBJECT DeviceObject
,
415 IN
const KSFILTER_DESCRIPTOR
*Descriptor
,
416 IN PWSTR RefString OPTIONAL
,
417 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
418 IN ULONG CreateItemFlags
,
419 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL
,
420 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL
,
421 OUT PKSFILTERFACTORY
*FilterFactory OPTIONAL
)
423 return KspCreateFilterFactory(DeviceObject
, Descriptor
, RefString
, SecurityDescriptor
, CreateItemFlags
, SleepCallback
, WakeCallback
, FilterFactory
);
433 KsFilterFactorySetDeviceClassesState(
434 IN PKSFILTERFACTORY FilterFactory
,
437 IKsFilterFactory
* Factory
;
438 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
440 Factory
= (IKsFilterFactory
*)&This
->Header
.OuterUnknown
;
441 return Factory
->lpVtbl
->SetDeviceClassesState(Factory
, NewState
);
451 KsFilterFactoryGetSymbolicLink(
452 IN PKSFILTERFACTORY FilterFactory
)
454 PSYMBOLIC_LINK_ENTRY LinkEntry
;
455 IKsFilterFactoryImpl
* Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
457 if (IsListEmpty(&Factory
->SymbolicLinkList
))
459 /* device has not registered any interfaces */
463 /* get first entry */
464 LinkEntry
= (PSYMBOLIC_LINK_ENTRY
)CONTAINING_RECORD(Factory
->SymbolicLinkList
.Flink
, SYMBOLIC_LINK_ENTRY
, Entry
);
466 /* return first link */
467 return &LinkEntry
->SymbolicLink
;
476 KsFilterFactoryAddCreateItem(
477 IN PKSFILTERFACTORY FilterFactory
,
479 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
480 IN ULONG CreateItemFlags
)
482 KSOBJECT_CREATE_ITEM CreateItem
;
484 IKsFilterFactoryImpl
* Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
486 /* initialize create item */
487 CreateItem
.Context
= (PVOID
)&Factory
->FilterFactory
;
488 CreateItem
.Create
= IKsFilterFactory_Create
;
489 CreateItem
.Flags
= CreateItemFlags
;
490 CreateItem
.SecurityDescriptor
= SecurityDescriptor
;
491 RtlInitUnicodeString(&CreateItem
.ObjectClass
, RefString
);
493 /* insert create item to device header */
494 return KsAllocateObjectCreateItem((KSDEVICE_HEADER
)Factory
->DeviceHeader
, &CreateItem
, TRUE
, IKsFilterFactory_ItemFreeCb
);
499 PKSPCACHE_DESCRIPTOR Descriptor
,
505 for(Index
= 0; Index
< Descriptor
->DataOffset
; Index
++)
507 if (RtlCompareMemory(Descriptor
->DataCache
, Data
, Length
) == Length
)
509 if (Index
+ Length
> Descriptor
->DataOffset
)
511 /* adjust used space */
512 Descriptor
->DataOffset
= Index
+ Length
;
513 /* return absolute offset */
514 return Descriptor
->DataLength
+ Index
;
520 ASSERT(Descriptor
->DataOffset
+ Length
< Descriptor
->DataLength
);
522 /* copy to data blob */
523 RtlMoveMemory((Descriptor
->DataCache
+ Descriptor
->DataOffset
), Data
, Length
);
526 Index
= Descriptor
->DataOffset
;
528 /* adjust used space */
529 Descriptor
->DataOffset
+= Length
;
531 /* return absolute offset */
532 return Descriptor
->DataLength
+ Index
;
541 KsFilterFactoryUpdateCacheData(
542 IN PKSFILTERFACTORY FilterFactory
,
543 IN
const KSFILTER_DESCRIPTOR
* FilterDescriptor OPTIONAL
)
545 KSPCACHE_DESCRIPTOR Descriptor
;
546 PKSPCACHE_FILTER_HEADER FilterHeader
;
547 UNICODE_STRING FilterData
= RTL_CONSTANT_STRING(L
"FilterData");
548 PKSPCACHE_PIN_HEADER PinHeader
;
549 ULONG Index
, SubIndex
;
551 PSYMBOLIC_LINK_ENTRY SymEntry
;
554 NTSTATUS Status
= STATUS_SUCCESS
;
556 IKsFilterFactoryImpl
* Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
558 DPRINT("KsFilterFactoryUpdateCacheData %p\n", FilterDescriptor
);
560 if (!FilterDescriptor
)
561 FilterDescriptor
= Factory
->FilterFactory
.FilterDescriptor
;
563 ASSERT(FilterDescriptor
);
565 /* initialize cache descriptor */
566 RtlZeroMemory(&Descriptor
, sizeof(KSPCACHE_DESCRIPTOR
));
568 /* calculate filter data size */
569 Descriptor
.FilterLength
= sizeof(KSPCACHE_FILTER_HEADER
);
571 /* FIXME support variable size pin descriptors */
572 ASSERT(FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
574 for(Index
= 0; Index
< FilterDescriptor
->PinDescriptorsCount
; Index
++)
576 /* add filter descriptor */
577 Descriptor
.FilterLength
+= sizeof(KSPCACHE_PIN_HEADER
);
579 if (FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Category
)
581 /* add extra ULONG for offset to category */
582 Descriptor
.FilterLength
+= sizeof(ULONG
);
584 /* add size for clsid */
585 Descriptor
.DataLength
+= sizeof(CLSID
);
588 /* add space for formats */
589 Descriptor
.FilterLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
* sizeof(KSPCACHE_DATARANGE
);
591 /* add space for MajorFormat / MinorFormat */
592 Descriptor
.DataLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
* sizeof(CLSID
) * 2;
594 /* add space for mediums */
595 Descriptor
.FilterLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
* sizeof(ULONG
);
597 /* add space for the data */
598 Descriptor
.DataLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
* sizeof(KSPCACHE_MEDIUM
);
601 /* now allocate the space */
602 Descriptor
.FilterData
= (PUCHAR
)AllocateItem(NonPagedPool
, Descriptor
.DataLength
+ Descriptor
.FilterLength
);
603 if (!Descriptor
.FilterData
)
606 return STATUS_INSUFFICIENT_RESOURCES
;
609 /* initialize data cache */
610 Descriptor
.DataCache
= (PUCHAR
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterLength
);
612 /* setup filter header */
613 FilterHeader
= (PKSPCACHE_FILTER_HEADER
)Descriptor
.FilterData
;
615 FilterHeader
->dwVersion
= 2;
616 FilterHeader
->dwMerit
= MERIT_DO_NOT_USE
;
617 FilterHeader
->dwUnused
= 0;
618 FilterHeader
->dwPins
= FilterDescriptor
->PinDescriptorsCount
;
620 Descriptor
.FilterOffset
= sizeof(KSPCACHE_FILTER_HEADER
);
622 /* write pin headers */
623 for(Index
= 0; Index
< FilterDescriptor
->PinDescriptorsCount
; Index
++)
625 /* get offset to pin */
626 PinHeader
= (PKSPCACHE_PIN_HEADER
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterOffset
);
628 /* write pin header */
629 PinHeader
->Signature
= 0x33697030 + Index
;
630 PinHeader
->Flags
= 0;
631 PinHeader
->Instances
= FilterDescriptor
->PinDescriptors
[Index
].InstancesPossible
;
632 if (PinHeader
->Instances
> 1)
633 PinHeader
->Flags
|= REG_PINFLAG_B_MANY
;
636 PinHeader
->MediaTypes
= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
;
637 PinHeader
->Mediums
= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
;
638 PinHeader
->Category
= (FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Category
? TRUE
: FALSE
);
640 Descriptor
.FilterOffset
+= sizeof(KSPCACHE_PIN_HEADER
);
642 if (PinHeader
->Category
)
644 /* get category offset */
645 PULONG Category
= (PULONG
)(PinHeader
+ 1);
647 /* write category offset */
648 *Category
= KspCacheAddData(&Descriptor
, FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Category
, sizeof(CLSID
));
651 Descriptor
.FilterOffset
+= sizeof(ULONG
);
655 for(SubIndex
= 0; SubIndex
< FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
; SubIndex
++)
657 /* get datarange offset */
658 PKSPCACHE_DATARANGE DataRange
= (PKSPCACHE_DATARANGE
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterOffset
);
660 /* initialize data range */
661 DataRange
->Signature
= 0x33797430 + SubIndex
;
662 DataRange
->dwUnused
= 0;
663 DataRange
->OffsetMajor
= KspCacheAddData(&Descriptor
, &FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRanges
[SubIndex
]->MajorFormat
, sizeof(CLSID
));
664 DataRange
->OffsetMinor
= KspCacheAddData(&Descriptor
, &FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRanges
[SubIndex
]->SubFormat
, sizeof(CLSID
));
667 Descriptor
.FilterOffset
+= sizeof(KSPCACHE_DATARANGE
);
671 for(SubIndex
= 0; SubIndex
< FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
; SubIndex
++)
673 KSPCACHE_MEDIUM Medium
;
676 /* get pin medium offset */
677 MediumOffset
= (PULONG
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterOffset
);
679 /* copy medium guid */
680 RtlMoveMemory(&Medium
.Medium
, &FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Mediums
[SubIndex
].Set
, sizeof(GUID
));
681 Medium
.dw1
= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Mediums
[SubIndex
].Id
; /* FIXME verify */
684 *MediumOffset
= KspCacheAddData(&Descriptor
, &Medium
, sizeof(KSPCACHE_MEDIUM
));
687 Descriptor
.FilterOffset
+= sizeof(ULONG
);
692 ASSERT(Descriptor
.FilterOffset
== Descriptor
.FilterLength
);
693 ASSERT(Descriptor
.DataOffset
<= Descriptor
.DataLength
);
696 /* now go through all entries and update 'FilterData' key */
697 for(Index
= 0; Index
< FilterDescriptor
->CategoriesCount
; Index
++)
699 /* get first entry */
700 Entry
= Factory
->SymbolicLinkList
.Flink
;
702 /* set status to not found */
704 /* loop list until the the current category is found */
705 while(Entry
!= &Factory
->SymbolicLinkList
)
707 /* fetch symbolic link entry */
708 SymEntry
= (PSYMBOLIC_LINK_ENTRY
)CONTAINING_RECORD(Entry
, SYMBOLIC_LINK_ENTRY
, Entry
);
710 if (IsEqualGUIDAligned(&SymEntry
->DeviceInterfaceClass
, &FilterDescriptor
->Categories
[Index
]))
717 /* move to next entry */
718 Entry
= Entry
->Flink
;
723 /* filter category is not present */
724 Status
= STATUS_INVALID_PARAMETER
;
728 /* now open device interface */
729 Status
= IoOpenDeviceInterfaceRegistryKey(&SymEntry
->SymbolicLink
, KEY_WRITE
, &hKey
);
730 if (!NT_SUCCESS(Status
))
732 /* failed to open interface key */
736 /* update filterdata key */
737 Status
= ZwSetValueKey(hKey
, &FilterData
, 0, REG_BINARY
, Descriptor
.FilterData
, Descriptor
.FilterLength
+ Descriptor
.DataOffset
);
739 /* close filterdata key */
742 if (!NT_SUCCESS(Status
))
744 /* failed to set key value */
748 /* free filter data */
749 FreeItem(Descriptor
.FilterData
);