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
14 KSBASIC_HEADER Header
;
15 KSFILTERFACTORY FilterFactory
;
18 PKSIDEVICE_HEADER DeviceHeader
;
19 PFNKSFILTERFACTORYPOWER SleepCallback
;
20 PFNKSFILTERFACTORYPOWER WakeCallback
;
22 LIST_ENTRY SymbolicLinkList
;
25 }IKsFilterFactoryImpl
;
29 IKsFilterFactory_ItemFreeCb(
30 IN PKSOBJECT_CREATE_ITEM CreateItem
)
32 /* callback when create item is freed in the device header */
33 IKsFilterFactory
* iface
= (IKsFilterFactory
*)CONTAINING_RECORD(CreateItem
->Context
, IKsFilterFactoryImpl
, FilterFactory
);
35 iface
->lpVtbl
->Release(iface
);
40 IKsFilterFactory_Create(
41 IN PDEVICE_OBJECT DeviceObject
,
44 PKSOBJECT_CREATE_ITEM CreateItem
;
45 IKsFilterFactoryImpl
* Factory
;
46 IKsFilterFactory
* iface
;
49 /* access the create item */
50 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
53 DPRINT1("IKsFilterFactory_Create no CreateItem\n");
54 return STATUS_UNSUCCESSFUL
;
57 /* get filter factory interface */
58 Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(CreateItem
->Context
, IKsFilterFactoryImpl
, FilterFactory
);
61 iface
= (IKsFilterFactory
*)&Factory
->Header
.OuterUnknown
;
63 /* create a filter instance */
64 Status
= KspCreateFilter(DeviceObject
, Irp
, iface
);
66 DPRINT("KspCreateFilter Status %x\n", Status
);
68 if (Status
!= STATUS_PENDING
)
70 Irp
->IoStatus
.Information
= 0;
71 Irp
->IoStatus
.Status
= Status
;
72 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
81 IKsFilterFactory_fnQueryInterface(
82 IKsFilterFactory
* iface
,
88 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
90 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
92 *Output
= &This
->Header
.OuterUnknown
;
93 _InterlockedIncrement(&This
->ref
);
94 return STATUS_SUCCESS
;
97 if (This
->Header
.ClientAggregate
)
99 /* using client aggregate */
100 Status
= This
->Header
.ClientAggregate
->lpVtbl
->QueryInterface(This
->Header
.ClientAggregate
, refiid
, Output
);
102 if (NT_SUCCESS(Status
))
104 /* client aggregate supports interface */
109 DPRINT("IKsFilterFactory_fnQueryInterface no interface\n");
110 return STATUS_NOT_SUPPORTED
;
115 IKsFilterFactory_fnAddRef(
116 IKsFilterFactory
* iface
)
118 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
120 return InterlockedIncrement(&This
->ref
);
125 IKsFilterFactory_fnRelease(
126 IKsFilterFactory
* iface
)
128 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
130 InterlockedDecrement(&This
->ref
);
134 if (!IsListEmpty(&This
->SymbolicLinkList
))
136 /* disable device interfaces */
137 KspSetDeviceInterfacesState(&This
->SymbolicLinkList
, FALSE
);
138 /* free device interface strings */
139 KspFreeDeviceInterfaces(&This
->SymbolicLinkList
);
145 /* Return new reference count */
151 IKsFilterFactory_fnGetStruct(
152 IKsFilterFactory
* iface
)
154 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
156 return &This
->FilterFactory
;
161 IKsFilterFactory_fnSetDeviceClassesState(
162 IKsFilterFactory
* iface
,
165 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
167 return KspSetDeviceInterfacesState(&This
->SymbolicLinkList
, Enable
);
171 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(
172 IKsFilterFactoryImpl
* This
,
173 PKSIDEVICE_HEADER DeviceHeader
)
175 PKSBASIC_HEADER BasicHeader
;
176 PKSFILTERFACTORY FilterFactory
;
178 if (DeviceHeader
->BasicHeader
.FirstChild
.FilterFactory
== NULL
)
180 /* first attached filter factory */
181 DeviceHeader
->BasicHeader
.FirstChild
.FilterFactory
= &This
->FilterFactory
;
185 /* set to first entry */
186 FilterFactory
= DeviceHeader
->BasicHeader
.FirstChild
.FilterFactory
;
190 /* get basic header */
191 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)FilterFactory
- sizeof(KSBASIC_HEADER
));
193 ASSERT(BasicHeader
->Type
== KsObjectTypeFilterFactory
);
195 if (BasicHeader
->Next
.FilterFactory
)
197 /* iterate to next filter factory */
198 FilterFactory
= BasicHeader
->Next
.FilterFactory
;
202 /* found last entry */
205 }while(FilterFactory
);
207 /* attach filter factory */
208 BasicHeader
->Next
.FilterFactory
= &This
->FilterFactory
;
213 IKsFilterFactory_fnInitialize(
214 IKsFilterFactory
* iface
,
215 IN PDEVICE_OBJECT DeviceObject
,
216 IN
const KSFILTER_DESCRIPTOR
*Descriptor
,
217 IN PWSTR RefString OPTIONAL
,
218 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
219 IN ULONG CreateItemFlags
,
220 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL
,
221 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL
,
222 OUT PKSFILTERFACTORY
*FilterFactory OPTIONAL
)
224 UNICODE_STRING ReferenceString
;
226 PDEVICE_EXTENSION DeviceExtension
;
227 KSOBJECT_CREATE_ITEM CreateItem
;
228 BOOL FreeString
= FALSE
;
229 IKsDevice
* KsDevice
;
231 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, Header
.OuterUnknown
);
233 /* get device extension */
234 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
236 /* initialize filterfactory */
237 This
->SleepCallback
= SleepCallback
;
238 This
->WakeCallback
= WakeCallback
;
239 This
->FilterFactory
.FilterDescriptor
= Descriptor
;
240 This
->Header
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
241 This
->Header
.Type
= KsObjectTypeFilterFactory
;
242 This
->Header
.Parent
.KsDevice
= &DeviceExtension
->DeviceHeader
->KsDevice
;
243 This
->DeviceHeader
= DeviceExtension
->DeviceHeader
;
245 /* initialize filter factory control mutex */
246 This
->Header
.ControlMutex
= &This
->ControlMutex
;
247 KeInitializeMutex(This
->Header
.ControlMutex
, 0);
250 InitializeListHead(&This
->Header
.EventList
);
251 KeInitializeSpinLock(&This
->Header
.EventListLock
);
253 InitializeListHead(&This
->SymbolicLinkList
);
255 /* does the device use a reference string */
256 if (RefString
|| !Descriptor
->ReferenceGuid
)
258 /* use device reference string */
259 RtlInitUnicodeString(&ReferenceString
, RefString
);
263 /* create reference string from descriptor guid */
264 Status
= RtlStringFromGUID(Descriptor
->ReferenceGuid
, &ReferenceString
);
266 /* check for success */
267 if (!NT_SUCCESS(Status
))
276 DPRINT("IKsFilterFactory_fnInitialize CategoriesCount %u ReferenceString '%S'\n", Descriptor
->CategoriesCount
,ReferenceString
.Buffer
);
278 /* now register the device interface */
279 Status
= KspRegisterDeviceInterfaces(DeviceExtension
->DeviceHeader
->KsDevice
.PhysicalDeviceObject
,
280 Descriptor
->CategoriesCount
,
281 Descriptor
->Categories
,
283 &This
->SymbolicLinkList
);
284 /* check for success */
285 if (!NT_SUCCESS(Status
))
287 DPRINT1("KspRegisterDeviceInterfaces failed with %x\n", Status
);
291 /* free unicode string */
292 RtlFreeUnicodeString(&ReferenceString
);
298 /* now setup the create item */
299 CreateItem
.SecurityDescriptor
= SecurityDescriptor
;
300 CreateItem
.Flags
= CreateItemFlags
;
301 CreateItem
.Create
= IKsFilterFactory_Create
;
302 CreateItem
.Context
= (PVOID
)&This
->FilterFactory
;
303 RtlInitUnicodeString(&CreateItem
.ObjectClass
, ReferenceString
.Buffer
);
305 /* insert create item to device header */
306 Status
= KsAllocateObjectCreateItem((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
, &CreateItem
, TRUE
, IKsFilterFactory_ItemFreeCb
);
310 /* free unicode string */
311 RtlFreeUnicodeString(&ReferenceString
);
316 /* return filterfactory */
317 *FilterFactory
= &This
->FilterFactory
;
319 /* create a object bag for the filter factory */
320 This
->FilterFactory
.Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
321 if (This
->FilterFactory
.Bag
)
323 /* initialize object bag */
324 KsDevice
= (IKsDevice
*)&DeviceExtension
->DeviceHeader
->BasicHeader
.OuterUnknown
;
325 KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, (PKSIOBJECT_BAG
)This
->FilterFactory
.Bag
, NULL
);
329 /* attach filterfactory to device header */
330 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(This
, DeviceExtension
->DeviceHeader
);
336 static IKsFilterFactoryVtbl vt_IKsFilterFactoryVtbl
=
338 IKsFilterFactory_fnQueryInterface
,
339 IKsFilterFactory_fnAddRef
,
340 IKsFilterFactory_fnRelease
,
341 IKsFilterFactory_fnGetStruct
,
342 IKsFilterFactory_fnSetDeviceClassesState
,
343 IKsFilterFactory_fnInitialize
349 KspCreateFilterFactory(
350 IN PDEVICE_OBJECT DeviceObject
,
351 IN
const KSFILTER_DESCRIPTOR
*Descriptor
,
352 IN PWSTR RefString OPTIONAL
,
353 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
354 IN ULONG CreateItemFlags
,
355 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL
,
356 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL
,
357 OUT PKSFILTERFACTORY
*FilterFactory OPTIONAL
)
359 IKsFilterFactoryImpl
* This
;
360 IKsFilterFactory
* Filter
;
363 DPRINT("KsCreateFilterFactory\n");
365 /* Lets allocate a filterfactory */
366 This
= AllocateItem(NonPagedPool
, sizeof(IKsFilterFactoryImpl
));
369 /* not enough memory */
370 return STATUS_INSUFFICIENT_RESOURCES
;
373 /* initialize struct */
375 This
->Header
.OuterUnknown
= (PUNKNOWN
)&vt_IKsFilterFactoryVtbl
;
377 /* map to com object */
378 Filter
= (IKsFilterFactory
*)&This
->Header
.OuterUnknown
;
380 /* initialize filter */
381 Status
= Filter
->lpVtbl
->Initialize(Filter
, DeviceObject
, Descriptor
, RefString
, SecurityDescriptor
, CreateItemFlags
, SleepCallback
, WakeCallback
, FilterFactory
);
383 if (!NT_SUCCESS(Status
))
385 /* destroy filterfactory */
386 Filter
->lpVtbl
->Release(Filter
);
390 DPRINT("KsCreateFilterFactory %x\n", Status
);
392 ASSERT(Status
== STATUS_SUCCESS
);
403 KsCreateFilterFactory(
404 IN PDEVICE_OBJECT DeviceObject
,
405 IN
const KSFILTER_DESCRIPTOR
*Descriptor
,
406 IN PWSTR RefString OPTIONAL
,
407 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
408 IN ULONG CreateItemFlags
,
409 IN PFNKSFILTERFACTORYPOWER SleepCallback OPTIONAL
,
410 IN PFNKSFILTERFACTORYPOWER WakeCallback OPTIONAL
,
411 OUT PKSFILTERFACTORY
*FilterFactory OPTIONAL
)
413 return KspCreateFilterFactory(DeviceObject
, Descriptor
, RefString
, SecurityDescriptor
, CreateItemFlags
, SleepCallback
, WakeCallback
, FilterFactory
);
423 KsFilterFactorySetDeviceClassesState(
424 IN PKSFILTERFACTORY FilterFactory
,
427 IKsFilterFactory
* Factory
;
428 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
430 Factory
= (IKsFilterFactory
*)&This
->Header
.OuterUnknown
;
431 return Factory
->lpVtbl
->SetDeviceClassesState(Factory
, NewState
);
441 KsFilterFactoryGetSymbolicLink(
442 IN PKSFILTERFACTORY FilterFactory
)
444 PSYMBOLIC_LINK_ENTRY LinkEntry
;
445 IKsFilterFactoryImpl
* Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
447 if (IsListEmpty(&Factory
->SymbolicLinkList
))
449 /* device has not registered any interfaces */
453 /* get first entry */
454 LinkEntry
= (PSYMBOLIC_LINK_ENTRY
)CONTAINING_RECORD(Factory
->SymbolicLinkList
.Flink
, SYMBOLIC_LINK_ENTRY
, Entry
);
456 /* return first link */
457 return &LinkEntry
->SymbolicLink
;
466 KsFilterFactoryAddCreateItem(
467 IN PKSFILTERFACTORY FilterFactory
,
469 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
470 IN ULONG CreateItemFlags
)
472 KSOBJECT_CREATE_ITEM CreateItem
;
474 IKsFilterFactoryImpl
* Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
476 /* initialize create item */
477 CreateItem
.Context
= (PVOID
)&Factory
->FilterFactory
;
478 CreateItem
.Create
= IKsFilterFactory_Create
;
479 CreateItem
.Flags
= CreateItemFlags
;
480 CreateItem
.SecurityDescriptor
= SecurityDescriptor
;
481 RtlInitUnicodeString(&CreateItem
.ObjectClass
, RefString
);
483 /* insert create item to device header */
484 return KsAllocateObjectCreateItem((KSDEVICE_HEADER
)Factory
->DeviceHeader
, &CreateItem
, TRUE
, IKsFilterFactory_ItemFreeCb
);
489 PKSPCACHE_DESCRIPTOR Descriptor
,
495 for(Index
= 0; Index
< Descriptor
->DataOffset
; Index
++)
497 if (RtlCompareMemory(Descriptor
->DataCache
, Data
, Length
) == Length
)
499 if (Index
+ Length
> Descriptor
->DataOffset
)
501 /* adjust used space */
502 Descriptor
->DataOffset
= Index
+ Length
;
503 /* return absolute offset */
504 return Descriptor
->DataLength
+ Index
;
510 ASSERT(Descriptor
->DataOffset
+ Length
< Descriptor
->DataLength
);
512 /* copy to data blob */
513 RtlMoveMemory((Descriptor
->DataCache
+ Descriptor
->DataOffset
), Data
, Length
);
516 Index
= Descriptor
->DataOffset
;
518 /* adjust used space */
519 Descriptor
->DataOffset
+= Length
;
521 /* return absolute offset */
522 return Descriptor
->DataLength
+ Index
;
531 KsFilterFactoryUpdateCacheData(
532 IN PKSFILTERFACTORY FilterFactory
,
533 IN
const KSFILTER_DESCRIPTOR
* FilterDescriptor OPTIONAL
)
535 KSPCACHE_DESCRIPTOR Descriptor
;
536 PKSPCACHE_FILTER_HEADER FilterHeader
;
537 UNICODE_STRING FilterData
= RTL_CONSTANT_STRING(L
"FilterData");
538 PKSPCACHE_PIN_HEADER PinHeader
;
539 ULONG Index
, SubIndex
;
541 PSYMBOLIC_LINK_ENTRY SymEntry
;
544 NTSTATUS Status
= STATUS_SUCCESS
;
546 IKsFilterFactoryImpl
* Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
548 DPRINT("KsFilterFactoryUpdateCacheData %p\n", FilterDescriptor
);
550 if (!FilterDescriptor
)
551 FilterDescriptor
= Factory
->FilterFactory
.FilterDescriptor
;
553 ASSERT(FilterDescriptor
);
555 /* initialize cache descriptor */
556 RtlZeroMemory(&Descriptor
, sizeof(KSPCACHE_DESCRIPTOR
));
558 /* calculate filter data size */
559 Descriptor
.FilterLength
= sizeof(KSPCACHE_FILTER_HEADER
);
561 /* FIXME support variable size pin descriptors */
562 ASSERT(FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
564 for(Index
= 0; Index
< FilterDescriptor
->PinDescriptorsCount
; Index
++)
566 /* add filter descriptor */
567 Descriptor
.FilterLength
+= sizeof(KSPCACHE_PIN_HEADER
);
569 if (FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Category
)
571 /* add extra ULONG for offset to category */
572 Descriptor
.FilterLength
+= sizeof(ULONG
);
574 /* add size for clsid */
575 Descriptor
.DataLength
+= sizeof(CLSID
);
578 /* add space for formats */
579 Descriptor
.FilterLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
* sizeof(KSPCACHE_DATARANGE
);
581 /* add space for MajorFormat / MinorFormat */
582 Descriptor
.DataLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
* sizeof(CLSID
) * 2;
584 /* add space for mediums */
585 Descriptor
.FilterLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
* sizeof(ULONG
);
587 /* add space for the data */
588 Descriptor
.DataLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
* sizeof(KSPCACHE_MEDIUM
);
591 /* now allocate the space */
592 Descriptor
.FilterData
= (PUCHAR
)AllocateItem(NonPagedPool
, Descriptor
.DataLength
+ Descriptor
.FilterLength
);
593 if (!Descriptor
.FilterData
)
596 return STATUS_INSUFFICIENT_RESOURCES
;
599 /* initialize data cache */
600 Descriptor
.DataCache
= (PUCHAR
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterLength
);
602 /* setup filter header */
603 FilterHeader
= (PKSPCACHE_FILTER_HEADER
)Descriptor
.FilterData
;
605 FilterHeader
->dwVersion
= 2;
606 FilterHeader
->dwMerit
= MERIT_DO_NOT_USE
;
607 FilterHeader
->dwUnused
= 0;
608 FilterHeader
->dwPins
= FilterDescriptor
->PinDescriptorsCount
;
610 Descriptor
.FilterOffset
= sizeof(KSPCACHE_FILTER_HEADER
);
612 /* write pin headers */
613 for(Index
= 0; Index
< FilterDescriptor
->PinDescriptorsCount
; Index
++)
615 /* get offset to pin */
616 PinHeader
= (PKSPCACHE_PIN_HEADER
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterOffset
);
618 /* write pin header */
619 PinHeader
->Signature
= 0x33697030 + Index
;
620 PinHeader
->Flags
= 0;
621 PinHeader
->Instances
= FilterDescriptor
->PinDescriptors
[Index
].InstancesPossible
;
622 if (PinHeader
->Instances
> 1)
623 PinHeader
->Flags
|= REG_PINFLAG_B_MANY
;
626 PinHeader
->MediaTypes
= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
;
627 PinHeader
->Mediums
= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
;
628 PinHeader
->Category
= (FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Category
? TRUE
: FALSE
);
630 Descriptor
.FilterOffset
+= sizeof(KSPCACHE_PIN_HEADER
);
632 if (PinHeader
->Category
)
634 /* get category offset */
635 PULONG Category
= (PULONG
)(PinHeader
+ 1);
637 /* write category offset */
638 *Category
= KspCacheAddData(&Descriptor
, FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Category
, sizeof(CLSID
));
641 Descriptor
.FilterOffset
+= sizeof(ULONG
);
645 for(SubIndex
= 0; SubIndex
< FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
; SubIndex
++)
647 /* get datarange offset */
648 PKSPCACHE_DATARANGE DataRange
= (PKSPCACHE_DATARANGE
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterOffset
);
650 /* initialize data range */
651 DataRange
->Signature
= 0x33797430 + SubIndex
;
652 DataRange
->dwUnused
= 0;
653 DataRange
->OffsetMajor
= KspCacheAddData(&Descriptor
, &FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRanges
[SubIndex
]->MajorFormat
, sizeof(CLSID
));
654 DataRange
->OffsetMinor
= KspCacheAddData(&Descriptor
, &FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRanges
[SubIndex
]->SubFormat
, sizeof(CLSID
));
657 Descriptor
.FilterOffset
+= sizeof(KSPCACHE_DATARANGE
);
661 for(SubIndex
= 0; SubIndex
< FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
; SubIndex
++)
663 KSPCACHE_MEDIUM Medium
;
666 /* get pin medium offset */
667 MediumOffset
= (PULONG
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterOffset
);
669 /* copy medium guid */
670 RtlMoveMemory(&Medium
.Medium
, &FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Mediums
[SubIndex
].Set
, sizeof(GUID
));
671 Medium
.dw1
= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Mediums
[SubIndex
].Id
; /* FIXME verify */
674 *MediumOffset
= KspCacheAddData(&Descriptor
, &Medium
, sizeof(KSPCACHE_MEDIUM
));
677 Descriptor
.FilterOffset
+= sizeof(ULONG
);
682 ASSERT(Descriptor
.FilterOffset
== Descriptor
.FilterLength
);
683 ASSERT(Descriptor
.DataOffset
<= Descriptor
.DataLength
);
686 /* now go through all entries and update 'FilterData' key */
687 for(Index
= 0; Index
< FilterDescriptor
->CategoriesCount
; Index
++)
689 /* get first entry */
690 Entry
= Factory
->SymbolicLinkList
.Flink
;
692 /* set status to not found */
694 /* loop list until the the current category is found */
695 while(Entry
!= &Factory
->SymbolicLinkList
)
697 /* fetch symbolic link entry */
698 SymEntry
= (PSYMBOLIC_LINK_ENTRY
)CONTAINING_RECORD(Entry
, SYMBOLIC_LINK_ENTRY
, Entry
);
700 if (IsEqualGUIDAligned(&SymEntry
->DeviceInterfaceClass
, &FilterDescriptor
->Categories
[Index
]))
707 /* move to next entry */
708 Entry
= Entry
->Flink
;
713 /* filter category is not present */
714 Status
= STATUS_INVALID_PARAMETER
;
718 /* now open device interface */
719 Status
= IoOpenDeviceInterfaceRegistryKey(&SymEntry
->SymbolicLink
, KEY_WRITE
, &hKey
);
720 if (!NT_SUCCESS(Status
))
722 /* failed to open interface key */
726 /* update filterdata key */
727 Status
= ZwSetValueKey(hKey
, &FilterData
, 0, REG_BINARY
, Descriptor
.FilterData
, Descriptor
.FilterLength
+ Descriptor
.DataOffset
);
729 /* close filterdata key */
732 if (!NT_SUCCESS(Status
))
734 /* failed to set key value */
738 /* free filter data */
739 FreeItem(Descriptor
.FilterData
);