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
;
17 IKsFilterFactoryVtbl
*lpVtbl
;
19 PKSIDEVICE_HEADER DeviceHeader
;
20 PFNKSFILTERFACTORYPOWER SleepCallback
;
21 PFNKSFILTERFACTORYPOWER WakeCallback
;
23 LIST_ENTRY SymbolicLinkList
;
26 }IKsFilterFactoryImpl
;
30 IKsFilterFactory_ItemFreeCb(
31 IN PKSOBJECT_CREATE_ITEM CreateItem
)
33 /* callback when create item is freed in the device header */
34 IKsFilterFactory
* iface
= (IKsFilterFactory
*)CONTAINING_RECORD(CreateItem
->Context
, IKsFilterFactoryImpl
, FilterFactory
);
36 iface
->lpVtbl
->Release(iface
);
41 IKsFilterFactory_Create(
42 IN PDEVICE_OBJECT DeviceObject
,
45 PKSOBJECT_CREATE_ITEM CreateItem
;
46 IKsFilterFactoryImpl
* Factory
;
47 IKsFilterFactory
* iface
;
50 /* access the create item */
51 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
54 DPRINT1("IKsFilterFactory_Create no CreateItem\n");
55 return STATUS_UNSUCCESSFUL
;
58 /* get filter factory interface */
59 Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(CreateItem
->Context
, IKsFilterFactoryImpl
, FilterFactory
);
62 iface
= (IKsFilterFactory
*)&Factory
->lpVtbl
;
64 /* create a filter instance */
65 Status
= KspCreateFilter(DeviceObject
, Irp
, iface
);
67 DPRINT("KspCreateFilter Status %x\n", Status
);
69 if (Status
!= STATUS_PENDING
)
71 Irp
->IoStatus
.Information
= 0;
72 Irp
->IoStatus
.Status
= Status
;
73 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
82 IKsFilterFactory_fnQueryInterface(
83 IKsFilterFactory
* iface
,
87 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, lpVtbl
);
89 if (IsEqualGUIDAligned(refiid
, &IID_IUnknown
))
91 *Output
= &This
->lpVtbl
;
92 _InterlockedIncrement(&This
->ref
);
93 return STATUS_SUCCESS
;
95 return STATUS_UNSUCCESSFUL
;
100 IKsFilterFactory_fnAddRef(
101 IKsFilterFactory
* iface
)
103 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, lpVtbl
);
105 return InterlockedIncrement(&This
->ref
);
110 IKsFilterFactory_fnRelease(
111 IKsFilterFactory
* iface
)
113 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, lpVtbl
);
115 InterlockedDecrement(&This
->ref
);
119 if (!IsListEmpty(&This
->SymbolicLinkList
))
121 /* disable device interfaces */
122 KspSetDeviceInterfacesState(&This
->SymbolicLinkList
, FALSE
);
123 /* free device interface strings */
124 KspFreeDeviceInterfaces(&This
->SymbolicLinkList
);
130 /* Return new reference count */
136 IKsFilterFactory_fnGetStruct(
137 IKsFilterFactory
* iface
)
139 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, lpVtbl
);
141 return &This
->FilterFactory
;
146 IKsFilterFactory_fnSetDeviceClassesState(
147 IKsFilterFactory
* iface
,
150 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, lpVtbl
);
152 return KspSetDeviceInterfacesState(&This
->SymbolicLinkList
, Enable
);
156 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(
157 IKsFilterFactoryImpl
* This
,
158 PKSIDEVICE_HEADER DeviceHeader
)
160 PKSBASIC_HEADER BasicHeader
;
161 PKSFILTERFACTORY FilterFactory
;
163 if (DeviceHeader
->BasicHeader
.FirstChild
.FilterFactory
== NULL
)
165 /* first attached filter factory */
166 DeviceHeader
->BasicHeader
.FirstChild
.FilterFactory
= &This
->FilterFactory
;
170 /* set to first entry */
171 FilterFactory
= DeviceHeader
->BasicHeader
.FirstChild
.FilterFactory
;
175 /* get basic header */
176 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)FilterFactory
- sizeof(KSBASIC_HEADER
));
178 ASSERT(BasicHeader
->Type
== KsObjectTypeFilterFactory
);
180 if (BasicHeader
->Next
.FilterFactory
)
182 /* iterate to next filter factory */
183 FilterFactory
= BasicHeader
->Next
.FilterFactory
;
187 /* found last entry */
190 }while(FilterFactory
);
192 /* attach filter factory */
193 BasicHeader
->Next
.FilterFactory
= &This
->FilterFactory
;
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
)
209 UNICODE_STRING ReferenceString
;
211 PDEVICE_EXTENSION DeviceExtension
;
212 KSOBJECT_CREATE_ITEM CreateItem
;
213 BOOL FreeString
= FALSE
;
214 IKsDevice
* KsDevice
;
216 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(iface
, IKsFilterFactoryImpl
, lpVtbl
);
218 /* get device extension */
219 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
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
;
230 /* initialize filter factory control mutex */
231 This
->Header
.ControlMutex
= &This
->ControlMutex
;
232 KeInitializeMutex(This
->Header
.ControlMutex
, 0);
235 InitializeListHead(&This
->Header
.EventList
);
236 KeInitializeSpinLock(&This
->Header
.EventListLock
);
238 InitializeListHead(&This
->SymbolicLinkList
);
240 /* does the device use a reference string */
241 if (RefString
|| !Descriptor
->ReferenceGuid
)
243 /* use device reference string */
244 RtlInitUnicodeString(&ReferenceString
, RefString
);
248 /* create reference string from descriptor guid */
249 Status
= RtlStringFromGUID(Descriptor
->ReferenceGuid
, &ReferenceString
);
251 /* check for success */
252 if (!NT_SUCCESS(Status
))
261 DPRINT("IKsFilterFactory_fnInitialize CategoriesCount %u ReferenceString '%S'\n", Descriptor
->CategoriesCount
,ReferenceString
.Buffer
);
263 /* now register the device interface */
264 Status
= KspRegisterDeviceInterfaces(DeviceExtension
->DeviceHeader
->KsDevice
.PhysicalDeviceObject
,
265 Descriptor
->CategoriesCount
,
266 Descriptor
->Categories
,
268 &This
->SymbolicLinkList
);
269 /* check for success */
270 if (!NT_SUCCESS(Status
))
272 DPRINT1("KspRegisterDeviceInterfaces failed with %x\n", Status
);
276 /* free unicode string */
277 RtlFreeUnicodeString(&ReferenceString
);
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
);
290 /* insert create item to device header */
291 Status
= KsAllocateObjectCreateItem((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
, &CreateItem
, TRUE
, IKsFilterFactory_ItemFreeCb
);
295 /* free unicode string */
296 RtlFreeUnicodeString(&ReferenceString
);
301 /* return filterfactory */
302 *FilterFactory
= &This
->FilterFactory
;
304 /* create a object bag for the filter factory */
305 This
->FilterFactory
.Bag
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_BAG
));
306 if (This
->FilterFactory
.Bag
)
308 /* initialize object bag */
309 KsDevice
= (IKsDevice
*)&DeviceExtension
->DeviceHeader
->lpVtblIKsDevice
;
310 KsDevice
->lpVtbl
->InitializeObjectBag(KsDevice
, (PKSIOBJECT_BAG
)This
->FilterFactory
.Bag
, NULL
);
314 /* attach filterfactory to device header */
315 IKsFilterFactory_AttachFilterFactoryToDeviceHeader(This
, DeviceExtension
->DeviceHeader
);
321 static IKsFilterFactoryVtbl vt_IKsFilterFactoryVtbl
=
323 IKsFilterFactory_fnQueryInterface
,
324 IKsFilterFactory_fnAddRef
,
325 IKsFilterFactory_fnRelease
,
326 IKsFilterFactory_fnGetStruct
,
327 IKsFilterFactory_fnSetDeviceClassesState
,
328 IKsFilterFactory_fnInitialize
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
)
344 IKsFilterFactoryImpl
* This
;
345 IKsFilterFactory
* Filter
;
348 DPRINT("KsCreateFilterFactory\n");
350 /* Lets allocate a filterfactory */
351 This
= AllocateItem(NonPagedPool
, sizeof(IKsFilterFactoryImpl
));
354 /* not enough memory */
355 return STATUS_INSUFFICIENT_RESOURCES
;
358 /* initialize struct */
360 This
->lpVtbl
= &vt_IKsFilterFactoryVtbl
;
362 /* map to com object */
363 Filter
= (IKsFilterFactory
*)&This
->lpVtbl
;
365 /* initialize filter */
366 Status
= Filter
->lpVtbl
->Initialize(Filter
, DeviceObject
, Descriptor
, RefString
, SecurityDescriptor
, CreateItemFlags
, SleepCallback
, WakeCallback
, FilterFactory
);
368 if (!NT_SUCCESS(Status
))
370 /* destroy filterfactory */
371 Filter
->lpVtbl
->Release(Filter
);
375 DPRINT("KsCreateFilterFactory %x\n", Status
);
377 ASSERT(Status
== STATUS_SUCCESS
);
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
)
398 return KspCreateFilterFactory(DeviceObject
, Descriptor
, RefString
, SecurityDescriptor
, CreateItemFlags
, SleepCallback
, WakeCallback
, FilterFactory
);
408 KsFilterFactorySetDeviceClassesState(
409 IN PKSFILTERFACTORY FilterFactory
,
412 IKsFilterFactory
* Factory
;
413 IKsFilterFactoryImpl
* This
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
415 Factory
= (IKsFilterFactory
*)&This
->lpVtbl
;
416 return Factory
->lpVtbl
->SetDeviceClassesState(Factory
, NewState
);
426 KsFilterFactoryGetSymbolicLink(
427 IN PKSFILTERFACTORY FilterFactory
)
429 PSYMBOLIC_LINK_ENTRY LinkEntry
;
430 IKsFilterFactoryImpl
* Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
432 if (IsListEmpty(&Factory
->SymbolicLinkList
))
434 /* device has not registered any interfaces */
438 /* get first entry */
439 LinkEntry
= (PSYMBOLIC_LINK_ENTRY
)CONTAINING_RECORD(Factory
->SymbolicLinkList
.Flink
, SYMBOLIC_LINK_ENTRY
, Entry
);
441 /* return first link */
442 return &LinkEntry
->SymbolicLink
;
451 KsFilterFactoryAddCreateItem(
452 IN PKSFILTERFACTORY FilterFactory
,
454 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
455 IN ULONG CreateItemFlags
)
457 KSOBJECT_CREATE_ITEM CreateItem
;
459 IKsFilterFactoryImpl
* Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
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
);
468 /* insert create item to device header */
469 return KsAllocateObjectCreateItem((KSDEVICE_HEADER
)Factory
->DeviceHeader
, &CreateItem
, TRUE
, IKsFilterFactory_ItemFreeCb
);
474 PKSPCACHE_DESCRIPTOR Descriptor
,
480 for(Index
= 0; Index
< Descriptor
->DataOffset
; Index
++)
482 if (RtlCompareMemory(Descriptor
->DataCache
, Data
, Length
) == Length
)
484 if (Index
+ Length
> Descriptor
->DataOffset
)
486 /* adjust used space */
487 Descriptor
->DataOffset
= Index
+ Length
;
488 /* return absolute offset */
489 return Descriptor
->DataLength
+ Index
;
495 ASSERT(Descriptor
->DataOffset
+ Length
< Descriptor
->DataLength
);
497 /* copy to data blob */
498 RtlMoveMemory((Descriptor
->DataCache
+ Descriptor
->DataOffset
), Data
, Length
);
501 Index
= Descriptor
->DataOffset
;
503 /* adjust used space */
504 Descriptor
->DataOffset
+= Length
;
506 /* return absolute offset */
507 return Descriptor
->DataLength
+ Index
;
516 KsFilterFactoryUpdateCacheData(
517 IN PKSFILTERFACTORY FilterFactory
,
518 IN
const KSFILTER_DESCRIPTOR
* FilterDescriptor OPTIONAL
)
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
;
526 PSYMBOLIC_LINK_ENTRY SymEntry
;
529 NTSTATUS Status
= STATUS_SUCCESS
;
531 IKsFilterFactoryImpl
* Factory
= (IKsFilterFactoryImpl
*)CONTAINING_RECORD(FilterFactory
, IKsFilterFactoryImpl
, FilterFactory
);
533 DPRINT("KsFilterFactoryUpdateCacheData %p\n", FilterDescriptor
);
535 if (!FilterDescriptor
)
536 FilterDescriptor
= Factory
->FilterFactory
.FilterDescriptor
;
538 ASSERT(FilterDescriptor
);
540 /* initialize cache descriptor */
541 RtlZeroMemory(&Descriptor
, sizeof(KSPCACHE_DESCRIPTOR
));
543 /* calculate filter data size */
544 Descriptor
.FilterLength
= sizeof(KSPCACHE_FILTER_HEADER
);
546 /* FIXME support variable size pin descriptors */
547 ASSERT(FilterDescriptor
->PinDescriptorSize
== sizeof(KSPIN_DESCRIPTOR_EX
));
549 for(Index
= 0; Index
< FilterDescriptor
->PinDescriptorsCount
; Index
++)
551 /* add filter descriptor */
552 Descriptor
.FilterLength
+= sizeof(KSPCACHE_PIN_HEADER
);
554 if (FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Category
)
556 /* add extra ULONG for offset to category */
557 Descriptor
.FilterLength
+= sizeof(ULONG
);
559 /* add size for clsid */
560 Descriptor
.DataLength
+= sizeof(CLSID
);
563 /* add space for formats */
564 Descriptor
.FilterLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
* sizeof(KSPCACHE_DATARANGE
);
566 /* add space for MajorFormat / MinorFormat */
567 Descriptor
.DataLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
* sizeof(CLSID
) * 2;
569 /* add space for mediums */
570 Descriptor
.FilterLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
* sizeof(ULONG
);
572 /* add space for the data */
573 Descriptor
.DataLength
+= FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
* sizeof(KSPCACHE_MEDIUM
);
576 /* now allocate the space */
577 Descriptor
.FilterData
= (PUCHAR
)AllocateItem(NonPagedPool
, Descriptor
.DataLength
+ Descriptor
.FilterLength
);
578 if (!Descriptor
.FilterData
)
581 return STATUS_INSUFFICIENT_RESOURCES
;
584 /* initialize data cache */
585 Descriptor
.DataCache
= (PUCHAR
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterLength
);
587 /* setup filter header */
588 FilterHeader
= (PKSPCACHE_FILTER_HEADER
)Descriptor
.FilterData
;
590 FilterHeader
->dwVersion
= 2;
591 FilterHeader
->dwMerit
= MERIT_DO_NOT_USE
;
592 FilterHeader
->dwUnused
= 0;
593 FilterHeader
->dwPins
= FilterDescriptor
->PinDescriptorsCount
;
595 Descriptor
.FilterOffset
= sizeof(KSPCACHE_FILTER_HEADER
);
597 /* write pin headers */
598 for(Index
= 0; Index
< FilterDescriptor
->PinDescriptorsCount
; Index
++)
600 /* get offset to pin */
601 PinHeader
= (PKSPCACHE_PIN_HEADER
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterOffset
);
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
;
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
);
615 Descriptor
.FilterOffset
+= sizeof(KSPCACHE_PIN_HEADER
);
617 if (PinHeader
->Category
)
619 /* get category offset */
620 PULONG Category
= (PULONG
)(PinHeader
+ 1);
622 /* write category offset */
623 *Category
= KspCacheAddData(&Descriptor
, FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.Category
, sizeof(CLSID
));
626 Descriptor
.FilterOffset
+= sizeof(ULONG
);
630 for(SubIndex
= 0; SubIndex
< FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.DataRangesCount
; SubIndex
++)
632 /* get datarange offset */
633 PKSPCACHE_DATARANGE DataRange
= (PKSPCACHE_DATARANGE
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterOffset
);
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
));
642 Descriptor
.FilterOffset
+= sizeof(KSPCACHE_DATARANGE
);
646 for(SubIndex
= 0; SubIndex
< FilterDescriptor
->PinDescriptors
[Index
].PinDescriptor
.MediumsCount
; SubIndex
++)
648 KSPCACHE_MEDIUM Medium
;
651 /* get pin medium offset */
652 MediumOffset
= (PULONG
)((ULONG_PTR
)Descriptor
.FilterData
+ Descriptor
.FilterOffset
);
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 */
659 *MediumOffset
= KspCacheAddData(&Descriptor
, &Medium
, sizeof(KSPCACHE_MEDIUM
));
662 Descriptor
.FilterOffset
+= sizeof(ULONG
);
667 ASSERT(Descriptor
.FilterOffset
== Descriptor
.FilterLength
);
668 ASSERT(Descriptor
.DataOffset
<= Descriptor
.DataLength
);
671 /* now go through all entries and update 'FilterData' key */
672 for(Index
= 0; Index
< FilterDescriptor
->CategoriesCount
; Index
++)
674 /* get first entry */
675 Entry
= Factory
->SymbolicLinkList
.Flink
;
677 /* set status to not found */
679 /* loop list until the the current category is found */
680 while(Entry
!= &Factory
->SymbolicLinkList
)
682 /* fetch symbolic link entry */
683 SymEntry
= (PSYMBOLIC_LINK_ENTRY
)CONTAINING_RECORD(Entry
, SYMBOLIC_LINK_ENTRY
, Entry
);
685 if (IsEqualGUIDAligned(&SymEntry
->DeviceInterfaceClass
, &FilterDescriptor
->Categories
[Index
]))
692 /* move to next entry */
693 Entry
= Entry
->Flink
;
698 /* filter category is not present */
699 Status
= STATUS_INVALID_PARAMETER
;
703 /* now open device interface */
704 Status
= IoOpenDeviceInterfaceRegistryKey(&SymEntry
->SymbolicLink
, KEY_WRITE
, &hKey
);
705 if (!NT_SUCCESS(Status
))
707 /* failed to open interface key */
711 /* update filterdata key */
712 Status
= ZwSetValueKey(hKey
, &FilterData
, 0, REG_BINARY
, Descriptor
.FilterData
, Descriptor
.FilterLength
+ Descriptor
.DataOffset
);
714 /* close filterdata key */
717 if (!NT_SUCCESS(Status
))
719 /* failed to set key value */
723 /* free filter data */
724 FreeItem(Descriptor
.FilterData
);