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
12 const GUID GUID_NULL
= {0x00000000L
, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
13 const GUID KSMEDIUMSETID_Standard
= {0x4747B320L
, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
23 OUT KSRESET
* ResetValue
)
25 PIO_STACK_LOCATION IoStack
;
27 NTSTATUS Status
= STATUS_SUCCESS
;
29 /* get current irp stack */
30 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
32 /* check if there is reset value provided */
33 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(KSRESET
))
34 return STATUS_INVALID_PARAMETER
;
36 if (Irp
->RequestorMode
== UserMode
)
38 /* need to probe the buffer */
41 ProbeForRead(IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
, sizeof(KSRESET
), sizeof(UCHAR
));
42 Value
= (KSRESET
*)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
45 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
47 /* Exception, get the error code */
48 Status
= _SEH2_GetExceptionCode();
54 Value
= (KSRESET
*)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
67 KsAcquireDeviceSecurityLock(
68 IN KSDEVICE_HEADER DevHeader
,
71 PKSIDEVICE_HEADER Header
= (PKSIDEVICE_HEADER
)DevHeader
;
73 KeEnterCriticalRegion();
77 ExAcquireResourceExclusiveLite(&Header
->SecurityLock
, TRUE
);
81 ExAcquireResourceSharedLite(&Header
->SecurityLock
, TRUE
);
91 KsReleaseDeviceSecurityLock(
92 IN KSDEVICE_HEADER DevHeader
)
94 PKSIDEVICE_HEADER Header
= (PKSIDEVICE_HEADER
)DevHeader
;
96 DPRINT("KsReleaseDevice\n");
98 ExReleaseResourceLite(&Header
->SecurityLock
);
99 KeLeaveCriticalRegion();
108 KsDefaultDispatchPnp(
109 IN PDEVICE_OBJECT DeviceObject
,
112 PDEVICE_EXTENSION DeviceExtension
;
113 PKSIDEVICE_HEADER DeviceHeader
;
114 PIO_STACK_LOCATION IoStack
;
115 PDEVICE_OBJECT PnpDeviceObject
;
119 /* get current irp stack */
120 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
122 /* caller wants to add the target device */
123 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
125 /* get device header */
126 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
128 /* backup PnpBaseObject */
129 PnpDeviceObject
= DeviceHeader
->PnpDeviceObject
;
132 /* backup minor function code */
133 MinorFunction
= IoStack
->MinorFunction
;
135 if(MinorFunction
== IRP_MN_REMOVE_DEVICE
)
137 /* remove the device */
138 KsFreeDeviceHeader((KSDEVICE_HEADER
)DeviceHeader
);
141 /* skip current irp stack */
142 IoSkipCurrentIrpStackLocation(Irp
);
144 /* call attached pnp device object */
145 Status
= IoCallDriver(PnpDeviceObject
, Irp
);
147 if (MinorFunction
== IRP_MN_REMOVE_DEVICE
)
150 IoDetachDevice(PnpDeviceObject
);
152 IoDeleteDevice(DeviceObject
);
164 KsDefaultDispatchPower(
165 IN PDEVICE_OBJECT DeviceObject
,
168 PDEVICE_EXTENSION DeviceExtension
;
169 PKSIDEVICE_HEADER DeviceHeader
;
170 PKSIOBJECT_HEADER ObjectHeader
;
171 //PIO_STACK_LOCATION IoStack;
172 PLIST_ENTRY ListEntry
;
175 /* get current irp stack */
176 //IoStack = IoGetCurrentIrpStackLocation(Irp);
178 /* caller wants to add the target device */
179 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
181 /* get device header */
182 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
186 /* loop our power dispatch list and call registered notification functions */
187 ListEntry
= DeviceHeader
->PowerDispatchList
.Flink
;
189 while(ListEntry
!= &DeviceHeader
->PowerDispatchList
)
191 /* get object header */
192 ObjectHeader
= (PKSIOBJECT_HEADER
)CONTAINING_RECORD(ListEntry
, KSIOBJECT_HEADER
, PowerDispatchEntry
);
194 /* does it have still a cb */
195 if (ObjectHeader
->PowerDispatch
)
197 /* call the power cb */
198 Status
= ObjectHeader
->PowerDispatch(ObjectHeader
->PowerContext
, Irp
);
199 ASSERT(NT_SUCCESS(Status
));
202 /* iterate to next entry */
203 ListEntry
= ListEntry
->Flink
;
206 /* start next power irp */
207 PoStartNextPowerIrp(Irp
);
209 /* skip current irp stack location */
210 IoSkipCurrentIrpStackLocation(Irp
);
213 Status
= PoCallDriver(DeviceHeader
->PnpDeviceObject
, Irp
);
226 IN PDEVICE_OBJECT DeviceObject
,
229 PDEVICE_EXTENSION DeviceExtension
;
230 PKSIDEVICE_HEADER DeviceHeader
;
231 //PIO_STACK_LOCATION IoStack;
234 /* get current irp stack */
235 //IoStack = IoGetCurrentIrpStackLocation(Irp);
237 /* caller wants to add the target device */
238 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
240 /* get device header */
241 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
243 /* forward the request to the PDO */
244 Status
= IoCallDriver(DeviceHeader
->PnpDeviceObject
, Irp
);
255 KsSetDevicePnpAndBaseObject(
256 IN KSDEVICE_HEADER Header
,
257 IN PDEVICE_OBJECT PnpDeviceObject
,
258 IN PDEVICE_OBJECT BaseDevice
)
260 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
262 DeviceHeader
->PnpDeviceObject
= PnpDeviceObject
;
263 DeviceHeader
->BaseDevice
= BaseDevice
;
272 KsQueryDevicePnpObject(
273 IN KSDEVICE_HEADER Header
)
275 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
277 /* return PnpDeviceObject */
278 return DeviceHeader
->PnpDeviceObject
;
288 KsQueryObjectAccessMask(
289 IN KSOBJECT_HEADER Header
)
291 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
293 /* return access mask */
294 return ObjectHeader
->AccessMask
;
304 KsRecalculateStackDepth(
305 IN KSDEVICE_HEADER Header
,
306 IN BOOLEAN ReuseStackLocation
)
319 IN KSOBJECT_HEADER Header
,
320 IN KSTARGET_STATE TargetState
)
322 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
324 /* set target state */
325 DeviceHeader
->TargetState
= TargetState
;
334 KsSetTargetDeviceObject(
335 IN KSOBJECT_HEADER Header
,
336 IN PDEVICE_OBJECT TargetDevice OPTIONAL
)
338 PDEVICE_EXTENSION DeviceExtension
;
339 PKSIDEVICE_HEADER DeviceHeader
;
340 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
342 if(ObjectHeader
->TargetDevice
)
344 /* there is already a target device set */
347 /* caller wants to remove the target device */
348 DeviceExtension
= (PDEVICE_EXTENSION
)ObjectHeader
->TargetDevice
->DeviceExtension
;
350 /* get device header */
351 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
354 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
, FALSE
);
357 RemoveEntryList(&ObjectHeader
->TargetDeviceListEntry
);
359 /* remove device pointer */
360 ObjectHeader
->TargetDevice
= NULL
;
363 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
);
368 /* no target device yet set */
371 /* caller wants to add the target device */
372 DeviceExtension
= (PDEVICE_EXTENSION
)TargetDevice
->DeviceExtension
;
374 /* get device header */
375 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
378 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
, FALSE
);
380 /* insert list entry */
381 InsertTailList(&DeviceHeader
->TargetDeviceList
, &ObjectHeader
->TargetDeviceListEntry
);
383 /* store target device */
384 ObjectHeader
->TargetDevice
= TargetDevice
;
387 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
);
400 IN KSOBJECT_HEADER Header
,
401 IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL
,
402 IN PVOID PowerContext OPTIONAL
)
404 PDEVICE_EXTENSION DeviceExtension
;
405 PKSIDEVICE_HEADER DeviceHeader
;
406 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
408 /* caller wants to add the target device */
409 DeviceExtension
= (PDEVICE_EXTENSION
)ObjectHeader
->ParentDeviceObject
->DeviceExtension
;
411 /* get device header */
412 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
415 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
, FALSE
);
419 /* add power dispatch entry */
420 InsertTailList(&DeviceHeader
->PowerDispatchList
, &ObjectHeader
->PowerDispatchEntry
);
422 /* store function and context */
423 ObjectHeader
->PowerDispatch
= PowerDispatch
;
424 ObjectHeader
->PowerContext
= PowerContext
;
428 /* remove power dispatch entry */
429 RemoveEntryList(&ObjectHeader
->PowerDispatchEntry
);
431 /* store function and context */
432 ObjectHeader
->PowerDispatch
= NULL
;
433 ObjectHeader
->PowerContext
= NULL
;
438 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
);
446 PKSOBJECT_CREATE_ITEM
448 KsQueryObjectCreateItem(
449 IN KSOBJECT_HEADER Header
)
451 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
452 return ObjectHeader
->OriginalCreateItem
;
456 KspAddCreateItemToList(
457 OUT PLIST_ENTRY ListHead
,
459 IN PKSOBJECT_CREATE_ITEM ItemsList
)
462 PCREATE_ITEM_ENTRY Entry
;
465 for(Index
= 0; Index
< ItemsCount
; Index
++)
468 Entry
= AllocateItem(NonPagedPool
, sizeof(CREATE_ITEM_ENTRY
));
472 return STATUS_INSUFFICIENT_RESOURCES
;
475 /* initialize entry */
476 InitializeListHead(&Entry
->ObjectItemList
);
477 Entry
->CreateItem
= &ItemsList
[Index
];
478 Entry
->ReferenceCount
= 0;
479 Entry
->ItemFreeCallback
= NULL
;
481 InsertTailList(ListHead
, &Entry
->Entry
);
483 return STATUS_SUCCESS
;
488 PLIST_ENTRY ListHead
)
490 PCREATE_ITEM_ENTRY Entry
;
492 while(!IsListEmpty(ListHead
))
494 /* remove create item from list */
495 Entry
= (PCREATE_ITEM_ENTRY
)CONTAINING_RECORD(RemoveHeadList(ListHead
), CREATE_ITEM_ENTRY
, Entry
);
497 /* caller shouldnt have any references */
498 //ASSERT(Entry->ReferenceCount == 0);
499 //ASSERT(IsListEmpty(&Entry->ObjectItemList));
501 /* does the creator wish notification */
502 if (Entry
->ItemFreeCallback
)
505 Entry
->ItemFreeCallback(Entry
->CreateItem
);
508 /* free create item entry */
520 KsAllocateDeviceHeader(
521 OUT KSDEVICE_HEADER
* OutHeader
,
523 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL
)
525 NTSTATUS Status
= STATUS_SUCCESS
;
526 PKSIDEVICE_HEADER Header
;
529 return STATUS_INVALID_PARAMETER
;
531 /* allocate a device header */
532 Header
= AllocateItem(PagedPool
, sizeof(KSIDEVICE_HEADER
));
534 /* check for success */
536 return STATUS_INSUFFICIENT_RESOURCES
;
538 /* clear all memory */
539 RtlZeroMemory(Header
, sizeof(KSIDEVICE_HEADER
));
541 /* initialize device mutex */
542 KeInitializeMutex(&Header
->DeviceMutex
, 0);
544 /* initialize target device list */
545 InitializeListHead(&Header
->TargetDeviceList
);
546 /* initialize power dispatch list */
547 InitializeListHead(&Header
->PowerDispatchList
);
548 /* initialize object bag lists */
549 InitializeListHead(&Header
->ObjectBags
);
551 /* initialize create item list */
552 InitializeListHead(&Header
->ItemList
);
554 /* initialize basic header */
555 Header
->BasicHeader
.Type
= KsObjectTypeDevice
;
556 Header
->BasicHeader
.KsDevice
= &Header
->KsDevice
;
557 Header
->BasicHeader
.Parent
.KsDevice
= &Header
->KsDevice
;
559 /* are there any create items provided */
560 if (ItemsCount
&& ItemsList
)
562 Status
= KspAddCreateItemToList(&Header
->ItemList
, ItemsCount
, ItemsList
);
564 if (NT_SUCCESS(Status
))
566 /* store item count */
567 Header
->ItemListCount
= ItemsCount
;
571 /* release create items */
572 KspFreeCreateItems(&Header
->ItemList
);
589 IN KSDEVICE_HEADER DevHeader
)
591 PKSIDEVICE_HEADER Header
;
593 Header
= (PKSIDEVICE_HEADER
)DevHeader
;
598 KspFreeCreateItems(&Header
->ItemList
);
608 KsAllocateObjectHeader(
609 OUT KSOBJECT_HEADER
*Header
,
611 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL
,
613 IN KSDISPATCH_TABLE
* Table
)
615 PIO_STACK_LOCATION IoStack
;
616 //PDEVICE_EXTENSION DeviceExtension;
617 //PKSIDEVICE_HEADER DeviceHeader;
618 PKSIOBJECT_HEADER ObjectHeader
;
619 //PKSOBJECT_CREATE_ITEM CreateItem;
623 return STATUS_INVALID_PARAMETER_1
;
626 return STATUS_INVALID_PARAMETER_4
;
629 return STATUS_INVALID_PARAMETER_5
;
631 /* get current stack location */
632 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
633 /* get device extension */
634 //DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
635 /* get device header */
636 //DeviceHeader = DeviceExtension->DeviceHeader;
639 ASSERT(IoStack
->FileObject
);
640 /* check for an file object */
642 /* allocate the object header */
643 ObjectHeader
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_HEADER
));
645 return STATUS_INSUFFICIENT_RESOURCES
;
647 /* initialize object header */
648 RtlZeroMemory(ObjectHeader
, sizeof(KSIOBJECT_HEADER
));
650 /* initialize create item list */
651 InitializeListHead(&ObjectHeader
->ItemList
);
653 /* get create item */
654 //CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
656 /* do we have a name */
657 if (IoStack
->FileObject
->FileName
.Buffer
)
659 /* copy object class */
660 ObjectHeader
->ObjectClass
.MaximumLength
= IoStack
->FileObject
->FileName
.MaximumLength
;
661 ObjectHeader
->ObjectClass
.Buffer
= AllocateItem(NonPagedPool
, ObjectHeader
->ObjectClass
.MaximumLength
);
662 if (!ObjectHeader
->ObjectClass
.Buffer
)
664 FreeItem(ObjectHeader
);
665 return STATUS_INSUFFICIENT_RESOURCES
;
667 RtlCopyUnicodeString(&ObjectHeader
->ObjectClass
, &IoStack
->FileObject
->FileName
);
670 /* copy dispatch table */
671 RtlCopyMemory(&ObjectHeader
->DispatchTable
, Table
, sizeof(KSDISPATCH_TABLE
));
673 /* store create items */
674 if (ItemsCount
&& ItemsList
)
676 Status
= KspAddCreateItemToList(&ObjectHeader
->ItemList
, ItemsCount
, ItemsList
);
678 if (NT_SUCCESS(Status
))
680 /* store item count */
681 ObjectHeader
->ItemListCount
= ItemsCount
;
686 KsFreeObjectHeader(ObjectHeader
);
690 /* store the object in the file object */
691 IoStack
->FileObject
->FsContext2
= ObjectHeader
;
693 /* store parent device */
694 ObjectHeader
->ParentDeviceObject
= IoGetRelatedDeviceObject(IoStack
->FileObject
);
696 /* store originating create item */
697 ObjectHeader
->OriginalCreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
699 /* FIXME store access mask see KsQueryObjectAccessMask */
700 ObjectHeader
->AccessMask
= IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
;
704 *Header
= ObjectHeader
;
706 DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader
->ObjectClass
.Buffer
, IoStack
->FileObject
, ObjectHeader
);
708 return STATUS_SUCCESS
;
721 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
) Header
;
723 DPRINT("KsFreeObjectHeader Header %p Class %wZ\n", Header
, &ObjectHeader
->ObjectClass
);
725 if (ObjectHeader
->ObjectClass
.Buffer
)
727 /* release object class buffer */
728 FreeItem(ObjectHeader
->ObjectClass
.Buffer
);
731 if (ObjectHeader
->Unknown
)
733 /* release associated object */
734 ObjectHeader
->Unknown
->lpVtbl
->Release(ObjectHeader
->Unknown
);
737 /* free create items */
738 KspFreeCreateItems(&ObjectHeader
->ItemList
);
740 /* free object header */
741 FreeItem(ObjectHeader
);
746 KspAddObjectCreateItemToList(
747 PLIST_ENTRY ListHead
,
748 IN PDRIVER_DISPATCH Create
,
750 IN PWCHAR ObjectClass
,
751 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
754 PCREATE_ITEM_ENTRY CreateEntry
;
756 /* point to first entry */
757 Entry
= ListHead
->Flink
;
759 while(Entry
!= ListHead
)
761 /* get create entry */
762 CreateEntry
= (PCREATE_ITEM_ENTRY
)CONTAINING_RECORD(Entry
, CREATE_ITEM_ENTRY
, Entry
);
763 /* if the create item has no create routine, then it is free to use */
764 if (CreateEntry
->CreateItem
->Create
== NULL
)
767 ASSERT(IsListEmpty(&CreateEntry
->ObjectItemList
));
768 ASSERT(CreateEntry
->ReferenceCount
== 0);
770 CreateEntry
->CreateItem
->Context
= Context
;
771 CreateEntry
->CreateItem
->Create
= Create
;
772 RtlInitUnicodeString(&CreateEntry
->CreateItem
->ObjectClass
, ObjectClass
);
773 CreateEntry
->CreateItem
->SecurityDescriptor
= SecurityDescriptor
;
775 return STATUS_SUCCESS
;
778 if (!wcsicmp(ObjectClass
, CreateEntry
->CreateItem
->ObjectClass
.Buffer
))
780 /* the same object class already exists */
781 return STATUS_OBJECT_NAME_COLLISION
;
784 /* iterate to next entry */
785 Entry
= Entry
->Flink
;
787 return STATUS_ALLOTTED_SPACE_EXCEEDED
;
796 KsAddObjectCreateItemToDeviceHeader(
797 IN KSDEVICE_HEADER DevHeader
,
798 IN PDRIVER_DISPATCH Create
,
800 IN PWCHAR ObjectClass
,
801 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
803 PKSIDEVICE_HEADER Header
;
806 Header
= (PKSIDEVICE_HEADER
)DevHeader
;
808 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
810 /* check if a device header has been provided */
812 return STATUS_INVALID_PARAMETER_1
;
814 /* check if a create item has been provided */
816 return STATUS_INVALID_PARAMETER_2
;
818 /* check if a object class has been provided */
820 return STATUS_INVALID_PARAMETER_4
;
822 /* let others do the work */
823 Status
= KspAddObjectCreateItemToList(&Header
->ItemList
, Create
, Context
, ObjectClass
, SecurityDescriptor
);
825 if (NT_SUCCESS(Status
))
827 /* increment create item count */
828 InterlockedIncrement(&Header
->ItemListCount
);
830 DPRINT("KsAddObjectCreateItemToDeviceHeader Status %x\n", Status
);
840 KsAddObjectCreateItemToObjectHeader(
841 IN KSOBJECT_HEADER ObjectHeader
,
842 IN PDRIVER_DISPATCH Create
,
844 IN PWCHAR ObjectClass
,
845 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
847 PKSIOBJECT_HEADER Header
;
850 Header
= (PKSIOBJECT_HEADER
)ObjectHeader
;
852 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
854 /* check if a device header has been provided */
856 return STATUS_INVALID_PARAMETER_1
;
858 /* check if a create item has been provided */
860 return STATUS_INVALID_PARAMETER_2
;
862 /* check if a object class has been provided */
864 return STATUS_INVALID_PARAMETER_4
;
867 Status
= KspAddObjectCreateItemToList(&Header
->ItemList
, Create
, Context
, ObjectClass
, SecurityDescriptor
);
869 if (NT_SUCCESS(Status
))
871 /* increment create item count */
872 InterlockedIncrement(&Header
->ItemListCount
);
884 KsAllocateObjectCreateItem(
885 IN KSDEVICE_HEADER DevHeader
,
886 IN PKSOBJECT_CREATE_ITEM CreateItem
,
887 IN BOOLEAN AllocateEntry
,
888 IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL
)
890 PCREATE_ITEM_ENTRY CreateEntry
;
891 PKSIDEVICE_HEADER Header
;
892 PKSOBJECT_CREATE_ITEM Item
;
894 Header
= (PKSIDEVICE_HEADER
)DevHeader
;
897 return STATUS_INVALID_PARAMETER_1
;
900 return STATUS_INVALID_PARAMETER_2
;
902 /* first allocate a create entry */
903 CreateEntry
= AllocateItem(NonPagedPool
, sizeof(CREATE_ITEM_ENTRY
));
905 /* check for allocation success */
908 /* not enough resources */
909 return STATUS_INSUFFICIENT_RESOURCES
;
915 /* allocate create item */
916 Item
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
));
920 FreeItem(CreateEntry
);
921 return STATUS_INSUFFICIENT_RESOURCES
;
924 /* initialize descriptor */
925 Item
->Context
= CreateItem
->Context
;
926 Item
->Create
= CreateItem
->Create
;
927 Item
->Flags
= CreateItem
->Flags
;
928 Item
->SecurityDescriptor
= CreateItem
->SecurityDescriptor
;
929 Item
->ObjectClass
.Length
= 0;
930 Item
->ObjectClass
.MaximumLength
= CreateItem
->ObjectClass
.MaximumLength
;
932 /* copy object class */
933 Item
->ObjectClass
.Buffer
= AllocateItem(NonPagedPool
, Item
->ObjectClass
.MaximumLength
);
934 if (!Item
->ObjectClass
.Buffer
)
936 /* release resources */
938 FreeItem(CreateEntry
);
940 return STATUS_INSUFFICIENT_RESOURCES
;
942 RtlCopyUnicodeString(&Item
->ObjectClass
, &CreateItem
->ObjectClass
);
946 if (ItemFreeCallback
)
948 /* callback is only accepted when the create item is copied */
949 ItemFreeCallback
= NULL
;
951 /* use passed create item */
955 /* initialize create item entry */
956 InitializeListHead(&CreateEntry
->ObjectItemList
);
957 CreateEntry
->ItemFreeCallback
= ItemFreeCallback
;
958 CreateEntry
->CreateItem
= Item
;
959 CreateEntry
->ReferenceCount
= 0;
961 /* now insert the create item entry */
962 InsertTailList(&Header
->ItemList
, &CreateEntry
->Entry
);
964 /* increment item count */
965 InterlockedIncrement(&Header
->ItemListCount
);
967 return STATUS_SUCCESS
;
971 KspObjectFreeCreateItems(
972 IN KSDEVICE_HEADER Header
,
973 IN PKSOBJECT_CREATE_ITEM CreateItem
)
976 return STATUS_NOT_IMPLEMENTED
;
985 KsFreeObjectCreateItem(
986 IN KSDEVICE_HEADER Header
,
987 IN PUNICODE_STRING CreateItem
)
989 KSOBJECT_CREATE_ITEM Item
;
991 RtlZeroMemory(&Item
, sizeof(KSOBJECT_CREATE_ITEM
));
992 RtlInitUnicodeString(&Item
.ObjectClass
, CreateItem
->Buffer
);
994 return KspObjectFreeCreateItems(Header
, &Item
);
1004 KsFreeObjectCreateItemsByContext(
1005 IN KSDEVICE_HEADER Header
,
1008 KSOBJECT_CREATE_ITEM Item
;
1010 RtlZeroMemory(&Item
, sizeof(KSOBJECT_CREATE_ITEM
));
1012 Item
.Context
= Context
;
1014 return KspObjectFreeCreateItems(Header
, &Item
);
1023 KsCreateDefaultSecurity(
1024 IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL
,
1025 OUT PSECURITY_DESCRIPTOR
* DefaultSecurity
)
1027 PGENERIC_MAPPING Mapping
;
1028 SECURITY_SUBJECT_CONTEXT SubjectContext
;
1031 /* start capturing security context of calling thread */
1032 SeCaptureSubjectContext(&SubjectContext
);
1033 /* get generic mapping */
1034 Mapping
= IoGetFileObjectGenericMapping();
1035 /* build new descriptor */
1036 Status
= SeAssignSecurity(ParentSecurity
, NULL
, DefaultSecurity
, FALSE
, &SubjectContext
, Mapping
, NonPagedPool
);
1037 /* release security descriptor */
1038 SeReleaseSubjectContext(&SubjectContext
);
1051 IN PFILE_OBJECT FileObject
,
1052 IN BOOLEAN ReuseStackLocation
)
1055 return STATUS_UNSUCCESSFUL
;
1065 KsForwardAndCatchIrp(
1066 IN PDEVICE_OBJECT DeviceObject
,
1068 IN PFILE_OBJECT FileObject
,
1069 IN KSSTACK_USE StackUse
)
1072 return STATUS_UNSUCCESSFUL
;
1078 KspSynchronousIoControlDeviceCompletion(
1079 IN PDEVICE_OBJECT DeviceObject
,
1083 PIO_STATUS_BLOCK IoStatusBlock
= (PIO_STATUS_BLOCK
)Context
;
1085 IoStatusBlock
->Information
= Irp
->IoStatus
.Information
;
1086 IoStatusBlock
->Status
= Irp
->IoStatus
.Status
;
1088 return STATUS_SUCCESS
;
1097 KsSynchronousIoControlDevice(
1098 IN PFILE_OBJECT FileObject
,
1099 IN KPROCESSOR_MODE RequestorMode
,
1103 OUT PVOID OutBuffer
,
1105 OUT PULONG BytesReturned
)
1107 PKSIOBJECT_HEADER ObjectHeader
;
1108 PDEVICE_OBJECT DeviceObject
;
1111 IO_STATUS_BLOCK IoStatusBlock
;
1112 PIO_STACK_LOCATION IoStack
;
1115 /* check for valid file object */
1117 return STATUS_INVALID_PARAMETER
;
1119 /* get device object to send the request to */
1120 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1122 return STATUS_UNSUCCESSFUL
;
1125 /* get object header */
1126 ObjectHeader
= (PKSIOBJECT_HEADER
)FileObject
->FsContext2
;
1128 /* check if there is fast device io function */
1129 if (ObjectHeader
&& ObjectHeader
->DispatchTable
.FastDeviceIoControl
)
1131 IoStatusBlock
.Status
= STATUS_UNSUCCESSFUL
;
1132 IoStatusBlock
.Information
= 0;
1134 /* send the request */
1135 Status
= ObjectHeader
->DispatchTable
.FastDeviceIoControl(FileObject
, TRUE
, InBuffer
, InSize
, OutBuffer
, OutSize
, IoControl
, &IoStatusBlock
, DeviceObject
);
1136 /* check if the request was handled */
1137 //DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
1140 /* store bytes returned */
1141 *BytesReturned
= IoStatusBlock
.Information
;
1143 return IoStatusBlock
.Status
;
1147 /* initialize the event */
1148 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1150 /* create the irp */
1151 Irp
= IoBuildDeviceIoControlRequest(IoControl
, DeviceObject
, InBuffer
, InSize
, OutBuffer
, OutSize
, FALSE
, &Event
, &IoStatusBlock
);
1155 /* no memory to allocate the irp */
1156 return STATUS_INSUFFICIENT_RESOURCES
;
1160 /* Store Fileobject */
1161 IoStack
= IoGetNextIrpStackLocation(Irp
);
1162 IoStack
->FileObject
= FileObject
;
1164 if (IoControl
== IOCTL_KS_WRITE_STREAM
)
1166 Irp
->AssociatedIrp
.SystemBuffer
= OutBuffer
;
1168 else if (IoControl
== IOCTL_KS_READ_STREAM
)
1170 Irp
->AssociatedIrp
.SystemBuffer
= InBuffer
;
1173 IoSetCompletionRoutine(Irp
, KspSynchronousIoControlDeviceCompletion
, (PVOID
)&IoStatusBlock
, TRUE
, TRUE
, TRUE
);
1175 Status
= IoCallDriver(DeviceObject
, Irp
);
1176 if (Status
== STATUS_PENDING
)
1178 KeWaitForSingleObject(&Event
, Executive
, RequestorMode
, FALSE
, NULL
);
1179 Status
= IoStatusBlock
.Status
;
1182 *BytesReturned
= IoStatusBlock
.Information
;
1192 KsUnserializeObjectPropertiesFromRegistry(
1193 IN PFILE_OBJECT FileObject
,
1194 IN HANDLE ParentKey OPTIONAL
,
1195 IN PUNICODE_STRING RegistryPath OPTIONAL
)
1198 return STATUS_NOT_IMPLEMENTED
;
1209 IN PUNICODE_STRING SymbolicLink
,
1210 IN PKSPIN_MEDIUM Medium
,
1211 IN ULONG PinDirection
)
1214 UNICODE_STRING Path
;
1215 UNICODE_STRING BasePath
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediumCache\\");
1216 UNICODE_STRING GuidString
;
1218 OBJECT_ATTRIBUTES ObjectAttributes
;
1219 BOOLEAN PathAdjusted
= FALSE
;
1222 /* first check if the medium is standard */
1223 if (IsEqualGUIDAligned(&KSMEDIUMSETID_Standard
, &Medium
->Set
) ||
1224 IsEqualGUIDAligned(&GUID_NULL
, &Medium
->Set
))
1226 /* no need to cache that */
1227 return STATUS_SUCCESS
;
1230 /* convert guid to string */
1231 Status
= RtlStringFromGUID(&Medium
->Set
, &GuidString
);
1232 if (!NT_SUCCESS(Status
))
1235 /* allocate path buffer */
1237 Path
.MaximumLength
= BasePath
.MaximumLength
+ GuidString
.MaximumLength
+ 10 * sizeof(WCHAR
);
1238 Path
.Buffer
= AllocateItem(PagedPool
, Path
.MaximumLength
);
1241 /* not enough resources */
1242 RtlFreeUnicodeString(&GuidString
);
1243 return STATUS_INSUFFICIENT_RESOURCES
;
1246 RtlAppendUnicodeStringToString(&Path
, &BasePath
);
1247 RtlAppendUnicodeStringToString(&Path
, &GuidString
);
1248 RtlAppendUnicodeToString(&Path
, L
"-");
1249 /* FIXME append real instance id */
1250 RtlAppendUnicodeToString(&Path
, L
"0");
1251 RtlAppendUnicodeToString(&Path
, L
"-");
1252 /* FIXME append real instance id */
1253 RtlAppendUnicodeToString(&Path
, L
"0");
1255 /* free guid string */
1256 RtlFreeUnicodeString(&GuidString
);
1258 /* initialize object attributes */
1259 InitializeObjectAttributes(&ObjectAttributes
, &Path
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1260 /* create the key */
1261 Status
= ZwCreateKey(&hKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1263 /* free path buffer */
1264 FreeItem(Path
.Buffer
);
1266 if (NT_SUCCESS(Status
))
1268 /* store symbolic link */
1269 if (SymbolicLink
->Buffer
[1] == L
'?' && SymbolicLink
->Buffer
[2] == L
'?')
1271 /* replace kernel path with user mode path */
1272 SymbolicLink
->Buffer
[1] = L
'\\';
1273 PathAdjusted
= TRUE
;
1277 Status
= ZwSetValueKey(hKey
, SymbolicLink
, 0, REG_DWORD
, &Value
, sizeof(ULONG
));
1281 /* restore kernel path */
1282 SymbolicLink
->Buffer
[1] = L
'?';
1298 PUNICODE_STRING RegistryPath
)
1300 return STATUS_SUCCESS
;
1307 IN PDEVICE_OBJECT DeviceObject
,
1310 PKO_OBJECT_HEADER Header
;
1311 PIO_STACK_LOCATION IoStack
;
1312 PDEVICE_EXTENSION DeviceExtension
;
1314 /* get current irp stack location */
1315 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1317 /* get ko object header */
1318 Header
= (PKO_OBJECT_HEADER
)IoStack
->FileObject
->FsContext2
;
1320 /* free ks object header */
1321 KsFreeObjectHeader(Header
->ObjectHeader
);
1323 /* free ko object header */
1326 /* get device extension */
1327 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1329 /* release bus object */
1330 KsDereferenceBusObject((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
);
1332 /* complete request */
1333 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1334 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1336 return STATUS_SUCCESS
;
1341 static KSDISPATCH_TABLE KoDispatchTable
=
1343 KsDispatchInvalidDeviceRequest
,
1344 KsDispatchInvalidDeviceRequest
,
1345 KsDispatchInvalidDeviceRequest
,
1346 KsDispatchInvalidDeviceRequest
,
1348 KsDispatchQuerySecurity
,
1349 KsDispatchSetSecurity
,
1350 KsDispatchFastIoDeviceControlFailure
,
1351 KsDispatchFastReadFailure
,
1352 KsDispatchFastReadFailure
,
1359 IN PDEVICE_OBJECT DeviceObject
,
1362 PKO_OBJECT_HEADER Header
= NULL
;
1363 PIO_STACK_LOCATION IoStack
;
1364 PKO_DRIVER_EXTENSION DriverObjectExtension
;
1367 /* get current irp stack location */
1368 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1370 if (!IoStack
->FileObject
)
1372 DPRINT1("FileObject not attached!\n");
1373 Status
= STATUS_UNSUCCESSFUL
;
1377 /* get driver object extension */
1378 DriverObjectExtension
= (PKO_DRIVER_EXTENSION
)IoGetDriverObjectExtension(DeviceObject
->DriverObject
, (PVOID
)KoDriverInitialize
);
1379 if (!DriverObjectExtension
)
1381 DPRINT1("No DriverObjectExtension!\n");
1382 Status
= STATUS_UNSUCCESSFUL
;
1386 /* allocate ko object header */
1387 Header
= (PKO_OBJECT_HEADER
)AllocateItem(NonPagedPool
, sizeof(KO_OBJECT_HEADER
));
1390 DPRINT1("failed to allocate KO_OBJECT_HEADER\n");
1391 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1395 /* initialize create item */
1396 Header
->CreateItem
.Create
= KopDispatchCreate
;
1397 RtlInitUnicodeString(&Header
->CreateItem
.ObjectClass
, KOSTRING_CreateObject
);
1400 /* now allocate the object header */
1401 Status
= KsAllocateObjectHeader(&Header
->ObjectHeader
, 1, &Header
->CreateItem
, Irp
, &KoDispatchTable
);
1402 if (!NT_SUCCESS(Status
))
1409 * extract clsid and interface id from irp
1410 * call the standard create handler
1415 IoStack
->FileObject
->FsContext2
= (PVOID
)Header
;
1417 Irp
->IoStatus
.Status
= Status
;
1418 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1424 if (Header
&& Header
->ObjectHeader
)
1425 KsFreeObjectHeader(Header
->ObjectHeader
);
1430 Irp
->IoStatus
.Status
= Status
;
1431 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1440 IN PDRIVER_OBJECT DriverObject
,
1441 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1443 NTSTATUS Status
= STATUS_DEVICE_REMOVED
;
1444 PDEVICE_OBJECT FunctionalDeviceObject
= NULL
;
1445 PDEVICE_OBJECT NextDeviceObject
;
1446 PDEVICE_EXTENSION DeviceExtension
;
1447 PKSOBJECT_CREATE_ITEM CreateItem
;
1449 /* create the device object */
1450 Status
= IoCreateDevice(DriverObject
, sizeof(DEVICE_EXTENSION
), NULL
, FILE_DEVICE_KS
, FILE_DEVICE_SECURE_OPEN
, FALSE
, &FunctionalDeviceObject
);
1451 if (!NT_SUCCESS(Status
))
1454 /* allocate the create item */
1455 CreateItem
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
));
1459 /* not enough memory */
1460 IoDeleteDevice(FunctionalDeviceObject
);
1461 return STATUS_INSUFFICIENT_RESOURCES
;
1464 /* initialize create item */
1465 CreateItem
->Create
= KopDispatchCreate
;
1466 RtlInitUnicodeString(&CreateItem
->ObjectClass
, KOSTRING_CreateObject
);
1468 /* get device extension */
1469 DeviceExtension
= (PDEVICE_EXTENSION
)FunctionalDeviceObject
->DeviceExtension
;
1471 /* now allocate the device header */
1472 Status
= KsAllocateDeviceHeader((KSDEVICE_HEADER
*)&DeviceExtension
->DeviceHeader
, 1, CreateItem
);
1473 if (!NT_SUCCESS(Status
))
1476 IoDeleteDevice(FunctionalDeviceObject
);
1477 FreeItem(CreateItem
);
1481 /* now attach to device stack */
1482 NextDeviceObject
= IoAttachDeviceToDeviceStack(FunctionalDeviceObject
, PhysicalDeviceObject
);
1483 if (NextDeviceObject
)
1485 /* store pnp base object */
1486 KsSetDevicePnpAndBaseObject((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
, NextDeviceObject
, FunctionalDeviceObject
);
1487 /* set device flags */
1488 FunctionalDeviceObject
->Flags
|= DO_DIRECT_IO
| DO_POWER_PAGABLE
;
1489 FunctionalDeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
1494 KsFreeDeviceHeader((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
);
1495 FreeItem(CreateItem
);
1496 IoDeleteDevice(FunctionalDeviceObject
);
1497 Status
= STATUS_DEVICE_REMOVED
;
1512 IN PDEVICE_OBJECT DeviceObject
)
1514 PDEVICE_EXTENSION DeviceExtension
;
1516 /* get device extension */
1517 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1519 return KsAddObjectCreateItemToDeviceHeader((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
, KopDispatchCreate
, NULL
, KOSTRING_CreateObject
, NULL
);
1529 IN PDRIVER_OBJECT DriverObject
,
1530 IN PUNICODE_STRING RegistryPathName
,
1531 IN KoCreateObjectHandler CreateObjectHandler
)
1533 PKO_DRIVER_EXTENSION DriverObjectExtension
;
1536 /* allocate driver object extension */
1537 Status
= IoAllocateDriverObjectExtension(DriverObject
, (PVOID
)KoDriverInitialize
, sizeof(KO_DRIVER_EXTENSION
), (PVOID
*)&DriverObjectExtension
);
1540 if (NT_SUCCESS(Status
))
1542 /* store create handler */
1543 DriverObjectExtension
->CreateObjectHandler
= CreateObjectHandler
;
1545 /* Setting our IRP handlers */
1546 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = KsDefaultDispatchPnp
;
1547 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KsDefaultDispatchPower
;
1548 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KsDefaultForwardIrp
;
1550 /* The driver unload routine */
1551 DriverObject
->DriverUnload
= KsNullDriverUnload
;
1553 /* The driver-supplied AddDevice */
1554 DriverObject
->DriverExtension
->AddDevice
= KopAddDevice
;
1556 /* KS handles these */
1557 DPRINT1("Setting KS function handlers\n");
1558 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CREATE
);
1559 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CLOSE
);
1560 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_DEVICE_CONTROL
);
1574 IN REFCLSID ClassId
)
1588 PKSBASIC_HEADER BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1591 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
1593 KeWaitForSingleObject(BasicHeader
->ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1605 PKSBASIC_HEADER BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1608 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
1610 KeReleaseMutex(BasicHeader
->ControlMutex
, FALSE
);
1622 IN PKSDEVICE Device
)
1624 IKsDevice
*KsDevice
;
1625 PKSIDEVICE_HEADER DeviceHeader
;
1627 DPRINT("KsAcquireDevice\n");
1628 DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
1630 /* get device interface*/
1631 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
1633 /* acquire device mutex */
1634 KsDevice
->lpVtbl
->AcquireDevice(KsDevice
);
1643 IN PKSDEVICE Device
)
1645 IKsDevice
*KsDevice
;
1646 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
1648 /* get device interface*/
1649 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
1651 /* release device mutex */
1652 KsDevice
->lpVtbl
->ReleaseDevice(KsDevice
);
1662 IN PDEVICE_OBJECT DeviceObject
)
1664 IKsDevice
*KsDevice
;
1665 PKSIDEVICE_HEADER DeviceHeader
;
1666 PDEVICE_EXTENSION DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1668 /* get device header */
1669 DeviceHeader
= DeviceExtension
->DeviceHeader
;
1671 /* get device interface*/
1672 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
1674 /* now free device header */
1675 KsFreeDeviceHeader((KSDEVICE_HEADER
)DeviceHeader
);
1677 /* release interface when available */
1680 /* delete IKsDevice interface */
1681 KsDevice
->lpVtbl
->Release(KsDevice
);
1691 KsCompletePendingRequest(
1694 PIO_STACK_LOCATION IoStack
;
1696 /* get current irp stack location */
1697 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1700 ASSERT(Irp
->IoStatus
.Status
!= STATUS_PENDING
);
1702 if (IoStack
->MajorFunction
!= IRP_MJ_CLOSE
)
1704 /* can be completed immediately */
1705 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1709 /* did close operation fail */
1710 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
1712 /* closing failed, complete irp */
1713 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1718 * delete object / device header
1719 * remove dead pin / filter instance
1727 KspSetGetBusDataCompletion(
1728 IN PDEVICE_OBJECT DeviceObject
,
1732 /* signal completion */
1733 KeSetEvent((PRKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
1735 /* more work needs be done, so dont free the irp */
1736 return STATUS_MORE_PROCESSING_REQUIRED
;
1741 KspDeviceSetGetBusData(
1742 IN PDEVICE_OBJECT DeviceObject
,
1749 PIO_STACK_LOCATION IoStack
;
1754 /* allocate the irp */
1755 Irp
= IoAllocateIrp(1, /*FIXME */
1759 return STATUS_INSUFFICIENT_RESOURCES
;
1761 /* initialize the event */
1762 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1764 /* get next stack location */
1765 IoStack
= IoGetNextIrpStackLocation(Irp
);
1767 /* setup a completion routine */
1768 IoSetCompletionRoutine(Irp
, KspSetGetBusDataCompletion
, (PVOID
)&Event
, TRUE
, TRUE
, TRUE
);
1770 /* setup parameters */
1771 IoStack
->Parameters
.ReadWriteConfig
.Buffer
= Buffer
;
1772 IoStack
->Parameters
.ReadWriteConfig
.Length
= Length
;
1773 IoStack
->Parameters
.ReadWriteConfig
.Offset
= Offset
;
1774 IoStack
->Parameters
.ReadWriteConfig
.WhichSpace
= DataType
;
1775 /* setup function code */
1776 IoStack
->MajorFunction
= IRP_MJ_PNP
;
1777 IoStack
->MinorFunction
= (bGet
? IRP_MN_READ_CONFIG
: IRP_MN_WRITE_CONFIG
);
1779 /* lets call the driver */
1780 Status
= IoCallDriver(DeviceObject
, Irp
);
1782 /* is the request still pending */
1783 if (Status
== STATUS_PENDING
)
1786 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1788 Status
= Irp
->IoStatus
.Status
;
1804 IN PKSDEVICE Device
,
1810 return KspDeviceSetGetBusData(Device
->PhysicalDeviceObject
, /* is this right? */
1811 DataType
, Buffer
, Offset
, Length
, FALSE
);
1822 IN PKSDEVICE Device
,
1828 return KspDeviceSetGetBusData(Device
->PhysicalDeviceObject
, /* is this right? */
1829 DataType
, Buffer
, Offset
, Length
, TRUE
);
1839 KsDeviceRegisterAdapterObject(
1840 IN PKSDEVICE Device
,
1841 IN PADAPTER_OBJECT AdapterObject
,
1842 IN ULONG MaxMappingsByteCount
,
1843 IN ULONG MappingTableStride
)
1845 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
1847 DeviceHeader
->AdapterObject
= AdapterObject
;
1848 DeviceHeader
->MaxMappingsByteCount
= MaxMappingsByteCount
;
1849 DeviceHeader
->MappingTableStride
= MappingTableStride
;
1863 PKSBASIC_HEADER BasicHeader
;
1865 /* get the basic header */
1866 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1868 /* type has to be either a device or a filter factory */
1869 ASSERT(BasicHeader
->Type
== KsObjectTypeDevice
|| BasicHeader
->Type
== KsObjectTypeFilterFactory
);
1871 return (PVOID
)BasicHeader
->FirstChild
.Filter
;
1883 PKSBASIC_HEADER BasicHeader
;
1885 /* get the basic header */
1886 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1888 ASSERT(BasicHeader
->Type
== KsObjectTypeDevice
|| BasicHeader
->Type
== KsObjectTypeFilterFactory
||
1889 BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
1891 return (PVOID
)BasicHeader
->Next
.Pin
;
1896 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
1897 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
1899 ULONG Index
, SubIndex
, Count
;
1902 if (!AutomationTableA
)
1903 return AutomationTableB
->MethodSetsCount
;
1905 if (!AutomationTableB
)
1906 return AutomationTableA
->MethodSetsCount
;
1909 DPRINT("AutomationTableA MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableA
->MethodItemSize
, AutomationTableA
->MethodSetsCount
);
1910 DPRINT("AutomationTableB MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableB
->MethodItemSize
, AutomationTableB
->MethodSetsCount
);
1912 if (AutomationTableA
->MethodItemSize
&& AutomationTableB
->MethodItemSize
)
1915 ASSERT(AutomationTableA
->MethodItemSize
== AutomationTableB
->MethodItemSize
);
1918 /* now iterate all property sets and compare their guids */
1919 Count
= AutomationTableA
->MethodSetsCount
;
1921 for(Index
= 0; Index
< AutomationTableB
->MethodSetsCount
; Index
++)
1923 /* set found to false */
1926 for(SubIndex
= 0; SubIndex
< AutomationTableA
->MethodSetsCount
; SubIndex
++)
1928 if (IsEqualGUIDAligned(AutomationTableB
->MethodSets
[Index
].Set
, AutomationTableA
->MethodSets
[SubIndex
].Set
))
1930 /* same property set found */
1945 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
1946 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
1948 ULONG Index
, SubIndex
, Count
;
1951 if (!AutomationTableA
)
1952 return AutomationTableB
->EventSetsCount
;
1954 if (!AutomationTableB
)
1955 return AutomationTableA
->EventSetsCount
;
1957 DPRINT("AutomationTableA EventItemSize %lu EventSetsCount %lu\n", AutomationTableA
->EventItemSize
, AutomationTableA
->EventSetsCount
);
1958 DPRINT("AutomationTableB EventItemSize %lu EventSetsCount %lu\n", AutomationTableB
->EventItemSize
, AutomationTableB
->EventSetsCount
);
1960 if (AutomationTableA
->EventItemSize
&& AutomationTableB
->EventItemSize
)
1963 ASSERT(AutomationTableA
->EventItemSize
== AutomationTableB
->EventItemSize
);
1966 /* now iterate all Event sets and compare their guids */
1967 Count
= AutomationTableA
->EventSetsCount
;
1969 for(Index
= 0; Index
< AutomationTableB
->EventSetsCount
; Index
++)
1971 /* set found to false */
1974 for(SubIndex
= 0; SubIndex
< AutomationTableA
->EventSetsCount
; SubIndex
++)
1976 if (IsEqualGUIDAligned(AutomationTableB
->EventSets
[Index
].Set
, AutomationTableA
->EventSets
[SubIndex
].Set
))
1978 /* same Event set found */
1993 KspCountPropertySets(
1994 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
1995 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
1997 ULONG Index
, SubIndex
, Count
;
2000 if (!AutomationTableA
)
2001 return AutomationTableB
->PropertySetsCount
;
2003 if (!AutomationTableB
)
2004 return AutomationTableA
->PropertySetsCount
;
2007 DPRINT("AutomationTableA PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableA
->PropertyItemSize
, AutomationTableA
->PropertySetsCount
);
2008 DPRINT("AutomationTableB PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableB
->PropertyItemSize
, AutomationTableB
->PropertySetsCount
);
2009 ASSERT(AutomationTableA
->PropertyItemSize
== AutomationTableB
->PropertyItemSize
);
2011 /* now iterate all property sets and compare their guids */
2012 Count
= AutomationTableA
->PropertySetsCount
;
2014 for(Index
= 0; Index
< AutomationTableB
->PropertySetsCount
; Index
++)
2016 /* set found to false */
2019 for(SubIndex
= 0; SubIndex
< AutomationTableA
->PropertySetsCount
; SubIndex
++)
2021 if (IsEqualGUIDAligned(AutomationTableB
->PropertySets
[Index
].Set
, AutomationTableA
->PropertySets
[SubIndex
].Set
))
2023 /* same property set found */
2038 OUT PKSAUTOMATION_TABLE Table
,
2039 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2040 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
2042 ULONG Index
, SubIndex
, Count
;
2045 if (!AutomationTableA
)
2047 /* copy of property set */
2048 RtlMoveMemory((PVOID
)Table
->MethodSets
, AutomationTableB
->MethodSets
, sizeof(KSMETHOD_SET
) * AutomationTableB
->MethodSetsCount
);
2049 return STATUS_SUCCESS
;
2051 else if (!AutomationTableB
)
2053 /* copy of property set */
2054 RtlMoveMemory((PVOID
)Table
->MethodSets
, AutomationTableA
->MethodSets
, sizeof(KSMETHOD_SET
) * AutomationTableA
->MethodSetsCount
);
2055 return STATUS_SUCCESS
;
2058 /* first copy all property items from dominant table */
2059 RtlMoveMemory((PVOID
)Table
->MethodSets
, AutomationTableA
->MethodSets
, sizeof(KSMETHOD_SET
) * AutomationTableA
->MethodSetsCount
);
2061 Count
= AutomationTableA
->MethodSetsCount
;
2063 /* now copy entries which aren't available in the dominant table */
2064 for(Index
= 0; Index
< AutomationTableB
->MethodSetsCount
; Index
++)
2066 /* set found to false */
2069 for(SubIndex
= 0; SubIndex
< AutomationTableA
->MethodSetsCount
; SubIndex
++)
2071 if (IsEqualGUIDAligned(AutomationTableB
->MethodSets
[Index
].Set
, AutomationTableA
->MethodSets
[SubIndex
].Set
))
2073 /* same property set found */
2081 /* copy new property item set */
2082 RtlMoveMemory((PVOID
)&Table
->MethodSets
[Count
], &AutomationTableB
->MethodSets
[Index
], sizeof(KSMETHOD_SET
));
2087 return STATUS_SUCCESS
;
2092 OUT PKSPROPERTY_SET OutPropertySet
,
2093 IN PKSPROPERTY_ITEM PropertyItem
,
2094 IN ULONG PropertyItemSize
)
2096 PKSPROPERTY_ITEM CurrentPropertyItem
;
2099 // check if the property item is already present
2100 CurrentPropertyItem
= (PKSPROPERTY_ITEM
)OutPropertySet
->PropertyItem
;
2101 for(Index
= 0; Index
< OutPropertySet
->PropertiesCount
; Index
++)
2103 if (CurrentPropertyItem
->PropertyId
== PropertyItem
->PropertyId
)
2105 // item already present
2110 CurrentPropertyItem
= (PKSPROPERTY_ITEM
)((ULONG_PTR
)CurrentPropertyItem
+ PropertyItemSize
);
2113 RtlCopyMemory(CurrentPropertyItem
, PropertyItem
, PropertyItemSize
);
2114 OutPropertySet
->PropertiesCount
++;
2118 KspMergePropertySet(
2119 OUT PKSAUTOMATION_TABLE Table
,
2120 OUT PKSPROPERTY_SET OutPropertySet
,
2121 IN PKSPROPERTY_SET PropertySetA
,
2122 IN PKSPROPERTY_SET PropertySetB
,
2123 IN KSOBJECT_BAG Bag OPTIONAL
)
2125 ULONG PropertyCount
, Index
;
2126 PKSPROPERTY_ITEM PropertyItem
, CurrentPropertyItem
;
2130 PropertyCount
= PropertySetA
->PropertiesCount
+ PropertySetB
->PropertiesCount
;
2133 PropertyItem
= AllocateItem(NonPagedPool
, Table
->PropertyItemSize
* PropertyCount
);
2135 return STATUS_INSUFFICIENT_RESOURCES
;
2139 /* add table to object bag */
2140 Status
= KsAddItemToObjectBag(Bag
, PropertyItem
, NULL
);
2141 /* check for success */
2142 if (!NT_SUCCESS(Status
))
2150 // copy entries from dominant table
2151 RtlCopyMemory(PropertyItem
, PropertySetA
->PropertyItem
, Table
->PropertyItemSize
* PropertySetA
->PropertiesCount
);
2153 // init property set
2154 OutPropertySet
->PropertiesCount
= PropertySetA
->PropertiesCount
;
2155 OutPropertySet
->PropertyItem
= PropertyItem
;
2157 // copy other entries
2158 CurrentPropertyItem
= (PKSPROPERTY_ITEM
)PropertySetB
->PropertyItem
;
2159 for(Index
= 0; Index
< PropertySetB
->PropertiesCount
; Index
++)
2163 KspAddPropertyItem(OutPropertySet
, CurrentPropertyItem
, Table
->PropertyItemSize
);
2166 CurrentPropertyItem
= (PKSPROPERTY_ITEM
)((ULONG_PTR
)CurrentPropertyItem
+ Table
->PropertyItemSize
);
2170 return STATUS_SUCCESS
;
2175 KspCopyPropertySets(
2176 OUT PKSAUTOMATION_TABLE Table
,
2177 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2178 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
,
2179 IN KSOBJECT_BAG Bag OPTIONAL
)
2181 ULONG Index
, SubIndex
, Count
;
2185 if (!AutomationTableA
)
2187 /* copy of property set */
2188 RtlMoveMemory((PVOID
)Table
->PropertySets
, AutomationTableB
->PropertySets
, sizeof(KSPROPERTY_SET
) * AutomationTableB
->PropertySetsCount
);
2189 return STATUS_SUCCESS
;
2191 else if (!AutomationTableB
)
2193 /* copy of property set */
2194 RtlMoveMemory((PVOID
)Table
->PropertySets
, AutomationTableA
->PropertySets
, sizeof(KSPROPERTY_SET
) * AutomationTableA
->PropertySetsCount
);
2195 return STATUS_SUCCESS
;
2198 /* first copy all property items from dominant table */
2199 RtlMoveMemory((PVOID
)Table
->PropertySets
, AutomationTableA
->PropertySets
, sizeof(KSPROPERTY_SET
) * AutomationTableA
->PropertySetsCount
);
2201 Count
= AutomationTableA
->PropertySetsCount
;
2203 /* now copy entries which aren't available in the dominant table */
2204 for(Index
= 0; Index
< AutomationTableB
->PropertySetsCount
; Index
++)
2206 /* set found to false */
2209 for(SubIndex
= 0; SubIndex
< AutomationTableA
->PropertySetsCount
; SubIndex
++)
2211 if (IsEqualGUIDAligned(AutomationTableB
->PropertySets
[Index
].Set
, AutomationTableA
->PropertySets
[SubIndex
].Set
))
2213 /* same property set found */
2221 /* copy new property item set */
2222 RtlMoveMemory((PVOID
)&Table
->PropertySets
[Count
], &AutomationTableB
->PropertySets
[Index
], sizeof(KSPROPERTY_SET
));
2227 // merge property sets
2228 Status
= KspMergePropertySet(Table
, (PKSPROPERTY_SET
)&Table
->PropertySets
[SubIndex
], (PKSPROPERTY_SET
)&AutomationTableA
->PropertySets
[SubIndex
], (PKSPROPERTY_SET
)&AutomationTableB
->PropertySets
[Index
], Bag
);
2229 if (!NT_SUCCESS(Status
))
2232 DPRINT1("[KS] Failed to merge %x\n", Status
);
2238 return STATUS_SUCCESS
;
2243 OUT PKSAUTOMATION_TABLE Table
,
2244 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2245 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
2247 ULONG Index
, SubIndex
, Count
;
2250 if (!AutomationTableA
)
2252 /* copy of Event set */
2253 RtlMoveMemory((PVOID
)Table
->EventSets
, AutomationTableB
->EventSets
, sizeof(KSEVENT_SET
) * AutomationTableB
->EventSetsCount
);
2254 return STATUS_SUCCESS
;
2256 else if (!AutomationTableB
)
2258 /* copy of Event set */
2259 RtlMoveMemory((PVOID
)Table
->EventSets
, AutomationTableA
->EventSets
, sizeof(KSEVENT_SET
) * AutomationTableA
->EventSetsCount
);
2260 return STATUS_SUCCESS
;
2263 /* first copy all Event items from dominant table */
2264 RtlMoveMemory((PVOID
)Table
->EventSets
, AutomationTableA
->EventSets
, sizeof(KSEVENT_SET
) * AutomationTableA
->EventSetsCount
);
2266 Count
= AutomationTableA
->EventSetsCount
;
2268 /* now copy entries which aren't available in the dominant table */
2269 for(Index
= 0; Index
< AutomationTableB
->EventSetsCount
; Index
++)
2271 /* set found to false */
2274 for(SubIndex
= 0; SubIndex
< AutomationTableA
->EventSetsCount
; SubIndex
++)
2276 if (IsEqualGUIDAligned(AutomationTableB
->EventSets
[Index
].Set
, AutomationTableA
->EventSets
[SubIndex
].Set
))
2278 /* same Event set found */
2286 /* copy new Event item set */
2287 RtlMoveMemory((PVOID
)&Table
->EventSets
[Count
], &AutomationTableB
->EventSets
[Index
], sizeof(KSEVENT_SET
));
2292 return STATUS_SUCCESS
;
2301 KsMergeAutomationTables(
2302 OUT PKSAUTOMATION_TABLE
*AutomationTableAB
,
2303 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2304 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
,
2305 IN KSOBJECT_BAG Bag OPTIONAL
)
2307 PKSAUTOMATION_TABLE Table
;
2308 NTSTATUS Status
= STATUS_SUCCESS
;
2310 if (!AutomationTableA
&& !AutomationTableB
)
2312 /* nothing to merge */
2313 return STATUS_SUCCESS
;
2316 /* allocate an automation table */
2317 Table
= AllocateItem(NonPagedPool
, sizeof(KSAUTOMATION_TABLE
));
2319 return STATUS_INSUFFICIENT_RESOURCES
;
2323 /* add table to object bag */
2324 Status
= KsAddItemToObjectBag(Bag
, Table
, NULL
);
2325 /* check for success */
2326 if (!NT_SUCCESS(Status
))
2334 /* count property sets */
2335 Table
->PropertySetsCount
= KspCountPropertySets(AutomationTableA
, AutomationTableB
);
2337 if (Table
->PropertySetsCount
)
2339 if (AutomationTableA
)
2341 /* use item size from dominant automation table */
2342 Table
->PropertyItemSize
= AutomationTableA
->PropertyItemSize
;
2346 /* use item size from 2nd automation table */
2347 Table
->PropertyItemSize
= AutomationTableB
->PropertyItemSize
;
2350 if (AutomationTableA
&& AutomationTableB
)
2352 // FIXME handle different propery item sizes
2353 ASSERT(AutomationTableA
->PropertyItemSize
== AutomationTableB
->PropertyItemSize
);
2356 /* now allocate the property sets */
2357 Table
->PropertySets
= AllocateItem(NonPagedPool
, sizeof(KSPROPERTY_SET
) * Table
->PropertySetsCount
);
2359 if (!Table
->PropertySets
)
2361 /* not enough memory */
2367 /* add set to property bag */
2368 Status
= KsAddItemToObjectBag(Bag
, (PVOID
)Table
->PropertySets
, NULL
);
2369 /* check for success */
2370 if (!NT_SUCCESS(Status
))
2376 /* now copy the property sets */
2377 Status
= KspCopyPropertySets(Table
, AutomationTableA
, AutomationTableB
, Bag
);
2378 if(!NT_SUCCESS(Status
))
2383 /* now count the method sets */
2384 Table
->MethodSetsCount
= KspCountMethodSets(AutomationTableA
, AutomationTableB
);
2386 if (Table
->MethodSetsCount
)
2388 if (AutomationTableA
)
2390 /* use item size from dominant automation table */
2391 Table
->MethodItemSize
= AutomationTableA
->MethodItemSize
;
2395 /* use item size from 2nd automation table */
2396 Table
->MethodItemSize
= AutomationTableB
->MethodItemSize
;
2399 /* now allocate the property sets */
2400 Table
->MethodSets
= AllocateItem(NonPagedPool
, sizeof(KSMETHOD_SET
) * Table
->MethodSetsCount
);
2402 if (!Table
->MethodSets
)
2404 /* not enough memory */
2410 /* add set to property bag */
2411 Status
= KsAddItemToObjectBag(Bag
, (PVOID
)Table
->MethodSets
, NULL
);
2412 /* check for success */
2413 if (!NT_SUCCESS(Status
))
2419 /* now copy the property sets */
2420 Status
= KspCopyMethodSets(Table
, AutomationTableA
, AutomationTableB
);
2421 if(!NT_SUCCESS(Status
))
2426 /* now count the event sets */
2427 Table
->EventSetsCount
= KspCountEventSets(AutomationTableA
, AutomationTableB
);
2429 if (Table
->EventSetsCount
)
2431 if (AutomationTableA
)
2433 /* use item size from dominant automation table */
2434 Table
->EventItemSize
= AutomationTableA
->EventItemSize
;
2438 /* use item size from 2nd automation table */
2439 Table
->EventItemSize
= AutomationTableB
->EventItemSize
;
2442 /* now allocate the property sets */
2443 Table
->EventSets
= AllocateItem(NonPagedPool
, sizeof(KSEVENT_SET
) * Table
->EventSetsCount
);
2445 if (!Table
->EventSets
)
2447 /* not enough memory */
2453 /* add set to property bag */
2454 Status
= KsAddItemToObjectBag(Bag
, (PVOID
)Table
->EventSets
, NULL
);
2455 /* check for success */
2456 if (!NT_SUCCESS(Status
))
2462 /* now copy the property sets */
2463 Status
= KspCopyEventSets(Table
, AutomationTableA
, AutomationTableB
);
2464 if(!NT_SUCCESS(Status
))
2469 *AutomationTableAB
= Table
;
2478 if (Table
->PropertySets
)
2480 /* clean property sets */
2481 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, (PVOID
)Table
->PropertySets
, TRUE
)))
2482 FreeItem((PVOID
)Table
->PropertySets
);
2485 if (Table
->MethodSets
)
2487 /* clean property sets */
2488 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, (PVOID
)Table
->MethodSets
, TRUE
)))
2489 FreeItem((PVOID
)Table
->MethodSets
);
2492 if (Table
->EventSets
)
2494 /* clean property sets */
2495 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, (PVOID
)Table
->EventSets
, TRUE
)))
2496 FreeItem((PVOID
)Table
->EventSets
);
2499 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, Table
, TRUE
)))
2503 return STATUS_INSUFFICIENT_RESOURCES
;
2512 KsRegisterAggregatedClientUnknown(
2514 IN PUNKNOWN ClientUnknown
)
2516 PKSBASIC_HEADER BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
2519 ASSERT(BasicHeader
->Type
== KsObjectTypeDevice
|| BasicHeader
->Type
== KsObjectTypeFilterFactory
||
2520 BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
2522 if (BasicHeader
->ClientAggregate
)
2524 /* release existing aggregate */
2525 BasicHeader
->ClientAggregate
->lpVtbl
->Release(BasicHeader
->ClientAggregate
);
2528 /* increment reference count */
2529 ClientUnknown
->lpVtbl
->AddRef(ClientUnknown
);
2531 /* store client aggregate */
2532 BasicHeader
->ClientAggregate
= ClientUnknown
;
2534 /* return objects outer unknown */
2535 return BasicHeader
->OuterUnknown
;
2543 KsRegisterFilterWithNoKSPins(
2544 IN PDEVICE_OBJECT DeviceObject
,
2545 IN
const GUID
* InterfaceClassGUID
,
2547 IN BOOL
* PinDirection
,
2548 IN KSPIN_MEDIUM
* MediumList
,
2549 IN GUID
* CategoryList OPTIONAL
)
2553 PWSTR SymbolicLinkList
;
2556 UNICODE_STRING InterfaceString
;
2557 //UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
2559 if (!InterfaceClassGUID
|| !PinCount
|| !PinDirection
|| !MediumList
)
2561 /* all these parameters are required */
2562 return STATUS_INVALID_PARAMETER
;
2565 /* calculate filter data value size */
2566 Size
= PinCount
* sizeof(KSPIN_MEDIUM
);
2569 /* add category list */
2570 Size
+= PinCount
* sizeof(GUID
);
2573 /* FIXME generate filter data blob */
2576 /* get symbolic link list */
2577 Status
= IoGetDeviceInterfaces(InterfaceClassGUID
, DeviceObject
, DEVICE_INTERFACE_INCLUDE_NONACTIVE
, &SymbolicLinkList
);
2578 if (NT_SUCCESS(Status
))
2580 /* initialize first symbolic link */
2581 RtlInitUnicodeString(&InterfaceString
, SymbolicLinkList
);
2583 /* open first device interface registry key */
2584 Status
= IoOpenDeviceInterfaceRegistryKey(&InterfaceString
, GENERIC_WRITE
, &hKey
);
2586 if (NT_SUCCESS(Status
))
2588 /* write filter data */
2589 //Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size);
2597 /* update medium cache */
2598 for(Index
= 0; Index
< PinCount
; Index
++)
2600 KsCacheMedium(&InterfaceString
, &MediumList
[Index
], PinDirection
[Index
]);
2604 /* free the symbolic link list */
2605 FreeItem(SymbolicLinkList
);