2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/api.c
5 * PURPOSE: KS API functions
6 * PROGRAMMER: Johannes Anderwald
14 const GUID GUID_NULL
= {0x00000000L
, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
15 const GUID KSMEDIUMSETID_Standard
= {0x4747B320L
, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
25 OUT KSRESET
* ResetValue
)
27 PIO_STACK_LOCATION IoStack
;
29 NTSTATUS Status
= STATUS_SUCCESS
;
31 /* get current irp stack */
32 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
34 /* check if there is reset value provided */
35 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSRESET
))
36 return STATUS_INVALID_PARAMETER
;
38 if (Irp
->RequestorMode
== UserMode
)
40 /* need to probe the buffer */
43 ProbeForRead(IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, sizeof(KSRESET
), sizeof(UCHAR
));
44 Value
= (KSRESET
*)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
47 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
49 /* Exception, get the error code */
50 Status
= _SEH2_GetExceptionCode();
56 Value
= (KSRESET
*)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
69 KsAcquireDeviceSecurityLock(
70 IN KSDEVICE_HEADER DevHeader
,
73 PKSIDEVICE_HEADER Header
= (PKSIDEVICE_HEADER
)DevHeader
;
75 KeEnterCriticalRegion();
79 ExAcquireResourceExclusiveLite(&Header
->SecurityLock
, TRUE
);
83 ExAcquireResourceSharedLite(&Header
->SecurityLock
, TRUE
);
93 KsReleaseDeviceSecurityLock(
94 IN KSDEVICE_HEADER DevHeader
)
96 PKSIDEVICE_HEADER Header
= (PKSIDEVICE_HEADER
)DevHeader
;
98 DPRINT("KsReleaseDevice\n");
100 ExReleaseResourceLite(&Header
->SecurityLock
);
101 KeLeaveCriticalRegion();
110 KsDefaultDispatchPnp(
111 IN PDEVICE_OBJECT DeviceObject
,
114 PDEVICE_EXTENSION DeviceExtension
;
115 PKSIDEVICE_HEADER DeviceHeader
;
116 PIO_STACK_LOCATION IoStack
;
117 PDEVICE_OBJECT PnpDeviceObject
;
121 /* get current irp stack */
122 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
124 /* caller wants to add the target device */
125 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
127 /* get device header */
128 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
130 /* backup PnpBaseObject */
131 PnpDeviceObject
= DeviceHeader
->PnpDeviceObject
;
134 /* backup minor function code */
135 MinorFunction
= IoStack
->MinorFunction
;
137 if(MinorFunction
== IRP_MN_REMOVE_DEVICE
)
139 /* remove the device */
140 KsFreeDeviceHeader((KSDEVICE_HEADER
)DeviceHeader
);
143 /* skip current irp stack */
144 IoSkipCurrentIrpStackLocation(Irp
);
146 /* call attached pnp device object */
147 Status
= IoCallDriver(PnpDeviceObject
, Irp
);
149 if (MinorFunction
== IRP_MN_REMOVE_DEVICE
)
152 IoDetachDevice(PnpDeviceObject
);
154 IoDeleteDevice(DeviceObject
);
166 KsDefaultDispatchPower(
167 IN PDEVICE_OBJECT DeviceObject
,
170 PDEVICE_EXTENSION DeviceExtension
;
171 PKSIDEVICE_HEADER DeviceHeader
;
172 PKSIOBJECT_HEADER ObjectHeader
;
173 //PIO_STACK_LOCATION IoStack;
174 PLIST_ENTRY ListEntry
;
177 /* get current irp stack */
178 //IoStack = IoGetCurrentIrpStackLocation(Irp);
180 /* caller wants to add the target device */
181 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
183 /* get device header */
184 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
188 /* loop our power dispatch list and call registered notification functions */
189 ListEntry
= DeviceHeader
->PowerDispatchList
.Flink
;
191 while(ListEntry
!= &DeviceHeader
->PowerDispatchList
)
193 /* get object header */
194 ObjectHeader
= (PKSIOBJECT_HEADER
)CONTAINING_RECORD(ListEntry
, KSIOBJECT_HEADER
, PowerDispatchEntry
);
196 /* does it have still a cb */
197 if (ObjectHeader
->PowerDispatch
)
199 /* call the power cb */
200 Status
= ObjectHeader
->PowerDispatch(ObjectHeader
->PowerContext
, Irp
);
201 ASSERT(NT_SUCCESS(Status
));
204 /* iterate to next entry */
205 ListEntry
= ListEntry
->Flink
;
208 /* start next power irp */
209 PoStartNextPowerIrp(Irp
);
211 /* skip current irp stack location */
212 IoSkipCurrentIrpStackLocation(Irp
);
215 Status
= PoCallDriver(DeviceHeader
->PnpDeviceObject
, Irp
);
228 IN PDEVICE_OBJECT DeviceObject
,
231 PDEVICE_EXTENSION DeviceExtension
;
232 PKSIDEVICE_HEADER DeviceHeader
;
233 //PIO_STACK_LOCATION IoStack;
236 /* get current irp stack */
237 //IoStack = IoGetCurrentIrpStackLocation(Irp);
239 /* caller wants to add the target device */
240 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
242 /* get device header */
243 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
245 /* forward the request to the PDO */
246 Status
= IoCallDriver(DeviceHeader
->PnpDeviceObject
, Irp
);
257 KsSetDevicePnpAndBaseObject(
258 IN KSDEVICE_HEADER Header
,
259 IN PDEVICE_OBJECT PnpDeviceObject
,
260 IN PDEVICE_OBJECT BaseDevice
)
262 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
264 DeviceHeader
->PnpDeviceObject
= PnpDeviceObject
;
265 DeviceHeader
->BaseDevice
= BaseDevice
;
274 KsQueryDevicePnpObject(
275 IN KSDEVICE_HEADER Header
)
277 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
279 /* return PnpDeviceObject */
280 return DeviceHeader
->PnpDeviceObject
;
290 KsQueryObjectAccessMask(
291 IN KSOBJECT_HEADER Header
)
293 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
295 /* return access mask */
296 return ObjectHeader
->AccessMask
;
306 KsRecalculateStackDepth(
307 IN KSDEVICE_HEADER Header
,
308 IN BOOLEAN ReuseStackLocation
)
321 IN KSOBJECT_HEADER Header
,
322 IN KSTARGET_STATE TargetState
)
324 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
326 /* set target state */
327 DeviceHeader
->TargetState
= TargetState
;
336 KsSetTargetDeviceObject(
337 IN KSOBJECT_HEADER Header
,
338 IN PDEVICE_OBJECT TargetDevice OPTIONAL
)
340 PDEVICE_EXTENSION DeviceExtension
;
341 PKSIDEVICE_HEADER DeviceHeader
;
342 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
344 if(ObjectHeader
->TargetDevice
)
346 /* there is already a target device set */
349 /* caller wants to remove the target device */
350 DeviceExtension
= (PDEVICE_EXTENSION
)ObjectHeader
->TargetDevice
->DeviceExtension
;
352 /* get device header */
353 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
356 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
, FALSE
);
359 RemoveEntryList(&ObjectHeader
->TargetDeviceListEntry
);
361 /* remove device pointer */
362 ObjectHeader
->TargetDevice
= NULL
;
365 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
);
370 /* no target device yet set */
373 /* caller wants to add the target device */
374 DeviceExtension
= (PDEVICE_EXTENSION
)TargetDevice
->DeviceExtension
;
376 /* get device header */
377 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
380 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
, FALSE
);
382 /* insert list entry */
383 InsertTailList(&DeviceHeader
->TargetDeviceList
, &ObjectHeader
->TargetDeviceListEntry
);
385 /* store target device */
386 ObjectHeader
->TargetDevice
= TargetDevice
;
389 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
);
402 IN KSOBJECT_HEADER Header
,
403 IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL
,
404 IN PVOID PowerContext OPTIONAL
)
406 PDEVICE_EXTENSION DeviceExtension
;
407 PKSIDEVICE_HEADER DeviceHeader
;
408 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
410 /* caller wants to add the target device */
411 DeviceExtension
= (PDEVICE_EXTENSION
)ObjectHeader
->ParentDeviceObject
->DeviceExtension
;
413 /* get device header */
414 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
417 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
, FALSE
);
421 /* add power dispatch entry */
422 InsertTailList(&DeviceHeader
->PowerDispatchList
, &ObjectHeader
->PowerDispatchEntry
);
424 /* store function and context */
425 ObjectHeader
->PowerDispatch
= PowerDispatch
;
426 ObjectHeader
->PowerContext
= PowerContext
;
430 /* remove power dispatch entry */
431 RemoveEntryList(&ObjectHeader
->PowerDispatchEntry
);
433 /* store function and context */
434 ObjectHeader
->PowerDispatch
= NULL
;
435 ObjectHeader
->PowerContext
= NULL
;
440 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
);
448 PKSOBJECT_CREATE_ITEM
450 KsQueryObjectCreateItem(
451 IN KSOBJECT_HEADER Header
)
453 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
454 return ObjectHeader
->OriginalCreateItem
;
458 KspAddCreateItemToList(
459 OUT PLIST_ENTRY ListHead
,
461 IN PKSOBJECT_CREATE_ITEM ItemsList
)
464 PCREATE_ITEM_ENTRY Entry
;
467 for(Index
= 0; Index
< ItemsCount
; Index
++)
470 Entry
= AllocateItem(NonPagedPool
, sizeof(CREATE_ITEM_ENTRY
));
474 return STATUS_INSUFFICIENT_RESOURCES
;
477 /* initialize entry */
478 InitializeListHead(&Entry
->ObjectItemList
);
479 Entry
->CreateItem
= &ItemsList
[Index
];
480 Entry
->ReferenceCount
= 0;
481 Entry
->ItemFreeCallback
= NULL
;
483 InsertTailList(ListHead
, &Entry
->Entry
);
485 return STATUS_SUCCESS
;
490 PLIST_ENTRY ListHead
)
492 PCREATE_ITEM_ENTRY Entry
;
494 while(!IsListEmpty(ListHead
))
496 /* remove create item from list */
497 Entry
= (PCREATE_ITEM_ENTRY
)CONTAINING_RECORD(RemoveHeadList(ListHead
), CREATE_ITEM_ENTRY
, Entry
);
499 /* caller shouldnt have any references */
500 //ASSERT(Entry->ReferenceCount == 0);
501 //ASSERT(IsListEmpty(&Entry->ObjectItemList));
503 /* does the creator wish notification */
504 if (Entry
->ItemFreeCallback
)
507 Entry
->ItemFreeCallback(Entry
->CreateItem
);
510 /* free create item entry */
522 KsAllocateDeviceHeader(
523 OUT KSDEVICE_HEADER
* OutHeader
,
525 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL
)
527 NTSTATUS Status
= STATUS_SUCCESS
;
528 PKSIDEVICE_HEADER Header
;
531 return STATUS_INVALID_PARAMETER
;
533 /* allocate a device header */
534 Header
= AllocateItem(PagedPool
, sizeof(KSIDEVICE_HEADER
));
536 /* check for success */
538 return STATUS_INSUFFICIENT_RESOURCES
;
540 /* clear all memory */
541 RtlZeroMemory(Header
, sizeof(KSIDEVICE_HEADER
));
543 /* initialize device mutex */
544 KeInitializeMutex(&Header
->DeviceMutex
, 0);
546 /* initialize target device list */
547 InitializeListHead(&Header
->TargetDeviceList
);
548 /* initialize power dispatch list */
549 InitializeListHead(&Header
->PowerDispatchList
);
550 /* initialize object bag lists */
551 InitializeListHead(&Header
->ObjectBags
);
553 /* initialize create item list */
554 InitializeListHead(&Header
->ItemList
);
556 /* initialize basic header */
557 Header
->BasicHeader
.Type
= KsObjectTypeDevice
;
558 Header
->BasicHeader
.KsDevice
= &Header
->KsDevice
;
559 Header
->BasicHeader
.Parent
.KsDevice
= &Header
->KsDevice
;
561 /* are there any create items provided */
562 if (ItemsCount
&& ItemsList
)
564 Status
= KspAddCreateItemToList(&Header
->ItemList
, ItemsCount
, ItemsList
);
566 if (NT_SUCCESS(Status
))
568 /* store item count */
569 Header
->ItemListCount
= ItemsCount
;
573 /* release create items */
574 KspFreeCreateItems(&Header
->ItemList
);
591 IN KSDEVICE_HEADER DevHeader
)
593 PKSIDEVICE_HEADER Header
;
595 Header
= (PKSIDEVICE_HEADER
)DevHeader
;
600 KspFreeCreateItems(&Header
->ItemList
);
610 KsAllocateObjectHeader(
611 OUT KSOBJECT_HEADER
*Header
,
613 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL
,
615 IN KSDISPATCH_TABLE
* Table
)
617 PIO_STACK_LOCATION IoStack
;
618 //PDEVICE_EXTENSION DeviceExtension;
619 //PKSIDEVICE_HEADER DeviceHeader;
620 PKSIOBJECT_HEADER ObjectHeader
;
621 //PKSOBJECT_CREATE_ITEM CreateItem;
625 return STATUS_INVALID_PARAMETER_1
;
628 return STATUS_INVALID_PARAMETER_4
;
631 return STATUS_INVALID_PARAMETER_5
;
633 /* get current stack location */
634 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
635 /* get device extension */
636 //DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
637 /* get device header */
638 //DeviceHeader = DeviceExtension->DeviceHeader;
641 ASSERT(IoStack
->FileObject
);
642 /* check for an file object */
644 /* allocate the object header */
645 ObjectHeader
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_HEADER
));
647 return STATUS_INSUFFICIENT_RESOURCES
;
649 /* initialize object header */
650 RtlZeroMemory(ObjectHeader
, sizeof(KSIOBJECT_HEADER
));
652 /* initialize create item list */
653 InitializeListHead(&ObjectHeader
->ItemList
);
655 /* get create item */
656 //CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
658 /* do we have a name */
659 if (IoStack
->FileObject
->FileName
.Buffer
)
661 /* copy object class */
662 ObjectHeader
->ObjectClass
.MaximumLength
= IoStack
->FileObject
->FileName
.MaximumLength
;
663 ObjectHeader
->ObjectClass
.Buffer
= AllocateItem(NonPagedPool
, ObjectHeader
->ObjectClass
.MaximumLength
);
664 if (!ObjectHeader
->ObjectClass
.Buffer
)
666 FreeItem(ObjectHeader
);
667 return STATUS_INSUFFICIENT_RESOURCES
;
669 RtlCopyUnicodeString(&ObjectHeader
->ObjectClass
, &IoStack
->FileObject
->FileName
);
672 /* copy dispatch table */
673 RtlCopyMemory(&ObjectHeader
->DispatchTable
, Table
, sizeof(KSDISPATCH_TABLE
));
675 /* store create items */
676 if (ItemsCount
&& ItemsList
)
678 Status
= KspAddCreateItemToList(&ObjectHeader
->ItemList
, ItemsCount
, ItemsList
);
680 if (NT_SUCCESS(Status
))
682 /* store item count */
683 ObjectHeader
->ItemListCount
= ItemsCount
;
688 KsFreeObjectHeader(ObjectHeader
);
692 /* store the object in the file object */
693 IoStack
->FileObject
->FsContext2
= ObjectHeader
;
695 /* store parent device */
696 ObjectHeader
->ParentDeviceObject
= IoGetRelatedDeviceObject(IoStack
->FileObject
);
698 /* store originating create item */
699 ObjectHeader
->OriginalCreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
701 /* FIXME store access mask see KsQueryObjectAccessMask */
702 ObjectHeader
->AccessMask
= IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
;
706 *Header
= ObjectHeader
;
708 DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader
->ObjectClass
.Buffer
, IoStack
->FileObject
, ObjectHeader
);
710 return STATUS_SUCCESS
;
723 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
) Header
;
725 DPRINT("KsFreeObjectHeader Header %p Class %wZ\n", Header
, &ObjectHeader
->ObjectClass
);
727 if (ObjectHeader
->ObjectClass
.Buffer
)
729 /* release object class buffer */
730 FreeItem(ObjectHeader
->ObjectClass
.Buffer
);
733 if (ObjectHeader
->Unknown
)
735 /* release associated object */
736 ObjectHeader
->Unknown
->lpVtbl
->Release(ObjectHeader
->Unknown
);
739 /* free create items */
740 KspFreeCreateItems(&ObjectHeader
->ItemList
);
742 /* free object header */
743 FreeItem(ObjectHeader
);
748 KspAddObjectCreateItemToList(
749 PLIST_ENTRY ListHead
,
750 IN PDRIVER_DISPATCH Create
,
752 IN PWCHAR ObjectClass
,
753 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
756 PCREATE_ITEM_ENTRY CreateEntry
;
758 /* point to first entry */
759 Entry
= ListHead
->Flink
;
761 while(Entry
!= ListHead
)
763 /* get create entry */
764 CreateEntry
= (PCREATE_ITEM_ENTRY
)CONTAINING_RECORD(Entry
, CREATE_ITEM_ENTRY
, Entry
);
765 /* if the create item has no create routine, then it is free to use */
766 if (CreateEntry
->CreateItem
->Create
== NULL
)
769 ASSERT(IsListEmpty(&CreateEntry
->ObjectItemList
));
770 ASSERT(CreateEntry
->ReferenceCount
== 0);
772 CreateEntry
->CreateItem
->Context
= Context
;
773 CreateEntry
->CreateItem
->Create
= Create
;
774 RtlInitUnicodeString(&CreateEntry
->CreateItem
->ObjectClass
, ObjectClass
);
775 CreateEntry
->CreateItem
->SecurityDescriptor
= SecurityDescriptor
;
777 return STATUS_SUCCESS
;
780 if (!wcsicmp(ObjectClass
, CreateEntry
->CreateItem
->ObjectClass
.Buffer
))
782 /* the same object class already exists */
783 return STATUS_OBJECT_NAME_COLLISION
;
786 /* iterate to next entry */
787 Entry
= Entry
->Flink
;
789 return STATUS_ALLOTTED_SPACE_EXCEEDED
;
798 KsAddObjectCreateItemToDeviceHeader(
799 IN KSDEVICE_HEADER DevHeader
,
800 IN PDRIVER_DISPATCH Create
,
802 IN PWCHAR ObjectClass
,
803 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
805 PKSIDEVICE_HEADER Header
;
808 Header
= (PKSIDEVICE_HEADER
)DevHeader
;
810 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
812 /* check if a device header has been provided */
814 return STATUS_INVALID_PARAMETER_1
;
816 /* check if a create item has been provided */
818 return STATUS_INVALID_PARAMETER_2
;
820 /* check if a object class has been provided */
822 return STATUS_INVALID_PARAMETER_4
;
824 /* let others do the work */
825 Status
= KspAddObjectCreateItemToList(&Header
->ItemList
, Create
, Context
, ObjectClass
, SecurityDescriptor
);
827 if (NT_SUCCESS(Status
))
829 /* increment create item count */
830 InterlockedIncrement(&Header
->ItemListCount
);
832 DPRINT("KsAddObjectCreateItemToDeviceHeader Status %x\n", Status
);
842 KsAddObjectCreateItemToObjectHeader(
843 IN KSOBJECT_HEADER ObjectHeader
,
844 IN PDRIVER_DISPATCH Create
,
846 IN PWCHAR ObjectClass
,
847 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
849 PKSIOBJECT_HEADER Header
;
852 Header
= (PKSIOBJECT_HEADER
)ObjectHeader
;
854 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
856 /* check if a device header has been provided */
858 return STATUS_INVALID_PARAMETER_1
;
860 /* check if a create item has been provided */
862 return STATUS_INVALID_PARAMETER_2
;
864 /* check if a object class has been provided */
866 return STATUS_INVALID_PARAMETER_4
;
869 Status
= KspAddObjectCreateItemToList(&Header
->ItemList
, Create
, Context
, ObjectClass
, SecurityDescriptor
);
871 if (NT_SUCCESS(Status
))
873 /* increment create item count */
874 InterlockedIncrement(&Header
->ItemListCount
);
886 KsAllocateObjectCreateItem(
887 IN KSDEVICE_HEADER DevHeader
,
888 IN PKSOBJECT_CREATE_ITEM CreateItem
,
889 IN BOOLEAN AllocateEntry
,
890 IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL
)
892 PCREATE_ITEM_ENTRY CreateEntry
;
893 PKSIDEVICE_HEADER Header
;
894 PKSOBJECT_CREATE_ITEM Item
;
896 Header
= (PKSIDEVICE_HEADER
)DevHeader
;
899 return STATUS_INVALID_PARAMETER_1
;
902 return STATUS_INVALID_PARAMETER_2
;
904 /* first allocate a create entry */
905 CreateEntry
= AllocateItem(NonPagedPool
, sizeof(CREATE_ITEM_ENTRY
));
907 /* check for allocation success */
910 /* not enough resources */
911 return STATUS_INSUFFICIENT_RESOURCES
;
917 /* allocate create item */
918 Item
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
));
922 FreeItem(CreateEntry
);
923 return STATUS_INSUFFICIENT_RESOURCES
;
926 /* initialize descriptor */
927 Item
->Context
= CreateItem
->Context
;
928 Item
->Create
= CreateItem
->Create
;
929 Item
->Flags
= CreateItem
->Flags
;
930 Item
->SecurityDescriptor
= CreateItem
->SecurityDescriptor
;
931 Item
->ObjectClass
.Length
= 0;
932 Item
->ObjectClass
.MaximumLength
= CreateItem
->ObjectClass
.MaximumLength
;
934 /* copy object class */
935 Item
->ObjectClass
.Buffer
= AllocateItem(NonPagedPool
, Item
->ObjectClass
.MaximumLength
);
936 if (!Item
->ObjectClass
.Buffer
)
938 /* release resources */
940 FreeItem(CreateEntry
);
942 return STATUS_INSUFFICIENT_RESOURCES
;
944 RtlCopyUnicodeString(&Item
->ObjectClass
, &CreateItem
->ObjectClass
);
948 if (ItemFreeCallback
)
950 /* callback is only accepted when the create item is copied */
951 ItemFreeCallback
= NULL
;
953 /* use passed create item */
957 /* initialize create item entry */
958 InitializeListHead(&CreateEntry
->ObjectItemList
);
959 CreateEntry
->ItemFreeCallback
= ItemFreeCallback
;
960 CreateEntry
->CreateItem
= Item
;
961 CreateEntry
->ReferenceCount
= 0;
963 /* now insert the create item entry */
964 InsertTailList(&Header
->ItemList
, &CreateEntry
->Entry
);
966 /* increment item count */
967 InterlockedIncrement(&Header
->ItemListCount
);
969 return STATUS_SUCCESS
;
973 KspObjectFreeCreateItems(
974 IN KSDEVICE_HEADER Header
,
975 IN PKSOBJECT_CREATE_ITEM CreateItem
)
978 return STATUS_NOT_IMPLEMENTED
;
987 KsFreeObjectCreateItem(
988 IN KSDEVICE_HEADER Header
,
989 IN PUNICODE_STRING CreateItem
)
991 KSOBJECT_CREATE_ITEM Item
;
993 RtlZeroMemory(&Item
, sizeof(KSOBJECT_CREATE_ITEM
));
994 RtlInitUnicodeString(&Item
.ObjectClass
, CreateItem
->Buffer
);
996 return KspObjectFreeCreateItems(Header
, &Item
);
1006 KsFreeObjectCreateItemsByContext(
1007 IN KSDEVICE_HEADER Header
,
1010 KSOBJECT_CREATE_ITEM Item
;
1012 RtlZeroMemory(&Item
, sizeof(KSOBJECT_CREATE_ITEM
));
1014 Item
.Context
= Context
;
1016 return KspObjectFreeCreateItems(Header
, &Item
);
1025 KsCreateDefaultSecurity(
1026 IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL
,
1027 OUT PSECURITY_DESCRIPTOR
* DefaultSecurity
)
1029 PGENERIC_MAPPING Mapping
;
1030 SECURITY_SUBJECT_CONTEXT SubjectContext
;
1033 /* start capturing security context of calling thread */
1034 SeCaptureSubjectContext(&SubjectContext
);
1035 /* get generic mapping */
1036 Mapping
= IoGetFileObjectGenericMapping();
1037 /* build new descriptor */
1038 Status
= SeAssignSecurity(ParentSecurity
, NULL
, DefaultSecurity
, FALSE
, &SubjectContext
, Mapping
, NonPagedPool
);
1039 /* release security descriptor */
1040 SeReleaseSubjectContext(&SubjectContext
);
1053 IN PFILE_OBJECT FileObject
,
1054 IN BOOLEAN ReuseStackLocation
)
1057 return STATUS_UNSUCCESSFUL
;
1067 KsForwardAndCatchIrp(
1068 IN PDEVICE_OBJECT DeviceObject
,
1070 IN PFILE_OBJECT FileObject
,
1071 IN KSSTACK_USE StackUse
)
1074 return STATUS_UNSUCCESSFUL
;
1080 KspSynchronousIoControlDeviceCompletion(
1081 IN PDEVICE_OBJECT DeviceObject
,
1085 PIO_STATUS_BLOCK IoStatusBlock
= (PIO_STATUS_BLOCK
)Context
;
1087 IoStatusBlock
->Information
= Irp
->IoStatus
.Information
;
1088 IoStatusBlock
->Status
= Irp
->IoStatus
.Status
;
1090 return STATUS_SUCCESS
;
1099 KsSynchronousIoControlDevice(
1100 IN PFILE_OBJECT FileObject
,
1101 IN KPROCESSOR_MODE RequestorMode
,
1105 OUT PVOID OutBuffer
,
1107 OUT PULONG BytesReturned
)
1109 PKSIOBJECT_HEADER ObjectHeader
;
1110 PDEVICE_OBJECT DeviceObject
;
1113 IO_STATUS_BLOCK IoStatusBlock
;
1114 PIO_STACK_LOCATION IoStack
;
1117 /* check for valid file object */
1119 return STATUS_INVALID_PARAMETER
;
1121 /* get device object to send the request to */
1122 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1124 return STATUS_UNSUCCESSFUL
;
1127 /* get object header */
1128 ObjectHeader
= (PKSIOBJECT_HEADER
)FileObject
->FsContext2
;
1130 /* check if there is fast device io function */
1131 if (ObjectHeader
&& ObjectHeader
->DispatchTable
.FastDeviceIoControl
)
1133 IoStatusBlock
.Status
= STATUS_UNSUCCESSFUL
;
1134 IoStatusBlock
.Information
= 0;
1136 /* send the request */
1137 Status
= ObjectHeader
->DispatchTable
.FastDeviceIoControl(FileObject
, TRUE
, InBuffer
, InSize
, OutBuffer
, OutSize
, IoControl
, &IoStatusBlock
, DeviceObject
);
1138 /* check if the request was handled */
1139 //DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
1142 /* store bytes returned */
1143 *BytesReturned
= (ULONG
)IoStatusBlock
.Information
;
1145 return IoStatusBlock
.Status
;
1149 /* initialize the event */
1150 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1152 /* create the irp */
1153 Irp
= IoBuildDeviceIoControlRequest(IoControl
, DeviceObject
, InBuffer
, InSize
, OutBuffer
, OutSize
, FALSE
, &Event
, &IoStatusBlock
);
1157 /* no memory to allocate the irp */
1158 return STATUS_INSUFFICIENT_RESOURCES
;
1162 /* Store Fileobject */
1163 IoStack
= IoGetNextIrpStackLocation(Irp
);
1164 IoStack
->FileObject
= FileObject
;
1166 if (IoControl
== IOCTL_KS_WRITE_STREAM
)
1168 Irp
->AssociatedIrp
.SystemBuffer
= OutBuffer
;
1170 else if (IoControl
== IOCTL_KS_READ_STREAM
)
1172 Irp
->AssociatedIrp
.SystemBuffer
= InBuffer
;
1175 IoSetCompletionRoutine(Irp
, KspSynchronousIoControlDeviceCompletion
, (PVOID
)&IoStatusBlock
, TRUE
, TRUE
, TRUE
);
1177 Status
= IoCallDriver(DeviceObject
, Irp
);
1178 if (Status
== STATUS_PENDING
)
1180 KeWaitForSingleObject(&Event
, Executive
, RequestorMode
, FALSE
, NULL
);
1181 Status
= IoStatusBlock
.Status
;
1184 *BytesReturned
= (ULONG
)IoStatusBlock
.Information
;
1194 KsUnserializeObjectPropertiesFromRegistry(
1195 IN PFILE_OBJECT FileObject
,
1196 IN HANDLE ParentKey OPTIONAL
,
1197 IN PUNICODE_STRING RegistryPath OPTIONAL
)
1200 return STATUS_NOT_IMPLEMENTED
;
1211 IN PUNICODE_STRING SymbolicLink
,
1212 IN PKSPIN_MEDIUM Medium
,
1213 IN ULONG PinDirection
)
1216 UNICODE_STRING Path
;
1217 UNICODE_STRING BasePath
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediumCache\\");
1218 UNICODE_STRING GuidString
;
1220 OBJECT_ATTRIBUTES ObjectAttributes
;
1221 BOOLEAN PathAdjusted
= FALSE
;
1224 /* first check if the medium is standard */
1225 if (IsEqualGUIDAligned(&KSMEDIUMSETID_Standard
, &Medium
->Set
) ||
1226 IsEqualGUIDAligned(&GUID_NULL
, &Medium
->Set
))
1228 /* no need to cache that */
1229 return STATUS_SUCCESS
;
1232 /* convert guid to string */
1233 Status
= RtlStringFromGUID(&Medium
->Set
, &GuidString
);
1234 if (!NT_SUCCESS(Status
))
1237 /* allocate path buffer */
1239 Path
.MaximumLength
= BasePath
.MaximumLength
+ GuidString
.MaximumLength
+ 10 * sizeof(WCHAR
);
1240 Path
.Buffer
= AllocateItem(PagedPool
, Path
.MaximumLength
);
1243 /* not enough resources */
1244 RtlFreeUnicodeString(&GuidString
);
1245 return STATUS_INSUFFICIENT_RESOURCES
;
1248 RtlAppendUnicodeStringToString(&Path
, &BasePath
);
1249 RtlAppendUnicodeStringToString(&Path
, &GuidString
);
1250 RtlAppendUnicodeToString(&Path
, L
"-");
1251 /* FIXME append real instance id */
1252 RtlAppendUnicodeToString(&Path
, L
"0");
1253 RtlAppendUnicodeToString(&Path
, L
"-");
1254 /* FIXME append real instance id */
1255 RtlAppendUnicodeToString(&Path
, L
"0");
1257 /* free guid string */
1258 RtlFreeUnicodeString(&GuidString
);
1260 /* initialize object attributes */
1261 InitializeObjectAttributes(&ObjectAttributes
, &Path
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1262 /* create the key */
1263 Status
= ZwCreateKey(&hKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1265 /* free path buffer */
1266 FreeItem(Path
.Buffer
);
1268 if (NT_SUCCESS(Status
))
1270 /* store symbolic link */
1271 if (SymbolicLink
->Buffer
[1] == L
'?' && SymbolicLink
->Buffer
[2] == L
'?')
1273 /* replace kernel path with user mode path */
1274 SymbolicLink
->Buffer
[1] = L
'\\';
1275 PathAdjusted
= TRUE
;
1279 Status
= ZwSetValueKey(hKey
, SymbolicLink
, 0, REG_DWORD
, &Value
, sizeof(ULONG
));
1283 /* restore kernel path */
1284 SymbolicLink
->Buffer
[1] = L
'?';
1300 PUNICODE_STRING RegistryPath
)
1302 return STATUS_SUCCESS
;
1309 IN PDEVICE_OBJECT DeviceObject
,
1312 PKO_OBJECT_HEADER Header
;
1313 PIO_STACK_LOCATION IoStack
;
1314 PDEVICE_EXTENSION DeviceExtension
;
1316 /* get current irp stack location */
1317 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1319 /* get ko object header */
1320 Header
= (PKO_OBJECT_HEADER
)IoStack
->FileObject
->FsContext2
;
1322 /* free ks object header */
1323 KsFreeObjectHeader(Header
->ObjectHeader
);
1325 /* free ko object header */
1328 /* get device extension */
1329 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1331 /* release bus object */
1332 KsDereferenceBusObject((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
);
1334 /* complete request */
1335 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1336 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1338 return STATUS_SUCCESS
;
1343 static KSDISPATCH_TABLE KoDispatchTable
=
1345 KsDispatchInvalidDeviceRequest
,
1346 KsDispatchInvalidDeviceRequest
,
1347 KsDispatchInvalidDeviceRequest
,
1348 KsDispatchInvalidDeviceRequest
,
1350 KsDispatchQuerySecurity
,
1351 KsDispatchSetSecurity
,
1352 KsDispatchFastIoDeviceControlFailure
,
1353 KsDispatchFastReadFailure
,
1354 KsDispatchFastReadFailure
,
1361 IN PDEVICE_OBJECT DeviceObject
,
1364 PKO_OBJECT_HEADER Header
= NULL
;
1365 PIO_STACK_LOCATION IoStack
;
1366 PKO_DRIVER_EXTENSION DriverObjectExtension
;
1369 /* get current irp stack location */
1370 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1372 if (!IoStack
->FileObject
)
1374 DPRINT1("FileObject not attached!\n");
1375 Status
= STATUS_UNSUCCESSFUL
;
1379 /* get driver object extension */
1380 DriverObjectExtension
= (PKO_DRIVER_EXTENSION
)IoGetDriverObjectExtension(DeviceObject
->DriverObject
, (PVOID
)KoDriverInitialize
);
1381 if (!DriverObjectExtension
)
1383 DPRINT1("No DriverObjectExtension!\n");
1384 Status
= STATUS_UNSUCCESSFUL
;
1388 /* allocate ko object header */
1389 Header
= (PKO_OBJECT_HEADER
)AllocateItem(NonPagedPool
, sizeof(KO_OBJECT_HEADER
));
1392 DPRINT1("failed to allocate KO_OBJECT_HEADER\n");
1393 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1397 /* initialize create item */
1398 Header
->CreateItem
.Create
= KopDispatchCreate
;
1399 RtlInitUnicodeString(&Header
->CreateItem
.ObjectClass
, KOSTRING_CreateObject
);
1402 /* now allocate the object header */
1403 Status
= KsAllocateObjectHeader(&Header
->ObjectHeader
, 1, &Header
->CreateItem
, Irp
, &KoDispatchTable
);
1404 if (!NT_SUCCESS(Status
))
1411 * extract clsid and interface id from irp
1412 * call the standard create handler
1417 IoStack
->FileObject
->FsContext2
= (PVOID
)Header
;
1419 Irp
->IoStatus
.Status
= Status
;
1420 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1426 if (Header
&& Header
->ObjectHeader
)
1427 KsFreeObjectHeader(Header
->ObjectHeader
);
1432 Irp
->IoStatus
.Status
= Status
;
1433 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1442 IN PDRIVER_OBJECT DriverObject
,
1443 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1445 NTSTATUS Status
= STATUS_DEVICE_REMOVED
;
1446 PDEVICE_OBJECT FunctionalDeviceObject
= NULL
;
1447 PDEVICE_OBJECT NextDeviceObject
;
1448 PDEVICE_EXTENSION DeviceExtension
;
1449 PKSOBJECT_CREATE_ITEM CreateItem
;
1451 /* create the device object */
1452 Status
= IoCreateDevice(DriverObject
, sizeof(DEVICE_EXTENSION
), NULL
, FILE_DEVICE_KS
, FILE_DEVICE_SECURE_OPEN
, FALSE
, &FunctionalDeviceObject
);
1453 if (!NT_SUCCESS(Status
))
1456 /* allocate the create item */
1457 CreateItem
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
));
1461 /* not enough memory */
1462 IoDeleteDevice(FunctionalDeviceObject
);
1463 return STATUS_INSUFFICIENT_RESOURCES
;
1466 /* initialize create item */
1467 CreateItem
->Create
= KopDispatchCreate
;
1468 RtlInitUnicodeString(&CreateItem
->ObjectClass
, KOSTRING_CreateObject
);
1470 /* get device extension */
1471 DeviceExtension
= (PDEVICE_EXTENSION
)FunctionalDeviceObject
->DeviceExtension
;
1473 /* now allocate the device header */
1474 Status
= KsAllocateDeviceHeader((KSDEVICE_HEADER
*)&DeviceExtension
->DeviceHeader
, 1, CreateItem
);
1475 if (!NT_SUCCESS(Status
))
1478 IoDeleteDevice(FunctionalDeviceObject
);
1479 FreeItem(CreateItem
);
1483 /* now attach to device stack */
1484 NextDeviceObject
= IoAttachDeviceToDeviceStack(FunctionalDeviceObject
, PhysicalDeviceObject
);
1485 if (NextDeviceObject
)
1487 /* store pnp base object */
1488 KsSetDevicePnpAndBaseObject((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
, NextDeviceObject
, FunctionalDeviceObject
);
1489 /* set device flags */
1490 FunctionalDeviceObject
->Flags
|= DO_DIRECT_IO
| DO_POWER_PAGABLE
;
1491 FunctionalDeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
1496 KsFreeDeviceHeader((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
);
1497 FreeItem(CreateItem
);
1498 IoDeleteDevice(FunctionalDeviceObject
);
1499 Status
= STATUS_DEVICE_REMOVED
;
1514 IN PDEVICE_OBJECT DeviceObject
)
1516 PDEVICE_EXTENSION DeviceExtension
;
1518 /* get device extension */
1519 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1521 return KsAddObjectCreateItemToDeviceHeader((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
, KopDispatchCreate
, NULL
, KOSTRING_CreateObject
, NULL
);
1531 IN PDRIVER_OBJECT DriverObject
,
1532 IN PUNICODE_STRING RegistryPathName
,
1533 IN KoCreateObjectHandler CreateObjectHandler
)
1535 PKO_DRIVER_EXTENSION DriverObjectExtension
;
1538 /* allocate driver object extension */
1539 Status
= IoAllocateDriverObjectExtension(DriverObject
, (PVOID
)KoDriverInitialize
, sizeof(KO_DRIVER_EXTENSION
), (PVOID
*)&DriverObjectExtension
);
1542 if (NT_SUCCESS(Status
))
1544 /* store create handler */
1545 DriverObjectExtension
->CreateObjectHandler
= CreateObjectHandler
;
1547 /* Setting our IRP handlers */
1548 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = KsDefaultDispatchPnp
;
1549 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KsDefaultDispatchPower
;
1550 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KsDefaultForwardIrp
;
1552 /* The driver unload routine */
1553 DriverObject
->DriverUnload
= KsNullDriverUnload
;
1555 /* The driver-supplied AddDevice */
1556 DriverObject
->DriverExtension
->AddDevice
= KopAddDevice
;
1558 /* KS handles these */
1559 DPRINT1("Setting KS function handlers\n");
1560 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CREATE
);
1561 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CLOSE
);
1562 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_DEVICE_CONTROL
);
1576 IN REFCLSID ClassId
)
1590 PKSBASIC_HEADER BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1593 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
1595 KeWaitForSingleObject(BasicHeader
->ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1607 PKSBASIC_HEADER BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1610 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
1612 KeReleaseMutex(BasicHeader
->ControlMutex
, FALSE
);
1624 IN PKSDEVICE Device
)
1626 IKsDevice
*KsDevice
;
1627 PKSIDEVICE_HEADER DeviceHeader
;
1629 DPRINT("KsAcquireDevice\n");
1630 DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
1632 /* get device interface*/
1633 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
1635 /* acquire device mutex */
1636 KsDevice
->lpVtbl
->AcquireDevice(KsDevice
);
1645 IN PKSDEVICE Device
)
1647 IKsDevice
*KsDevice
;
1648 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
1650 /* get device interface*/
1651 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
1653 /* release device mutex */
1654 KsDevice
->lpVtbl
->ReleaseDevice(KsDevice
);
1664 IN PDEVICE_OBJECT DeviceObject
)
1666 IKsDevice
*KsDevice
;
1667 PKSIDEVICE_HEADER DeviceHeader
;
1668 PDEVICE_EXTENSION DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1670 /* get device header */
1671 DeviceHeader
= DeviceExtension
->DeviceHeader
;
1673 /* get device interface*/
1674 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
1676 /* now free device header */
1677 KsFreeDeviceHeader((KSDEVICE_HEADER
)DeviceHeader
);
1679 /* release interface when available */
1682 /* delete IKsDevice interface */
1683 KsDevice
->lpVtbl
->Release(KsDevice
);
1693 KsCompletePendingRequest(
1696 PIO_STACK_LOCATION IoStack
;
1698 /* get current irp stack location */
1699 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1702 ASSERT(Irp
->IoStatus
.Status
!= STATUS_PENDING
);
1704 if (IoStack
->MajorFunction
!= IRP_MJ_CLOSE
)
1706 /* can be completed immediately */
1707 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1711 /* did close operation fail */
1712 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
1714 /* closing failed, complete irp */
1715 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1720 * delete object / device header
1721 * remove dead pin / filter instance
1729 KspSetGetBusDataCompletion(
1730 IN PDEVICE_OBJECT DeviceObject
,
1734 /* signal completion */
1735 KeSetEvent((PRKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
1737 /* more work needs be done, so dont free the irp */
1738 return STATUS_MORE_PROCESSING_REQUIRED
;
1743 KspDeviceSetGetBusData(
1744 IN PDEVICE_OBJECT DeviceObject
,
1751 PIO_STACK_LOCATION IoStack
;
1756 /* allocate the irp */
1757 Irp
= IoAllocateIrp(1, /*FIXME */
1761 return STATUS_INSUFFICIENT_RESOURCES
;
1763 /* initialize the event */
1764 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1766 /* get next stack location */
1767 IoStack
= IoGetNextIrpStackLocation(Irp
);
1769 /* setup a completion routine */
1770 IoSetCompletionRoutine(Irp
, KspSetGetBusDataCompletion
, (PVOID
)&Event
, TRUE
, TRUE
, TRUE
);
1772 /* setup parameters */
1773 IoStack
->Parameters
.ReadWriteConfig
.Buffer
= Buffer
;
1774 IoStack
->Parameters
.ReadWriteConfig
.Length
= Length
;
1775 IoStack
->Parameters
.ReadWriteConfig
.Offset
= Offset
;
1776 IoStack
->Parameters
.ReadWriteConfig
.WhichSpace
= DataType
;
1777 /* setup function code */
1778 IoStack
->MajorFunction
= IRP_MJ_PNP
;
1779 IoStack
->MinorFunction
= (bGet
? IRP_MN_READ_CONFIG
: IRP_MN_WRITE_CONFIG
);
1781 /* lets call the driver */
1782 Status
= IoCallDriver(DeviceObject
, Irp
);
1784 /* is the request still pending */
1785 if (Status
== STATUS_PENDING
)
1788 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1790 Status
= Irp
->IoStatus
.Status
;
1806 IN PKSDEVICE Device
,
1812 return KspDeviceSetGetBusData(Device
->PhysicalDeviceObject
, /* is this right? */
1813 DataType
, Buffer
, Offset
, Length
, FALSE
);
1824 IN PKSDEVICE Device
,
1830 return KspDeviceSetGetBusData(Device
->PhysicalDeviceObject
, /* is this right? */
1831 DataType
, Buffer
, Offset
, Length
, TRUE
);
1841 KsDeviceRegisterAdapterObject(
1842 IN PKSDEVICE Device
,
1843 IN PADAPTER_OBJECT AdapterObject
,
1844 IN ULONG MaxMappingsByteCount
,
1845 IN ULONG MappingTableStride
)
1847 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
1849 DeviceHeader
->AdapterObject
= AdapterObject
;
1850 DeviceHeader
->MaxMappingsByteCount
= MaxMappingsByteCount
;
1851 DeviceHeader
->MappingTableStride
= MappingTableStride
;
1865 PKSBASIC_HEADER BasicHeader
;
1867 /* get the basic header */
1868 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1870 /* type has to be either a device or a filter factory */
1871 ASSERT(BasicHeader
->Type
== KsObjectTypeDevice
|| BasicHeader
->Type
== KsObjectTypeFilterFactory
);
1873 return (PVOID
)BasicHeader
->FirstChild
.Filter
;
1885 PKSBASIC_HEADER BasicHeader
;
1887 /* get the basic header */
1888 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1890 ASSERT(BasicHeader
->Type
== KsObjectTypeDevice
|| BasicHeader
->Type
== KsObjectTypeFilterFactory
||
1891 BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
1893 return (PVOID
)BasicHeader
->Next
.Pin
;
1898 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
1899 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
1901 ULONG Index
, SubIndex
, Count
;
1904 if (!AutomationTableA
)
1905 return AutomationTableB
->MethodSetsCount
;
1907 if (!AutomationTableB
)
1908 return AutomationTableA
->MethodSetsCount
;
1911 DPRINT("AutomationTableA MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableA
->MethodItemSize
, AutomationTableA
->MethodSetsCount
);
1912 DPRINT("AutomationTableB MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableB
->MethodItemSize
, AutomationTableB
->MethodSetsCount
);
1914 if (AutomationTableA
->MethodItemSize
&& AutomationTableB
->MethodItemSize
)
1917 ASSERT(AutomationTableA
->MethodItemSize
== AutomationTableB
->MethodItemSize
);
1920 /* now iterate all property sets and compare their guids */
1921 Count
= AutomationTableA
->MethodSetsCount
;
1923 for(Index
= 0; Index
< AutomationTableB
->MethodSetsCount
; Index
++)
1925 /* set found to false */
1928 for(SubIndex
= 0; SubIndex
< AutomationTableA
->MethodSetsCount
; SubIndex
++)
1930 if (IsEqualGUIDAligned(AutomationTableB
->MethodSets
[Index
].Set
, AutomationTableA
->MethodSets
[SubIndex
].Set
))
1932 /* same property set found */
1947 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
1948 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
1950 ULONG Index
, SubIndex
, Count
;
1953 if (!AutomationTableA
)
1954 return AutomationTableB
->EventSetsCount
;
1956 if (!AutomationTableB
)
1957 return AutomationTableA
->EventSetsCount
;
1959 DPRINT("AutomationTableA EventItemSize %lu EventSetsCount %lu\n", AutomationTableA
->EventItemSize
, AutomationTableA
->EventSetsCount
);
1960 DPRINT("AutomationTableB EventItemSize %lu EventSetsCount %lu\n", AutomationTableB
->EventItemSize
, AutomationTableB
->EventSetsCount
);
1962 if (AutomationTableA
->EventItemSize
&& AutomationTableB
->EventItemSize
)
1965 ASSERT(AutomationTableA
->EventItemSize
== AutomationTableB
->EventItemSize
);
1968 /* now iterate all Event sets and compare their guids */
1969 Count
= AutomationTableA
->EventSetsCount
;
1971 for(Index
= 0; Index
< AutomationTableB
->EventSetsCount
; Index
++)
1973 /* set found to false */
1976 for(SubIndex
= 0; SubIndex
< AutomationTableA
->EventSetsCount
; SubIndex
++)
1978 if (IsEqualGUIDAligned(AutomationTableB
->EventSets
[Index
].Set
, AutomationTableA
->EventSets
[SubIndex
].Set
))
1980 /* same Event set found */
1995 KspCountPropertySets(
1996 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
1997 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
1999 ULONG Index
, SubIndex
, Count
;
2002 if (!AutomationTableA
)
2003 return AutomationTableB
->PropertySetsCount
;
2005 if (!AutomationTableB
)
2006 return AutomationTableA
->PropertySetsCount
;
2009 DPRINT("AutomationTableA PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableA
->PropertyItemSize
, AutomationTableA
->PropertySetsCount
);
2010 DPRINT("AutomationTableB PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableB
->PropertyItemSize
, AutomationTableB
->PropertySetsCount
);
2011 ASSERT(AutomationTableA
->PropertyItemSize
== AutomationTableB
->PropertyItemSize
);
2013 /* now iterate all property sets and compare their guids */
2014 Count
= AutomationTableA
->PropertySetsCount
;
2016 for(Index
= 0; Index
< AutomationTableB
->PropertySetsCount
; Index
++)
2018 /* set found to false */
2021 for(SubIndex
= 0; SubIndex
< AutomationTableA
->PropertySetsCount
; SubIndex
++)
2023 if (IsEqualGUIDAligned(AutomationTableB
->PropertySets
[Index
].Set
, AutomationTableA
->PropertySets
[SubIndex
].Set
))
2025 /* same property set found */
2040 OUT PKSAUTOMATION_TABLE Table
,
2041 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2042 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
2044 ULONG Index
, SubIndex
, Count
;
2047 if (!AutomationTableA
)
2049 /* copy of property set */
2050 RtlMoveMemory((PVOID
)Table
->MethodSets
, AutomationTableB
->MethodSets
, sizeof(KSMETHOD_SET
) * AutomationTableB
->MethodSetsCount
);
2051 return STATUS_SUCCESS
;
2053 else if (!AutomationTableB
)
2055 /* copy of property set */
2056 RtlMoveMemory((PVOID
)Table
->MethodSets
, AutomationTableA
->MethodSets
, sizeof(KSMETHOD_SET
) * AutomationTableA
->MethodSetsCount
);
2057 return STATUS_SUCCESS
;
2060 /* first copy all property items from dominant table */
2061 RtlMoveMemory((PVOID
)Table
->MethodSets
, AutomationTableA
->MethodSets
, sizeof(KSMETHOD_SET
) * AutomationTableA
->MethodSetsCount
);
2063 Count
= AutomationTableA
->MethodSetsCount
;
2065 /* now copy entries which aren't available in the dominant table */
2066 for(Index
= 0; Index
< AutomationTableB
->MethodSetsCount
; Index
++)
2068 /* set found to false */
2071 for(SubIndex
= 0; SubIndex
< AutomationTableA
->MethodSetsCount
; SubIndex
++)
2073 if (IsEqualGUIDAligned(AutomationTableB
->MethodSets
[Index
].Set
, AutomationTableA
->MethodSets
[SubIndex
].Set
))
2075 /* same property set found */
2083 /* copy new property item set */
2084 RtlMoveMemory((PVOID
)&Table
->MethodSets
[Count
], &AutomationTableB
->MethodSets
[Index
], sizeof(KSMETHOD_SET
));
2089 return STATUS_SUCCESS
;
2094 OUT PKSPROPERTY_SET OutPropertySet
,
2095 IN PKSPROPERTY_ITEM PropertyItem
,
2096 IN ULONG PropertyItemSize
)
2098 PKSPROPERTY_ITEM CurrentPropertyItem
;
2101 // check if the property item is already present
2102 CurrentPropertyItem
= (PKSPROPERTY_ITEM
)OutPropertySet
->PropertyItem
;
2103 for(Index
= 0; Index
< OutPropertySet
->PropertiesCount
; Index
++)
2105 if (CurrentPropertyItem
->PropertyId
== PropertyItem
->PropertyId
)
2107 // item already present
2112 CurrentPropertyItem
= (PKSPROPERTY_ITEM
)((ULONG_PTR
)CurrentPropertyItem
+ PropertyItemSize
);
2115 RtlCopyMemory(CurrentPropertyItem
, PropertyItem
, PropertyItemSize
);
2116 OutPropertySet
->PropertiesCount
++;
2120 KspMergePropertySet(
2121 OUT PKSAUTOMATION_TABLE Table
,
2122 OUT PKSPROPERTY_SET OutPropertySet
,
2123 IN PKSPROPERTY_SET PropertySetA
,
2124 IN PKSPROPERTY_SET PropertySetB
,
2125 IN KSOBJECT_BAG Bag OPTIONAL
)
2127 ULONG PropertyCount
, Index
;
2128 PKSPROPERTY_ITEM PropertyItem
, CurrentPropertyItem
;
2132 PropertyCount
= PropertySetA
->PropertiesCount
+ PropertySetB
->PropertiesCount
;
2135 PropertyItem
= AllocateItem(NonPagedPool
, Table
->PropertyItemSize
* PropertyCount
);
2137 return STATUS_INSUFFICIENT_RESOURCES
;
2141 /* add table to object bag */
2142 Status
= KsAddItemToObjectBag(Bag
, PropertyItem
, NULL
);
2143 /* check for success */
2144 if (!NT_SUCCESS(Status
))
2152 // copy entries from dominant table
2153 RtlCopyMemory(PropertyItem
, PropertySetA
->PropertyItem
, Table
->PropertyItemSize
* PropertySetA
->PropertiesCount
);
2155 // init property set
2156 OutPropertySet
->PropertiesCount
= PropertySetA
->PropertiesCount
;
2157 OutPropertySet
->PropertyItem
= PropertyItem
;
2159 // copy other entries
2160 CurrentPropertyItem
= (PKSPROPERTY_ITEM
)PropertySetB
->PropertyItem
;
2161 for(Index
= 0; Index
< PropertySetB
->PropertiesCount
; Index
++)
2165 KspAddPropertyItem(OutPropertySet
, CurrentPropertyItem
, Table
->PropertyItemSize
);
2168 CurrentPropertyItem
= (PKSPROPERTY_ITEM
)((ULONG_PTR
)CurrentPropertyItem
+ Table
->PropertyItemSize
);
2172 return STATUS_SUCCESS
;
2177 KspCopyPropertySets(
2178 OUT PKSAUTOMATION_TABLE Table
,
2179 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2180 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
,
2181 IN KSOBJECT_BAG Bag OPTIONAL
)
2183 ULONG Index
, SubIndex
, Count
;
2187 if (!AutomationTableA
)
2189 /* copy of property set */
2190 RtlMoveMemory((PVOID
)Table
->PropertySets
, AutomationTableB
->PropertySets
, sizeof(KSPROPERTY_SET
) * AutomationTableB
->PropertySetsCount
);
2191 return STATUS_SUCCESS
;
2193 else if (!AutomationTableB
)
2195 /* copy of property set */
2196 RtlMoveMemory((PVOID
)Table
->PropertySets
, AutomationTableA
->PropertySets
, sizeof(KSPROPERTY_SET
) * AutomationTableA
->PropertySetsCount
);
2197 return STATUS_SUCCESS
;
2200 /* first copy all property items from dominant table */
2201 RtlMoveMemory((PVOID
)Table
->PropertySets
, AutomationTableA
->PropertySets
, sizeof(KSPROPERTY_SET
) * AutomationTableA
->PropertySetsCount
);
2203 Count
= AutomationTableA
->PropertySetsCount
;
2205 /* now copy entries which aren't available in the dominant table */
2206 for(Index
= 0; Index
< AutomationTableB
->PropertySetsCount
; Index
++)
2208 /* set found to false */
2211 for(SubIndex
= 0; SubIndex
< AutomationTableA
->PropertySetsCount
; SubIndex
++)
2213 if (IsEqualGUIDAligned(AutomationTableB
->PropertySets
[Index
].Set
, AutomationTableA
->PropertySets
[SubIndex
].Set
))
2215 /* same property set found */
2223 /* copy new property item set */
2224 RtlMoveMemory((PVOID
)&Table
->PropertySets
[Count
], &AutomationTableB
->PropertySets
[Index
], sizeof(KSPROPERTY_SET
));
2229 // merge property sets
2230 Status
= KspMergePropertySet(Table
, (PKSPROPERTY_SET
)&Table
->PropertySets
[SubIndex
], (PKSPROPERTY_SET
)&AutomationTableA
->PropertySets
[SubIndex
], (PKSPROPERTY_SET
)&AutomationTableB
->PropertySets
[Index
], Bag
);
2231 if (!NT_SUCCESS(Status
))
2234 DPRINT1("[KS] Failed to merge %x\n", Status
);
2240 return STATUS_SUCCESS
;
2245 OUT PKSAUTOMATION_TABLE Table
,
2246 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2247 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
2249 ULONG Index
, SubIndex
, Count
;
2252 if (!AutomationTableA
)
2254 /* copy of Event set */
2255 RtlMoveMemory((PVOID
)Table
->EventSets
, AutomationTableB
->EventSets
, sizeof(KSEVENT_SET
) * AutomationTableB
->EventSetsCount
);
2256 return STATUS_SUCCESS
;
2258 else if (!AutomationTableB
)
2260 /* copy of Event set */
2261 RtlMoveMemory((PVOID
)Table
->EventSets
, AutomationTableA
->EventSets
, sizeof(KSEVENT_SET
) * AutomationTableA
->EventSetsCount
);
2262 return STATUS_SUCCESS
;
2265 /* first copy all Event items from dominant table */
2266 RtlMoveMemory((PVOID
)Table
->EventSets
, AutomationTableA
->EventSets
, sizeof(KSEVENT_SET
) * AutomationTableA
->EventSetsCount
);
2268 Count
= AutomationTableA
->EventSetsCount
;
2270 /* now copy entries which aren't available in the dominant table */
2271 for(Index
= 0; Index
< AutomationTableB
->EventSetsCount
; Index
++)
2273 /* set found to false */
2276 for(SubIndex
= 0; SubIndex
< AutomationTableA
->EventSetsCount
; SubIndex
++)
2278 if (IsEqualGUIDAligned(AutomationTableB
->EventSets
[Index
].Set
, AutomationTableA
->EventSets
[SubIndex
].Set
))
2280 /* same Event set found */
2288 /* copy new Event item set */
2289 RtlMoveMemory((PVOID
)&Table
->EventSets
[Count
], &AutomationTableB
->EventSets
[Index
], sizeof(KSEVENT_SET
));
2294 return STATUS_SUCCESS
;
2303 KsMergeAutomationTables(
2304 OUT PKSAUTOMATION_TABLE
*AutomationTableAB
,
2305 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2306 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
,
2307 IN KSOBJECT_BAG Bag OPTIONAL
)
2309 PKSAUTOMATION_TABLE Table
;
2310 NTSTATUS Status
= STATUS_SUCCESS
;
2312 if (!AutomationTableA
&& !AutomationTableB
)
2314 /* nothing to merge */
2315 return STATUS_SUCCESS
;
2318 /* allocate an automation table */
2319 Table
= AllocateItem(NonPagedPool
, sizeof(KSAUTOMATION_TABLE
));
2321 return STATUS_INSUFFICIENT_RESOURCES
;
2325 /* add table to object bag */
2326 Status
= KsAddItemToObjectBag(Bag
, Table
, NULL
);
2327 /* check for success */
2328 if (!NT_SUCCESS(Status
))
2336 /* count property sets */
2337 Table
->PropertySetsCount
= KspCountPropertySets(AutomationTableA
, AutomationTableB
);
2339 if (Table
->PropertySetsCount
)
2341 if (AutomationTableA
)
2343 /* use item size from dominant automation table */
2344 Table
->PropertyItemSize
= AutomationTableA
->PropertyItemSize
;
2348 /* use item size from 2nd automation table */
2349 Table
->PropertyItemSize
= AutomationTableB
->PropertyItemSize
;
2352 if (AutomationTableA
&& AutomationTableB
)
2354 // FIXME handle different propery item sizes
2355 ASSERT(AutomationTableA
->PropertyItemSize
== AutomationTableB
->PropertyItemSize
);
2358 /* now allocate the property sets */
2359 Table
->PropertySets
= AllocateItem(NonPagedPool
, sizeof(KSPROPERTY_SET
) * Table
->PropertySetsCount
);
2361 if (!Table
->PropertySets
)
2363 /* not enough memory */
2369 /* add set to property bag */
2370 Status
= KsAddItemToObjectBag(Bag
, (PVOID
)Table
->PropertySets
, NULL
);
2371 /* check for success */
2372 if (!NT_SUCCESS(Status
))
2378 /* now copy the property sets */
2379 Status
= KspCopyPropertySets(Table
, AutomationTableA
, AutomationTableB
, Bag
);
2380 if(!NT_SUCCESS(Status
))
2385 /* now count the method sets */
2386 Table
->MethodSetsCount
= KspCountMethodSets(AutomationTableA
, AutomationTableB
);
2388 if (Table
->MethodSetsCount
)
2390 if (AutomationTableA
)
2392 /* use item size from dominant automation table */
2393 Table
->MethodItemSize
= AutomationTableA
->MethodItemSize
;
2397 /* use item size from 2nd automation table */
2398 Table
->MethodItemSize
= AutomationTableB
->MethodItemSize
;
2401 /* now allocate the property sets */
2402 Table
->MethodSets
= AllocateItem(NonPagedPool
, sizeof(KSMETHOD_SET
) * Table
->MethodSetsCount
);
2404 if (!Table
->MethodSets
)
2406 /* not enough memory */
2412 /* add set to property bag */
2413 Status
= KsAddItemToObjectBag(Bag
, (PVOID
)Table
->MethodSets
, NULL
);
2414 /* check for success */
2415 if (!NT_SUCCESS(Status
))
2421 /* now copy the property sets */
2422 Status
= KspCopyMethodSets(Table
, AutomationTableA
, AutomationTableB
);
2423 if(!NT_SUCCESS(Status
))
2428 /* now count the event sets */
2429 Table
->EventSetsCount
= KspCountEventSets(AutomationTableA
, AutomationTableB
);
2431 if (Table
->EventSetsCount
)
2433 if (AutomationTableA
)
2435 /* use item size from dominant automation table */
2436 Table
->EventItemSize
= AutomationTableA
->EventItemSize
;
2440 /* use item size from 2nd automation table */
2441 Table
->EventItemSize
= AutomationTableB
->EventItemSize
;
2444 /* now allocate the property sets */
2445 Table
->EventSets
= AllocateItem(NonPagedPool
, sizeof(KSEVENT_SET
) * Table
->EventSetsCount
);
2447 if (!Table
->EventSets
)
2449 /* not enough memory */
2455 /* add set to property bag */
2456 Status
= KsAddItemToObjectBag(Bag
, (PVOID
)Table
->EventSets
, NULL
);
2457 /* check for success */
2458 if (!NT_SUCCESS(Status
))
2464 /* now copy the property sets */
2465 Status
= KspCopyEventSets(Table
, AutomationTableA
, AutomationTableB
);
2466 if(!NT_SUCCESS(Status
))
2471 *AutomationTableAB
= Table
;
2480 if (Table
->PropertySets
)
2482 /* clean property sets */
2483 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, (PVOID
)Table
->PropertySets
, TRUE
)))
2484 FreeItem((PVOID
)Table
->PropertySets
);
2487 if (Table
->MethodSets
)
2489 /* clean property sets */
2490 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, (PVOID
)Table
->MethodSets
, TRUE
)))
2491 FreeItem((PVOID
)Table
->MethodSets
);
2494 if (Table
->EventSets
)
2496 /* clean property sets */
2497 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, (PVOID
)Table
->EventSets
, TRUE
)))
2498 FreeItem((PVOID
)Table
->EventSets
);
2501 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, Table
, TRUE
)))
2505 return STATUS_INSUFFICIENT_RESOURCES
;
2514 KsRegisterAggregatedClientUnknown(
2516 IN PUNKNOWN ClientUnknown
)
2518 PKSBASIC_HEADER BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
2521 ASSERT(BasicHeader
->Type
== KsObjectTypeDevice
|| BasicHeader
->Type
== KsObjectTypeFilterFactory
||
2522 BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
2524 if (BasicHeader
->ClientAggregate
)
2526 /* release existing aggregate */
2527 BasicHeader
->ClientAggregate
->lpVtbl
->Release(BasicHeader
->ClientAggregate
);
2530 /* increment reference count */
2531 ClientUnknown
->lpVtbl
->AddRef(ClientUnknown
);
2533 /* store client aggregate */
2534 BasicHeader
->ClientAggregate
= ClientUnknown
;
2536 /* return objects outer unknown */
2537 return BasicHeader
->OuterUnknown
;
2545 KsRegisterFilterWithNoKSPins(
2546 IN PDEVICE_OBJECT DeviceObject
,
2547 IN
const GUID
* InterfaceClassGUID
,
2549 IN BOOL
* PinDirection
,
2550 IN KSPIN_MEDIUM
* MediumList
,
2551 IN GUID
* CategoryList OPTIONAL
)
2555 PWSTR SymbolicLinkList
;
2558 UNICODE_STRING InterfaceString
;
2559 //UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
2561 if (!InterfaceClassGUID
|| !PinCount
|| !PinDirection
|| !MediumList
)
2563 /* all these parameters are required */
2564 return STATUS_INVALID_PARAMETER
;
2567 /* calculate filter data value size */
2568 Size
= PinCount
* sizeof(KSPIN_MEDIUM
);
2571 /* add category list */
2572 Size
+= PinCount
* sizeof(GUID
);
2575 /* FIXME generate filter data blob */
2578 /* get symbolic link list */
2579 Status
= IoGetDeviceInterfaces(InterfaceClassGUID
, DeviceObject
, DEVICE_INTERFACE_INCLUDE_NONACTIVE
, &SymbolicLinkList
);
2580 if (NT_SUCCESS(Status
))
2582 /* initialize first symbolic link */
2583 RtlInitUnicodeString(&InterfaceString
, SymbolicLinkList
);
2585 /* open first device interface registry key */
2586 Status
= IoOpenDeviceInterfaceRegistryKey(&InterfaceString
, GENERIC_WRITE
, &hKey
);
2588 if (NT_SUCCESS(Status
))
2590 /* write filter data */
2591 //Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size);
2599 /* update medium cache */
2600 for(Index
= 0; Index
< PinCount
; Index
++)
2602 KsCacheMedium(&InterfaceString
, &MediumList
[Index
], PinDirection
[Index
]);
2606 /* free the symbolic link list */
2607 FreeItem(SymbolicLinkList
);