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
,
72 PKSIDEVICE_HEADER Header
= (PKSIDEVICE_HEADER
)DevHeader
;
74 KeEnterCriticalRegion();
78 Status
= ExAcquireResourceExclusiveLite(&Header
->SecurityLock
, TRUE
);
82 Status
= ExAcquireResourceSharedLite(&Header
->SecurityLock
, TRUE
);
92 KsReleaseDeviceSecurityLock(
93 IN KSDEVICE_HEADER DevHeader
)
95 PKSIDEVICE_HEADER Header
= (PKSIDEVICE_HEADER
)DevHeader
;
97 DPRINT("KsReleaseDevice\n");
99 ExReleaseResourceLite(&Header
->SecurityLock
);
100 KeLeaveCriticalRegion();
109 KsDefaultDispatchPnp(
110 IN PDEVICE_OBJECT DeviceObject
,
113 PDEVICE_EXTENSION DeviceExtension
;
114 PKSIDEVICE_HEADER DeviceHeader
;
115 PIO_STACK_LOCATION IoStack
;
116 PDEVICE_OBJECT PnpDeviceObject
;
120 /* get current irp stack */
121 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
123 /* caller wants to add the target device */
124 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
126 /* get device header */
127 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
129 /* backup PnpBaseObject */
130 PnpDeviceObject
= DeviceHeader
->PnpDeviceObject
;
133 /* backup minor function code */
134 MinorFunction
= IoStack
->MinorFunction
;
136 if(MinorFunction
== IRP_MN_REMOVE_DEVICE
)
138 /* remove the device */
139 KsFreeDeviceHeader((KSDEVICE_HEADER
)DeviceHeader
);
142 /* skip current irp stack */
143 IoSkipCurrentIrpStackLocation(Irp
);
145 /* call attached pnp device object */
146 Status
= IoCallDriver(PnpDeviceObject
, Irp
);
148 if (MinorFunction
== IRP_MN_REMOVE_DEVICE
)
151 IoDetachDevice(PnpDeviceObject
);
153 IoDeleteDevice(DeviceObject
);
165 KsDefaultDispatchPower(
166 IN PDEVICE_OBJECT DeviceObject
,
169 PDEVICE_EXTENSION DeviceExtension
;
170 PKSIDEVICE_HEADER DeviceHeader
;
171 PKSIOBJECT_HEADER ObjectHeader
;
172 PIO_STACK_LOCATION IoStack
;
173 PLIST_ENTRY ListEntry
;
176 /* get current irp stack */
177 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
179 /* caller wants to add the target device */
180 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
182 /* get device header */
183 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
187 /* loop our power dispatch list and call registered notification functions */
188 ListEntry
= DeviceHeader
->PowerDispatchList
.Flink
;
190 while(ListEntry
!= &DeviceHeader
->PowerDispatchList
)
192 /* get object header */
193 ObjectHeader
= (PKSIOBJECT_HEADER
)CONTAINING_RECORD(ListEntry
, KSIOBJECT_HEADER
, PowerDispatchEntry
);
195 /* does it have still a cb */
196 if (ObjectHeader
->PowerDispatch
)
198 /* call the power cb */
199 Status
= ObjectHeader
->PowerDispatch(ObjectHeader
->PowerContext
, Irp
);
200 ASSERT(NT_SUCCESS(Status
));
203 /* iterate to next entry */
204 ListEntry
= ListEntry
->Flink
;
207 /* start next power irp */
208 PoStartNextPowerIrp(Irp
);
210 /* skip current irp stack location */
211 IoSkipCurrentIrpStackLocation(Irp
);
214 Status
= PoCallDriver(DeviceHeader
->PnpDeviceObject
, Irp
);
227 IN PDEVICE_OBJECT DeviceObject
,
230 PDEVICE_EXTENSION DeviceExtension
;
231 PKSIDEVICE_HEADER DeviceHeader
;
232 PIO_STACK_LOCATION IoStack
;
235 /* get current irp stack */
236 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
238 /* caller wants to add the target device */
239 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
241 /* get device header */
242 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
244 /* forward the request to the PDO */
245 Status
= IoCallDriver(DeviceHeader
->PnpDeviceObject
, Irp
);
256 KsSetDevicePnpAndBaseObject(
257 IN KSDEVICE_HEADER Header
,
258 IN PDEVICE_OBJECT PnpDeviceObject
,
259 IN PDEVICE_OBJECT BaseDevice
)
261 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
263 DeviceHeader
->PnpDeviceObject
= PnpDeviceObject
;
264 DeviceHeader
->BaseDevice
= BaseDevice
;
273 KsQueryDevicePnpObject(
274 IN KSDEVICE_HEADER Header
)
276 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
278 /* return PnpDeviceObject */
279 return DeviceHeader
->PnpDeviceObject
;
289 KsQueryObjectAccessMask(
290 IN KSOBJECT_HEADER Header
)
292 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
294 /* return access mask */
295 return ObjectHeader
->AccessMask
;
305 KsRecalculateStackDepth(
306 IN KSDEVICE_HEADER Header
,
307 IN BOOLEAN ReuseStackLocation
)
320 IN KSOBJECT_HEADER Header
,
321 IN KSTARGET_STATE TargetState
)
323 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)Header
;
325 /* set target state */
326 DeviceHeader
->TargetState
= TargetState
;
335 KsSetTargetDeviceObject(
336 IN KSOBJECT_HEADER Header
,
337 IN PDEVICE_OBJECT TargetDevice OPTIONAL
)
339 PDEVICE_EXTENSION DeviceExtension
;
340 PKSIDEVICE_HEADER DeviceHeader
;
341 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
343 if(ObjectHeader
->TargetDevice
)
345 /* there is already a target device set */
348 /* caller wants to remove the target device */
349 DeviceExtension
= (PDEVICE_EXTENSION
)ObjectHeader
->TargetDevice
->DeviceExtension
;
351 /* get device header */
352 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
355 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
, FALSE
);
358 RemoveEntryList(&ObjectHeader
->TargetDeviceListEntry
);
360 /* remove device pointer */
361 ObjectHeader
->TargetDevice
= NULL
;
364 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
);
369 /* no target device yet set */
372 /* caller wants to add the target device */
373 DeviceExtension
= (PDEVICE_EXTENSION
)TargetDevice
->DeviceExtension
;
375 /* get device header */
376 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
379 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
, FALSE
);
381 /* insert list entry */
382 InsertTailList(&DeviceHeader
->TargetDeviceList
, &ObjectHeader
->TargetDeviceListEntry
);
384 /* store target device */
385 ObjectHeader
->TargetDevice
= TargetDevice
;
388 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
);
401 IN KSOBJECT_HEADER Header
,
402 IN PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL
,
403 IN PVOID PowerContext OPTIONAL
)
405 PDEVICE_EXTENSION DeviceExtension
;
406 PKSIDEVICE_HEADER DeviceHeader
;
407 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
409 /* caller wants to add the target device */
410 DeviceExtension
= (PDEVICE_EXTENSION
)ObjectHeader
->ParentDeviceObject
->DeviceExtension
;
412 /* get device header */
413 DeviceHeader
= (PKSIDEVICE_HEADER
)DeviceExtension
->DeviceHeader
;
416 KsAcquireDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
, FALSE
);
420 /* add power dispatch entry */
421 InsertTailList(&DeviceHeader
->PowerDispatchList
, &ObjectHeader
->PowerDispatchEntry
);
423 /* store function and context */
424 ObjectHeader
->PowerDispatch
= PowerDispatch
;
425 ObjectHeader
->PowerContext
= PowerContext
;
429 /* remove power dispatch entry */
430 RemoveEntryList(&ObjectHeader
->PowerDispatchEntry
);
432 /* store function and context */
433 ObjectHeader
->PowerDispatch
= NULL
;
434 ObjectHeader
->PowerContext
= NULL
;
439 KsReleaseDeviceSecurityLock((KSDEVICE_HEADER
)DeviceHeader
);
447 PKSOBJECT_CREATE_ITEM
449 KsQueryObjectCreateItem(
450 IN KSOBJECT_HEADER Header
)
452 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
)Header
;
453 return ObjectHeader
->OriginalCreateItem
;
457 KspAddCreateItemToList(
458 OUT PLIST_ENTRY ListHead
,
460 IN PKSOBJECT_CREATE_ITEM ItemsList
)
463 PCREATE_ITEM_ENTRY Entry
;
466 for(Index
= 0; Index
< ItemsCount
; Index
++)
469 Entry
= AllocateItem(NonPagedPool
, sizeof(CREATE_ITEM_ENTRY
));
473 return STATUS_INSUFFICIENT_RESOURCES
;
476 /* initialize entry */
477 InitializeListHead(&Entry
->ObjectItemList
);
478 Entry
->CreateItem
= &ItemsList
[Index
];
479 Entry
->ReferenceCount
= 0;
480 Entry
->ItemFreeCallback
= NULL
;
482 InsertTailList(ListHead
, &Entry
->Entry
);
484 return STATUS_SUCCESS
;
489 PLIST_ENTRY ListHead
)
491 PCREATE_ITEM_ENTRY Entry
;
493 while(!IsListEmpty(ListHead
))
495 /* remove create item from list */
496 Entry
= (PCREATE_ITEM_ENTRY
)CONTAINING_RECORD(RemoveHeadList(ListHead
), CREATE_ITEM_ENTRY
, Entry
);
498 /* caller shouldnt have any references */
499 //ASSERT(Entry->ReferenceCount == 0);
500 //ASSERT(IsListEmpty(&Entry->ObjectItemList));
502 /* does the creator wish notification */
503 if (Entry
->ItemFreeCallback
)
506 Entry
->ItemFreeCallback(Entry
->CreateItem
);
509 /* free create item entry */
521 KsAllocateDeviceHeader(
522 OUT KSDEVICE_HEADER
* OutHeader
,
524 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL
)
526 NTSTATUS Status
= STATUS_SUCCESS
;
527 PKSIDEVICE_HEADER Header
;
530 return STATUS_INVALID_PARAMETER
;
532 /* allocate a device header */
533 Header
= AllocateItem(PagedPool
, sizeof(KSIDEVICE_HEADER
));
535 /* check for success */
537 return STATUS_INSUFFICIENT_RESOURCES
;
539 /* clear all memory */
540 RtlZeroMemory(Header
, sizeof(KSIDEVICE_HEADER
));
542 /* initialize device mutex */
543 KeInitializeMutex(&Header
->DeviceMutex
, 0);
545 /* initialize target device list */
546 InitializeListHead(&Header
->TargetDeviceList
);
547 /* initialize power dispatch list */
548 InitializeListHead(&Header
->PowerDispatchList
);
549 /* initialize object bag lists */
550 InitializeListHead(&Header
->ObjectBags
);
552 /* initialize create item list */
553 InitializeListHead(&Header
->ItemList
);
555 /* initialize basic header */
556 Header
->BasicHeader
.Type
= KsObjectTypeDevice
;
557 Header
->BasicHeader
.KsDevice
= &Header
->KsDevice
;
558 Header
->BasicHeader
.Parent
.KsDevice
= &Header
->KsDevice
;
560 /* are there any create items provided */
561 if (ItemsCount
&& ItemsList
)
563 Status
= KspAddCreateItemToList(&Header
->ItemList
, ItemsCount
, ItemsList
);
565 if (NT_SUCCESS(Status
))
567 /* store item count */
568 Header
->ItemListCount
= ItemsCount
;
572 /* release create items */
573 KspFreeCreateItems(&Header
->ItemList
);
590 IN KSDEVICE_HEADER DevHeader
)
592 PKSIDEVICE_HEADER Header
;
594 Header
= (PKSIDEVICE_HEADER
)DevHeader
;
599 KspFreeCreateItems(&Header
->ItemList
);
609 KsAllocateObjectHeader(
610 OUT KSOBJECT_HEADER
*Header
,
612 IN PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL
,
614 IN KSDISPATCH_TABLE
* Table
)
616 PIO_STACK_LOCATION IoStack
;
617 PDEVICE_EXTENSION DeviceExtension
;
618 PKSIDEVICE_HEADER DeviceHeader
;
619 PKSIOBJECT_HEADER ObjectHeader
;
620 PKSOBJECT_CREATE_ITEM CreateItem
;
624 return STATUS_INVALID_PARAMETER_1
;
627 return STATUS_INVALID_PARAMETER_4
;
630 return STATUS_INVALID_PARAMETER_5
;
632 /* get current stack location */
633 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
634 /* get device extension */
635 DeviceExtension
= (PDEVICE_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
636 /* get device header */
637 DeviceHeader
= DeviceExtension
->DeviceHeader
;
640 ASSERT(IoStack
->FileObject
);
641 /* check for an file object */
643 /* allocate the object header */
644 ObjectHeader
= AllocateItem(NonPagedPool
, sizeof(KSIOBJECT_HEADER
));
646 return STATUS_INSUFFICIENT_RESOURCES
;
648 /* initialize object header */
649 RtlZeroMemory(ObjectHeader
, sizeof(KSIOBJECT_HEADER
));
651 /* initialize create item list */
652 InitializeListHead(&ObjectHeader
->ItemList
);
654 /* get create item */
655 CreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
657 /* do we have a name */
658 if (IoStack
->FileObject
->FileName
.Buffer
)
660 /* copy object class */
661 ObjectHeader
->ObjectClass
.MaximumLength
= IoStack
->FileObject
->FileName
.MaximumLength
;
662 ObjectHeader
->ObjectClass
.Buffer
= AllocateItem(NonPagedPool
, ObjectHeader
->ObjectClass
.MaximumLength
);
663 if (!ObjectHeader
->ObjectClass
.Buffer
)
665 FreeItem(ObjectHeader
);
666 return STATUS_INSUFFICIENT_RESOURCES
;
668 RtlCopyUnicodeString(&ObjectHeader
->ObjectClass
, &IoStack
->FileObject
->FileName
);
671 /* copy dispatch table */
672 RtlCopyMemory(&ObjectHeader
->DispatchTable
, Table
, sizeof(KSDISPATCH_TABLE
));
674 /* store create items */
675 if (ItemsCount
&& ItemsList
)
677 Status
= KspAddCreateItemToList(&ObjectHeader
->ItemList
, ItemsCount
, ItemsList
);
679 if (NT_SUCCESS(Status
))
681 /* store item count */
682 ObjectHeader
->ItemListCount
= ItemsCount
;
687 KsFreeObjectHeader(ObjectHeader
);
691 /* store the object in the file object */
692 IoStack
->FileObject
->FsContext2
= ObjectHeader
;
694 /* store parent device */
695 ObjectHeader
->ParentDeviceObject
= IoGetRelatedDeviceObject(IoStack
->FileObject
);
697 /* store originating create item */
698 ObjectHeader
->OriginalCreateItem
= KSCREATE_ITEM_IRP_STORAGE(Irp
);
700 /* FIXME store access mask see KsQueryObjectAccessMask */
701 ObjectHeader
->AccessMask
= IoStack
->Parameters
.Create
.SecurityContext
->DesiredAccess
;
705 *Header
= ObjectHeader
;
707 DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader
->ObjectClass
.Buffer
, IoStack
->FileObject
, ObjectHeader
);
709 return STATUS_SUCCESS
;
722 PKSIOBJECT_HEADER ObjectHeader
= (PKSIOBJECT_HEADER
) Header
;
724 DPRINT("KsFreeObjectHeader Header %p Class %wZ\n", Header
, &ObjectHeader
->ObjectClass
);
726 if (ObjectHeader
->ObjectClass
.Buffer
)
728 /* release object class buffer */
729 FreeItem(ObjectHeader
->ObjectClass
.Buffer
);
732 if (ObjectHeader
->Unknown
)
734 /* release associated object */
735 ObjectHeader
->Unknown
->lpVtbl
->Release(ObjectHeader
->Unknown
);
738 /* free create items */
739 KspFreeCreateItems(&ObjectHeader
->ItemList
);
741 /* free object header */
742 FreeItem(ObjectHeader
);
747 KspAddObjectCreateItemToList(
748 PLIST_ENTRY ListHead
,
749 IN PDRIVER_DISPATCH Create
,
751 IN PWCHAR ObjectClass
,
752 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
755 PCREATE_ITEM_ENTRY CreateEntry
;
757 /* point to first entry */
758 Entry
= ListHead
->Flink
;
760 while(Entry
!= ListHead
)
762 /* get create entry */
763 CreateEntry
= (PCREATE_ITEM_ENTRY
)CONTAINING_RECORD(Entry
, CREATE_ITEM_ENTRY
, Entry
);
764 /* if the create item has no create routine, then it is free to use */
765 if (CreateEntry
->CreateItem
->Create
== NULL
)
768 ASSERT(IsListEmpty(&CreateEntry
->ObjectItemList
));
769 ASSERT(CreateEntry
->ReferenceCount
== 0);
771 CreateEntry
->CreateItem
->Context
= Context
;
772 CreateEntry
->CreateItem
->Create
= Create
;
773 RtlInitUnicodeString(&CreateEntry
->CreateItem
->ObjectClass
, ObjectClass
);
774 CreateEntry
->CreateItem
->SecurityDescriptor
= SecurityDescriptor
;
776 return STATUS_SUCCESS
;
779 if (!wcsicmp(ObjectClass
, CreateEntry
->CreateItem
->ObjectClass
.Buffer
))
781 /* the same object class already exists */
782 return STATUS_OBJECT_NAME_COLLISION
;
785 /* iterate to next entry */
786 Entry
= Entry
->Flink
;
788 return STATUS_ALLOTTED_SPACE_EXCEEDED
;
797 KsAddObjectCreateItemToDeviceHeader(
798 IN KSDEVICE_HEADER DevHeader
,
799 IN PDRIVER_DISPATCH Create
,
801 IN PWCHAR ObjectClass
,
802 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
804 PKSIDEVICE_HEADER Header
;
807 Header
= (PKSIDEVICE_HEADER
)DevHeader
;
809 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
811 /* check if a device header has been provided */
813 return STATUS_INVALID_PARAMETER_1
;
815 /* check if a create item has been provided */
817 return STATUS_INVALID_PARAMETER_2
;
819 /* check if a object class has been provided */
821 return STATUS_INVALID_PARAMETER_4
;
823 /* let others do the work */
824 Status
= KspAddObjectCreateItemToList(&Header
->ItemList
, Create
, Context
, ObjectClass
, SecurityDescriptor
);
826 if (NT_SUCCESS(Status
))
828 /* increment create item count */
829 InterlockedIncrement(&Header
->ItemListCount
);
831 DPRINT("KsAddObjectCreateItemToDeviceHeader Status %x\n", Status
);
841 KsAddObjectCreateItemToObjectHeader(
842 IN KSOBJECT_HEADER ObjectHeader
,
843 IN PDRIVER_DISPATCH Create
,
845 IN PWCHAR ObjectClass
,
846 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
848 PKSIOBJECT_HEADER Header
;
851 Header
= (PKSIOBJECT_HEADER
)ObjectHeader
;
853 DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
855 /* check if a device header has been provided */
857 return STATUS_INVALID_PARAMETER_1
;
859 /* check if a create item has been provided */
861 return STATUS_INVALID_PARAMETER_2
;
863 /* check if a object class has been provided */
865 return STATUS_INVALID_PARAMETER_4
;
868 Status
= KspAddObjectCreateItemToList(&Header
->ItemList
, Create
, Context
, ObjectClass
, SecurityDescriptor
);
870 if (NT_SUCCESS(Status
))
872 /* increment create item count */
873 InterlockedIncrement(&Header
->ItemListCount
);
885 KsAllocateObjectCreateItem(
886 IN KSDEVICE_HEADER DevHeader
,
887 IN PKSOBJECT_CREATE_ITEM CreateItem
,
888 IN BOOLEAN AllocateEntry
,
889 IN PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL
)
891 PCREATE_ITEM_ENTRY CreateEntry
;
892 PKSIDEVICE_HEADER Header
;
893 PKSOBJECT_CREATE_ITEM Item
;
895 Header
= (PKSIDEVICE_HEADER
)DevHeader
;
898 return STATUS_INVALID_PARAMETER_1
;
901 return STATUS_INVALID_PARAMETER_2
;
903 /* first allocate a create entry */
904 CreateEntry
= AllocateItem(NonPagedPool
, sizeof(CREATE_ITEM_ENTRY
));
906 /* check for allocation success */
909 /* not enough resources */
910 return STATUS_INSUFFICIENT_RESOURCES
;
916 /* allocate create item */
917 Item
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
));
921 FreeItem(CreateEntry
);
922 return STATUS_INSUFFICIENT_RESOURCES
;
925 /* initialize descriptor */
926 Item
->Context
= CreateItem
->Context
;
927 Item
->Create
= CreateItem
->Create
;
928 Item
->Flags
= CreateItem
->Flags
;
929 Item
->SecurityDescriptor
= CreateItem
->SecurityDescriptor
;
930 Item
->ObjectClass
.Length
= 0;
931 Item
->ObjectClass
.MaximumLength
= CreateItem
->ObjectClass
.MaximumLength
;
933 /* copy object class */
934 Item
->ObjectClass
.Buffer
= AllocateItem(NonPagedPool
, Item
->ObjectClass
.MaximumLength
);
935 if (!Item
->ObjectClass
.Buffer
)
937 /* release resources */
939 FreeItem(CreateEntry
);
941 return STATUS_INSUFFICIENT_RESOURCES
;
943 RtlCopyUnicodeString(&Item
->ObjectClass
, &CreateItem
->ObjectClass
);
947 if (ItemFreeCallback
)
949 /* callback is only accepted when the create item is copied */
950 ItemFreeCallback
= NULL
;
952 /* use passed create item */
956 /* initialize create item entry */
957 InitializeListHead(&CreateEntry
->ObjectItemList
);
958 CreateEntry
->ItemFreeCallback
= ItemFreeCallback
;
959 CreateEntry
->CreateItem
= Item
;
960 CreateEntry
->ReferenceCount
= 0;
962 /* now insert the create item entry */
963 InsertTailList(&Header
->ItemList
, &CreateEntry
->Entry
);
965 /* increment item count */
966 InterlockedIncrement(&Header
->ItemListCount
);
968 return STATUS_SUCCESS
;
972 KspObjectFreeCreateItems(
973 IN KSDEVICE_HEADER Header
,
974 IN PKSOBJECT_CREATE_ITEM CreateItem
)
977 return STATUS_NOT_IMPLEMENTED
;
986 KsFreeObjectCreateItem(
987 IN KSDEVICE_HEADER Header
,
988 IN PUNICODE_STRING CreateItem
)
990 KSOBJECT_CREATE_ITEM Item
;
992 RtlZeroMemory(&Item
, sizeof(KSOBJECT_CREATE_ITEM
));
993 RtlInitUnicodeString(&Item
.ObjectClass
, CreateItem
->Buffer
);
995 return KspObjectFreeCreateItems(Header
, &Item
);
1005 KsFreeObjectCreateItemsByContext(
1006 IN KSDEVICE_HEADER Header
,
1009 KSOBJECT_CREATE_ITEM Item
;
1011 RtlZeroMemory(&Item
, sizeof(KSOBJECT_CREATE_ITEM
));
1013 Item
.Context
= Context
;
1015 return KspObjectFreeCreateItems(Header
, &Item
);
1024 KsCreateDefaultSecurity(
1025 IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL
,
1026 OUT PSECURITY_DESCRIPTOR
* DefaultSecurity
)
1028 PGENERIC_MAPPING Mapping
;
1029 SECURITY_SUBJECT_CONTEXT SubjectContext
;
1032 /* start capturing security context of calling thread */
1033 SeCaptureSubjectContext(&SubjectContext
);
1034 /* get generic mapping */
1035 Mapping
= IoGetFileObjectGenericMapping();
1036 /* build new descriptor */
1037 Status
= SeAssignSecurity(ParentSecurity
, NULL
, DefaultSecurity
, FALSE
, &SubjectContext
, Mapping
, NonPagedPool
);
1038 /* release security descriptor */
1039 SeReleaseSubjectContext(&SubjectContext
);
1052 IN PFILE_OBJECT FileObject
,
1053 IN BOOLEAN ReuseStackLocation
)
1056 return STATUS_UNSUCCESSFUL
;
1066 KsForwardAndCatchIrp(
1067 IN PDEVICE_OBJECT DeviceObject
,
1069 IN PFILE_OBJECT FileObject
,
1070 IN KSSTACK_USE StackUse
)
1073 return STATUS_UNSUCCESSFUL
;
1079 KspSynchronousIoControlDeviceCompletion(
1080 IN PDEVICE_OBJECT DeviceObject
,
1084 PIO_STATUS_BLOCK IoStatusBlock
= (PIO_STATUS_BLOCK
)Context
;
1086 IoStatusBlock
->Information
= Irp
->IoStatus
.Information
;
1087 IoStatusBlock
->Status
= Irp
->IoStatus
.Status
;
1089 return STATUS_SUCCESS
;
1098 KsSynchronousIoControlDevice(
1099 IN PFILE_OBJECT FileObject
,
1100 IN KPROCESSOR_MODE RequestorMode
,
1104 OUT PVOID OutBuffer
,
1106 OUT PULONG BytesReturned
)
1108 PKSIOBJECT_HEADER ObjectHeader
;
1109 PDEVICE_OBJECT DeviceObject
;
1112 IO_STATUS_BLOCK IoStatusBlock
;
1113 PIO_STACK_LOCATION IoStack
;
1116 /* check for valid file object */
1118 return STATUS_INVALID_PARAMETER
;
1120 /* get device object to send the request to */
1121 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1123 return STATUS_UNSUCCESSFUL
;
1126 /* get object header */
1127 ObjectHeader
= (PKSIOBJECT_HEADER
)FileObject
->FsContext2
;
1129 /* check if there is fast device io function */
1130 if (ObjectHeader
&& ObjectHeader
->DispatchTable
.FastDeviceIoControl
)
1132 IoStatusBlock
.Status
= STATUS_UNSUCCESSFUL
;
1133 IoStatusBlock
.Information
= 0;
1135 /* send the request */
1136 Status
= ObjectHeader
->DispatchTable
.FastDeviceIoControl(FileObject
, TRUE
, InBuffer
, InSize
, OutBuffer
, OutSize
, IoControl
, &IoStatusBlock
, DeviceObject
);
1137 /* check if the request was handled */
1138 //DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
1141 /* store bytes returned */
1142 *BytesReturned
= IoStatusBlock
.Information
;
1144 return IoStatusBlock
.Status
;
1148 /* initialize the event */
1149 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1151 /* create the irp */
1152 Irp
= IoBuildDeviceIoControlRequest(IoControl
, DeviceObject
, InBuffer
, InSize
, OutBuffer
, OutSize
, FALSE
, &Event
, &IoStatusBlock
);
1156 /* no memory to allocate the irp */
1157 return STATUS_INSUFFICIENT_RESOURCES
;
1161 /* Store Fileobject */
1162 IoStack
= IoGetNextIrpStackLocation(Irp
);
1163 IoStack
->FileObject
= FileObject
;
1165 if (IoControl
== IOCTL_KS_WRITE_STREAM
)
1167 Irp
->AssociatedIrp
.SystemBuffer
= OutBuffer
;
1169 else if (IoControl
== IOCTL_KS_READ_STREAM
)
1171 Irp
->AssociatedIrp
.SystemBuffer
= InBuffer
;
1174 IoSetCompletionRoutine(Irp
, KspSynchronousIoControlDeviceCompletion
, (PVOID
)&IoStatusBlock
, TRUE
, TRUE
, TRUE
);
1176 Status
= IoCallDriver(DeviceObject
, Irp
);
1177 if (Status
== STATUS_PENDING
)
1179 KeWaitForSingleObject(&Event
, Executive
, RequestorMode
, FALSE
, NULL
);
1180 Status
= IoStatusBlock
.Status
;
1183 *BytesReturned
= IoStatusBlock
.Information
;
1193 KsUnserializeObjectPropertiesFromRegistry(
1194 IN PFILE_OBJECT FileObject
,
1195 IN HANDLE ParentKey OPTIONAL
,
1196 IN PUNICODE_STRING RegistryPath OPTIONAL
)
1199 return STATUS_NOT_IMPLEMENTED
;
1210 IN PUNICODE_STRING SymbolicLink
,
1211 IN PKSPIN_MEDIUM Medium
,
1212 IN ULONG PinDirection
)
1215 UNICODE_STRING Path
;
1216 UNICODE_STRING BasePath
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediumCache\\");
1217 UNICODE_STRING GuidString
;
1219 OBJECT_ATTRIBUTES ObjectAttributes
;
1220 BOOLEAN PathAdjusted
= FALSE
;
1223 /* first check if the medium is standard */
1224 if (IsEqualGUIDAligned(&KSMEDIUMSETID_Standard
, &Medium
->Set
) ||
1225 IsEqualGUIDAligned(&GUID_NULL
, &Medium
->Set
))
1227 /* no need to cache that */
1228 return STATUS_SUCCESS
;
1231 /* convert guid to string */
1232 Status
= RtlStringFromGUID(&Medium
->Set
, &GuidString
);
1233 if (!NT_SUCCESS(Status
))
1236 /* allocate path buffer */
1238 Path
.MaximumLength
= BasePath
.MaximumLength
+ GuidString
.MaximumLength
+ 10 * sizeof(WCHAR
);
1239 Path
.Buffer
= AllocateItem(PagedPool
, Path
.MaximumLength
);
1242 /* not enough resources */
1243 RtlFreeUnicodeString(&GuidString
);
1244 return STATUS_INSUFFICIENT_RESOURCES
;
1247 RtlAppendUnicodeStringToString(&Path
, &BasePath
);
1248 RtlAppendUnicodeStringToString(&Path
, &GuidString
);
1249 RtlAppendUnicodeToString(&Path
, L
"-");
1250 /* FIXME append real instance id */
1251 RtlAppendUnicodeToString(&Path
, L
"0");
1252 RtlAppendUnicodeToString(&Path
, L
"-");
1253 /* FIXME append real instance id */
1254 RtlAppendUnicodeToString(&Path
, L
"0");
1256 /* free guid string */
1257 RtlFreeUnicodeString(&GuidString
);
1259 /* initialize object attributes */
1260 InitializeObjectAttributes(&ObjectAttributes
, &Path
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1261 /* create the key */
1262 Status
= ZwCreateKey(&hKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1264 /* free path buffer */
1265 FreeItem(Path
.Buffer
);
1267 if (NT_SUCCESS(Status
))
1269 /* store symbolic link */
1270 if (SymbolicLink
->Buffer
[1] == L
'?' && SymbolicLink
->Buffer
[2] == L
'?')
1272 /* replace kernel path with user mode path */
1273 SymbolicLink
->Buffer
[1] = L
'\\';
1274 PathAdjusted
= TRUE
;
1278 Status
= ZwSetValueKey(hKey
, SymbolicLink
, 0, REG_DWORD
, &Value
, sizeof(ULONG
));
1282 /* restore kernel path */
1283 SymbolicLink
->Buffer
[1] = L
'?';
1299 PUNICODE_STRING RegistryPath
)
1301 return STATUS_SUCCESS
;
1308 IN PDEVICE_OBJECT DeviceObject
,
1311 PKO_OBJECT_HEADER Header
;
1312 PIO_STACK_LOCATION IoStack
;
1313 PDEVICE_EXTENSION DeviceExtension
;
1315 /* get current irp stack location */
1316 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1318 /* get ko object header */
1319 Header
= (PKO_OBJECT_HEADER
)IoStack
->FileObject
->FsContext2
;
1321 /* free ks object header */
1322 KsFreeObjectHeader(Header
->ObjectHeader
);
1324 /* free ko object header */
1327 /* get device extension */
1328 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1330 /* release bus object */
1331 KsDereferenceBusObject((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
);
1333 /* complete request */
1334 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1335 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1337 return STATUS_SUCCESS
;
1342 static KSDISPATCH_TABLE KoDispatchTable
=
1344 KsDispatchInvalidDeviceRequest
,
1345 KsDispatchInvalidDeviceRequest
,
1346 KsDispatchInvalidDeviceRequest
,
1347 KsDispatchInvalidDeviceRequest
,
1349 KsDispatchQuerySecurity
,
1350 KsDispatchSetSecurity
,
1351 KsDispatchFastIoDeviceControlFailure
,
1352 KsDispatchFastReadFailure
,
1353 KsDispatchFastReadFailure
,
1360 IN PDEVICE_OBJECT DeviceObject
,
1363 PKO_OBJECT_HEADER Header
= NULL
;
1364 PIO_STACK_LOCATION IoStack
;
1365 PKO_DRIVER_EXTENSION DriverObjectExtension
;
1368 /* get current irp stack location */
1369 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1371 if (!IoStack
->FileObject
)
1373 DPRINT1("FileObject not attached!\n");
1374 Status
= STATUS_UNSUCCESSFUL
;
1378 /* get driver object extension */
1379 DriverObjectExtension
= (PKO_DRIVER_EXTENSION
)IoGetDriverObjectExtension(DeviceObject
->DriverObject
, (PVOID
)KoDriverInitialize
);
1380 if (!DriverObjectExtension
)
1382 DPRINT1("No DriverObjectExtension!\n");
1383 Status
= STATUS_UNSUCCESSFUL
;
1387 /* allocate ko object header */
1388 Header
= (PKO_OBJECT_HEADER
)AllocateItem(NonPagedPool
, sizeof(KO_OBJECT_HEADER
));
1391 DPRINT1("failed to allocate KO_OBJECT_HEADER\n");
1392 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1396 /* initialize create item */
1397 Header
->CreateItem
.Create
= KopDispatchCreate
;
1398 RtlInitUnicodeString(&Header
->CreateItem
.ObjectClass
, KOSTRING_CreateObject
);
1401 /* now allocate the object header */
1402 Status
= KsAllocateObjectHeader(&Header
->ObjectHeader
, 1, &Header
->CreateItem
, Irp
, &KoDispatchTable
);
1403 if (!NT_SUCCESS(Status
))
1410 * extract clsid and interface id from irp
1411 * call the standard create handler
1416 IoStack
->FileObject
->FsContext2
= (PVOID
)Header
;
1418 Irp
->IoStatus
.Status
= Status
;
1419 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1425 if (Header
&& Header
->ObjectHeader
)
1426 KsFreeObjectHeader(Header
->ObjectHeader
);
1431 Irp
->IoStatus
.Status
= Status
;
1432 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1441 IN PDRIVER_OBJECT DriverObject
,
1442 IN PDEVICE_OBJECT PhysicalDeviceObject
)
1444 NTSTATUS Status
= STATUS_DEVICE_REMOVED
;
1445 PDEVICE_OBJECT FunctionalDeviceObject
= NULL
;
1446 PDEVICE_OBJECT NextDeviceObject
;
1447 PDEVICE_EXTENSION DeviceExtension
;
1448 PKSOBJECT_CREATE_ITEM CreateItem
;
1450 /* create the device object */
1451 Status
= IoCreateDevice(DriverObject
, sizeof(DEVICE_EXTENSION
), NULL
, FILE_DEVICE_KS
, FILE_DEVICE_SECURE_OPEN
, FALSE
, &FunctionalDeviceObject
);
1452 if (!NT_SUCCESS(Status
))
1455 /* allocate the create item */
1456 CreateItem
= AllocateItem(NonPagedPool
, sizeof(KSOBJECT_CREATE_ITEM
));
1460 /* not enough memory */
1461 IoDeleteDevice(FunctionalDeviceObject
);
1462 return STATUS_INSUFFICIENT_RESOURCES
;
1465 /* initialize create item */
1466 CreateItem
->Create
= KopDispatchCreate
;
1467 RtlInitUnicodeString(&CreateItem
->ObjectClass
, KOSTRING_CreateObject
);
1469 /* get device extension */
1470 DeviceExtension
= (PDEVICE_EXTENSION
)FunctionalDeviceObject
->DeviceExtension
;
1472 /* now allocate the device header */
1473 Status
= KsAllocateDeviceHeader((KSDEVICE_HEADER
*)&DeviceExtension
->DeviceHeader
, 1, CreateItem
);
1474 if (!NT_SUCCESS(Status
))
1477 IoDeleteDevice(FunctionalDeviceObject
);
1478 FreeItem(CreateItem
);
1482 /* now attach to device stack */
1483 NextDeviceObject
= IoAttachDeviceToDeviceStack(FunctionalDeviceObject
, PhysicalDeviceObject
);
1484 if (NextDeviceObject
)
1486 /* store pnp base object */
1487 KsSetDevicePnpAndBaseObject((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
, NextDeviceObject
, FunctionalDeviceObject
);
1488 /* set device flags */
1489 FunctionalDeviceObject
->Flags
|= DO_DIRECT_IO
| DO_POWER_PAGABLE
;
1490 FunctionalDeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
1495 KsFreeDeviceHeader((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
);
1496 FreeItem(CreateItem
);
1497 IoDeleteDevice(FunctionalDeviceObject
);
1498 Status
= STATUS_DEVICE_REMOVED
;
1513 IN PDEVICE_OBJECT DeviceObject
)
1515 PDEVICE_EXTENSION DeviceExtension
;
1517 /* get device extension */
1518 DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1520 return KsAddObjectCreateItemToDeviceHeader((KSDEVICE_HEADER
)DeviceExtension
->DeviceHeader
, KopDispatchCreate
, NULL
, KOSTRING_CreateObject
, NULL
);
1530 IN PDRIVER_OBJECT DriverObject
,
1531 IN PUNICODE_STRING RegistryPathName
,
1532 IN KoCreateObjectHandler CreateObjectHandler
)
1534 PKO_DRIVER_EXTENSION DriverObjectExtension
;
1537 /* allocate driver object extension */
1538 Status
= IoAllocateDriverObjectExtension(DriverObject
, (PVOID
)KoDriverInitialize
, sizeof(KO_DRIVER_EXTENSION
), (PVOID
*)&DriverObjectExtension
);
1541 if (NT_SUCCESS(Status
))
1543 /* store create handler */
1544 DriverObjectExtension
->CreateObjectHandler
= CreateObjectHandler
;
1546 /* Setting our IRP handlers */
1547 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = KsDefaultDispatchPnp
;
1548 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KsDefaultDispatchPower
;
1549 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KsDefaultForwardIrp
;
1551 /* The driver unload routine */
1552 DriverObject
->DriverUnload
= KsNullDriverUnload
;
1554 /* The driver-supplied AddDevice */
1555 DriverObject
->DriverExtension
->AddDevice
= KopAddDevice
;
1557 /* KS handles these */
1558 DPRINT1("Setting KS function handlers\n");
1559 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CREATE
);
1560 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CLOSE
);
1561 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_DEVICE_CONTROL
);
1575 IN REFCLSID ClassId
)
1589 PKSBASIC_HEADER BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1592 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
1594 KeWaitForSingleObject(BasicHeader
->ControlMutex
, Executive
, KernelMode
, FALSE
, NULL
);
1606 PKSBASIC_HEADER BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1609 ASSERT(BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
1611 KeReleaseMutex(BasicHeader
->ControlMutex
, FALSE
);
1623 IN PKSDEVICE Device
)
1625 IKsDevice
*KsDevice
;
1626 PKSIDEVICE_HEADER DeviceHeader
;
1628 DPRINT("KsAcquireDevice\n");
1629 DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
1631 /* get device interface*/
1632 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
1634 /* acquire device mutex */
1635 KsDevice
->lpVtbl
->AcquireDevice(KsDevice
);
1644 IN PKSDEVICE Device
)
1646 IKsDevice
*KsDevice
;
1647 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
1649 /* get device interface*/
1650 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
1652 /* release device mutex */
1653 KsDevice
->lpVtbl
->ReleaseDevice(KsDevice
);
1663 IN PDEVICE_OBJECT DeviceObject
)
1665 IKsDevice
*KsDevice
;
1666 PKSIDEVICE_HEADER DeviceHeader
;
1667 PDEVICE_EXTENSION DeviceExtension
= (PDEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
1669 /* get device header */
1670 DeviceHeader
= DeviceExtension
->DeviceHeader
;
1672 /* get device interface*/
1673 KsDevice
= (IKsDevice
*)&DeviceHeader
->BasicHeader
.OuterUnknown
;
1675 /* now free device header */
1676 KsFreeDeviceHeader((KSDEVICE_HEADER
)DeviceHeader
);
1678 /* release interface when available */
1681 /* delete IKsDevice interface */
1682 KsDevice
->lpVtbl
->Release(KsDevice
);
1692 KsCompletePendingRequest(
1695 PIO_STACK_LOCATION IoStack
;
1697 /* get current irp stack location */
1698 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1701 ASSERT(Irp
->IoStatus
.Status
!= STATUS_PENDING
);
1703 if (IoStack
->MajorFunction
!= IRP_MJ_CLOSE
)
1705 /* can be completed immediately */
1706 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1710 /* did close operation fail */
1711 if (!NT_SUCCESS(Irp
->IoStatus
.Status
))
1713 /* closing failed, complete irp */
1714 CompleteRequest(Irp
, IO_NO_INCREMENT
);
1719 * delete object / device header
1720 * remove dead pin / filter instance
1728 KspSetGetBusDataCompletion(
1729 IN PDEVICE_OBJECT DeviceObject
,
1733 /* signal completion */
1734 KeSetEvent((PRKEVENT
)Context
, IO_NO_INCREMENT
, FALSE
);
1736 /* more work needs be done, so dont free the irp */
1737 return STATUS_MORE_PROCESSING_REQUIRED
;
1742 KspDeviceSetGetBusData(
1743 IN PDEVICE_OBJECT DeviceObject
,
1750 PIO_STACK_LOCATION IoStack
;
1755 /* allocate the irp */
1756 Irp
= IoAllocateIrp(1, /*FIXME */
1760 return STATUS_INSUFFICIENT_RESOURCES
;
1762 /* initialize the event */
1763 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
1765 /* get next stack location */
1766 IoStack
= IoGetNextIrpStackLocation(Irp
);
1768 /* setup a completion routine */
1769 IoSetCompletionRoutine(Irp
, KspSetGetBusDataCompletion
, (PVOID
)&Event
, TRUE
, TRUE
, TRUE
);
1771 /* setup parameters */
1772 IoStack
->Parameters
.ReadWriteConfig
.Buffer
= Buffer
;
1773 IoStack
->Parameters
.ReadWriteConfig
.Length
= Length
;
1774 IoStack
->Parameters
.ReadWriteConfig
.Offset
= Offset
;
1775 IoStack
->Parameters
.ReadWriteConfig
.WhichSpace
= DataType
;
1776 /* setup function code */
1777 IoStack
->MajorFunction
= IRP_MJ_PNP
;
1778 IoStack
->MinorFunction
= (bGet
? IRP_MN_READ_CONFIG
: IRP_MN_WRITE_CONFIG
);
1780 /* lets call the driver */
1781 Status
= IoCallDriver(DeviceObject
, Irp
);
1783 /* is the request still pending */
1784 if (Status
== STATUS_PENDING
)
1787 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
1789 Status
= Irp
->IoStatus
.Status
;
1805 IN PKSDEVICE Device
,
1811 return KspDeviceSetGetBusData(Device
->PhysicalDeviceObject
, /* is this right? */
1812 DataType
, Buffer
, Offset
, Length
, FALSE
);
1823 IN PKSDEVICE Device
,
1829 return KspDeviceSetGetBusData(Device
->PhysicalDeviceObject
, /* is this right? */
1830 DataType
, Buffer
, Offset
, Length
, TRUE
);
1840 KsDeviceRegisterAdapterObject(
1841 IN PKSDEVICE Device
,
1842 IN PADAPTER_OBJECT AdapterObject
,
1843 IN ULONG MaxMappingsByteCount
,
1844 IN ULONG MappingTableStride
)
1846 PKSIDEVICE_HEADER DeviceHeader
= (PKSIDEVICE_HEADER
)CONTAINING_RECORD(Device
, KSIDEVICE_HEADER
, KsDevice
);
1848 DeviceHeader
->AdapterObject
= AdapterObject
;
1849 DeviceHeader
->MaxMappingsByteCount
= MaxMappingsByteCount
;
1850 DeviceHeader
->MappingTableStride
= MappingTableStride
;
1864 PKSBASIC_HEADER BasicHeader
;
1866 /* get the basic header */
1867 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1869 /* type has to be either a device or a filter factory */
1870 ASSERT(BasicHeader
->Type
== KsObjectTypeDevice
|| BasicHeader
->Type
== KsObjectTypeFilterFactory
);
1872 return (PVOID
)BasicHeader
->FirstChild
.Filter
;
1884 PKSBASIC_HEADER BasicHeader
;
1886 /* get the basic header */
1887 BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
1889 ASSERT(BasicHeader
->Type
== KsObjectTypeDevice
|| BasicHeader
->Type
== KsObjectTypeFilterFactory
||
1890 BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
1892 return (PVOID
)BasicHeader
->Next
.Pin
;
1897 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
1898 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
1900 ULONG Index
, SubIndex
, Count
;
1903 if (!AutomationTableA
)
1904 return AutomationTableB
->MethodSetsCount
;
1906 if (!AutomationTableB
)
1907 return AutomationTableA
->MethodSetsCount
;
1910 DPRINT("AutomationTableA MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableA
->MethodItemSize
, AutomationTableA
->MethodSetsCount
);
1911 DPRINT("AutomationTableB MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableB
->MethodItemSize
, AutomationTableB
->MethodSetsCount
);
1913 if (AutomationTableA
->MethodItemSize
&& AutomationTableB
->MethodItemSize
)
1916 ASSERT(AutomationTableA
->MethodItemSize
== AutomationTableB
->MethodItemSize
);
1919 /* now iterate all property sets and compare their guids */
1920 Count
= AutomationTableA
->MethodSetsCount
;
1922 for(Index
= 0; Index
< AutomationTableB
->MethodSetsCount
; Index
++)
1924 /* set found to false */
1927 for(SubIndex
= 0; SubIndex
< AutomationTableA
->MethodSetsCount
; SubIndex
++)
1929 if (IsEqualGUIDAligned(AutomationTableB
->MethodSets
[Index
].Set
, AutomationTableA
->MethodSets
[SubIndex
].Set
))
1931 /* same property set found */
1946 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
1947 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
1949 ULONG Index
, SubIndex
, Count
;
1952 if (!AutomationTableA
)
1953 return AutomationTableB
->EventSetsCount
;
1955 if (!AutomationTableB
)
1956 return AutomationTableA
->EventSetsCount
;
1958 DPRINT("AutomationTableA EventItemSize %lu EventSetsCount %lu\n", AutomationTableA
->EventItemSize
, AutomationTableA
->EventSetsCount
);
1959 DPRINT("AutomationTableB EventItemSize %lu EventSetsCount %lu\n", AutomationTableB
->EventItemSize
, AutomationTableB
->EventSetsCount
);
1961 if (AutomationTableA
->EventItemSize
&& AutomationTableB
->EventItemSize
)
1964 ASSERT(AutomationTableA
->EventItemSize
== AutomationTableB
->EventItemSize
);
1967 /* now iterate all Event sets and compare their guids */
1968 Count
= AutomationTableA
->EventSetsCount
;
1970 for(Index
= 0; Index
< AutomationTableB
->EventSetsCount
; Index
++)
1972 /* set found to false */
1975 for(SubIndex
= 0; SubIndex
< AutomationTableA
->EventSetsCount
; SubIndex
++)
1977 if (IsEqualGUIDAligned(AutomationTableB
->EventSets
[Index
].Set
, AutomationTableA
->EventSets
[SubIndex
].Set
))
1979 /* same Event set found */
1994 KspCountPropertySets(
1995 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
1996 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
1998 ULONG Index
, SubIndex
, Count
;
2001 if (!AutomationTableA
)
2002 return AutomationTableB
->PropertySetsCount
;
2004 if (!AutomationTableB
)
2005 return AutomationTableA
->PropertySetsCount
;
2008 DPRINT("AutomationTableA PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableA
->PropertyItemSize
, AutomationTableA
->PropertySetsCount
);
2009 DPRINT("AutomationTableB PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableB
->PropertyItemSize
, AutomationTableB
->PropertySetsCount
);
2010 ASSERT(AutomationTableA
->PropertyItemSize
== AutomationTableB
->PropertyItemSize
);
2012 /* now iterate all property sets and compare their guids */
2013 Count
= AutomationTableA
->PropertySetsCount
;
2015 for(Index
= 0; Index
< AutomationTableB
->PropertySetsCount
; Index
++)
2017 /* set found to false */
2020 for(SubIndex
= 0; SubIndex
< AutomationTableA
->PropertySetsCount
; SubIndex
++)
2022 if (IsEqualGUIDAligned(AutomationTableB
->PropertySets
[Index
].Set
, AutomationTableA
->PropertySets
[SubIndex
].Set
))
2024 /* same property set found */
2039 OUT PKSAUTOMATION_TABLE Table
,
2040 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2041 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
2043 ULONG Index
, SubIndex
, Count
;
2046 if (!AutomationTableA
)
2048 /* copy of property set */
2049 RtlMoveMemory((PVOID
)Table
->MethodSets
, AutomationTableB
->MethodSets
, sizeof(KSMETHOD_SET
) * AutomationTableB
->MethodSetsCount
);
2050 return STATUS_SUCCESS
;
2052 else if (!AutomationTableB
)
2054 /* copy of property set */
2055 RtlMoveMemory((PVOID
)Table
->MethodSets
, AutomationTableA
->MethodSets
, sizeof(KSMETHOD_SET
) * AutomationTableA
->MethodSetsCount
);
2056 return STATUS_SUCCESS
;
2059 /* first copy all property items from dominant table */
2060 RtlMoveMemory((PVOID
)Table
->MethodSets
, AutomationTableA
->MethodSets
, sizeof(KSMETHOD_SET
) * AutomationTableA
->MethodSetsCount
);
2062 Count
= AutomationTableA
->MethodSetsCount
;
2064 /* now copy entries which arent available in the dominant table */
2065 for(Index
= 0; Index
< AutomationTableB
->MethodSetsCount
; Index
++)
2067 /* set found to false */
2070 for(SubIndex
= 0; SubIndex
< AutomationTableA
->MethodSetsCount
; SubIndex
++)
2072 if (IsEqualGUIDAligned(AutomationTableB
->MethodSets
[Index
].Set
, AutomationTableA
->MethodSets
[SubIndex
].Set
))
2074 /* same property set found */
2082 /* copy new property item set */
2083 RtlMoveMemory((PVOID
)&Table
->MethodSets
[Count
], &AutomationTableB
->MethodSets
[Index
], sizeof(KSMETHOD_SET
));
2088 return STATUS_SUCCESS
;
2093 KspCopyPropertySets(
2094 OUT PKSAUTOMATION_TABLE Table
,
2095 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2096 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
2098 ULONG Index
, SubIndex
, Count
;
2101 if (!AutomationTableA
)
2103 /* copy of property set */
2104 RtlMoveMemory((PVOID
)Table
->PropertySets
, AutomationTableB
->PropertySets
, sizeof(KSPROPERTY_SET
) * AutomationTableB
->PropertySetsCount
);
2105 return STATUS_SUCCESS
;
2107 else if (!AutomationTableB
)
2109 /* copy of property set */
2110 RtlMoveMemory((PVOID
)Table
->PropertySets
, AutomationTableA
->PropertySets
, sizeof(KSPROPERTY_SET
) * AutomationTableA
->PropertySetsCount
);
2111 return STATUS_SUCCESS
;
2114 /* first copy all property items from dominant table */
2115 RtlMoveMemory((PVOID
)Table
->PropertySets
, AutomationTableA
->PropertySets
, sizeof(KSPROPERTY_SET
) * AutomationTableA
->PropertySetsCount
);
2117 Count
= AutomationTableA
->PropertySetsCount
;
2119 /* now copy entries which arent available in the dominant table */
2120 for(Index
= 0; Index
< AutomationTableB
->PropertySetsCount
; Index
++)
2122 /* set found to false */
2125 for(SubIndex
= 0; SubIndex
< AutomationTableA
->PropertySetsCount
; SubIndex
++)
2127 if (IsEqualGUIDAligned(AutomationTableB
->PropertySets
[Index
].Set
, AutomationTableA
->PropertySets
[SubIndex
].Set
))
2129 /* same property set found */
2137 /* copy new property item set */
2138 RtlMoveMemory((PVOID
)&Table
->PropertySets
[Count
], &AutomationTableB
->PropertySets
[Index
], sizeof(KSPROPERTY_SET
));
2143 return STATUS_SUCCESS
;
2148 OUT PKSAUTOMATION_TABLE Table
,
2149 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2150 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
)
2152 ULONG Index
, SubIndex
, Count
;
2155 if (!AutomationTableA
)
2157 /* copy of Event set */
2158 RtlMoveMemory((PVOID
)Table
->EventSets
, AutomationTableB
->EventSets
, sizeof(KSEVENT_SET
) * AutomationTableB
->EventSetsCount
);
2159 return STATUS_SUCCESS
;
2161 else if (!AutomationTableB
)
2163 /* copy of Event set */
2164 RtlMoveMemory((PVOID
)Table
->EventSets
, AutomationTableA
->EventSets
, sizeof(KSEVENT_SET
) * AutomationTableA
->EventSetsCount
);
2165 return STATUS_SUCCESS
;
2168 /* first copy all Event items from dominant table */
2169 RtlMoveMemory((PVOID
)Table
->EventSets
, AutomationTableA
->EventSets
, sizeof(KSEVENT_SET
) * AutomationTableA
->EventSetsCount
);
2171 Count
= AutomationTableA
->EventSetsCount
;
2173 /* now copy entries which arent available in the dominant table */
2174 for(Index
= 0; Index
< AutomationTableB
->EventSetsCount
; Index
++)
2176 /* set found to false */
2179 for(SubIndex
= 0; SubIndex
< AutomationTableA
->EventSetsCount
; SubIndex
++)
2181 if (IsEqualGUIDAligned(AutomationTableB
->EventSets
[Index
].Set
, AutomationTableA
->EventSets
[SubIndex
].Set
))
2183 /* same Event set found */
2191 /* copy new Event item set */
2192 RtlMoveMemory((PVOID
)&Table
->EventSets
[Count
], &AutomationTableB
->EventSets
[Index
], sizeof(KSEVENT_SET
));
2197 return STATUS_SUCCESS
;
2206 KsMergeAutomationTables(
2207 OUT PKSAUTOMATION_TABLE
*AutomationTableAB
,
2208 IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL
,
2209 IN PKSAUTOMATION_TABLE AutomationTableB OPTIONAL
,
2210 IN KSOBJECT_BAG Bag OPTIONAL
)
2212 PKSAUTOMATION_TABLE Table
;
2213 NTSTATUS Status
= STATUS_SUCCESS
;
2215 if (!AutomationTableA
&& !AutomationTableB
)
2217 /* nothing to merge */
2218 return STATUS_SUCCESS
;
2221 /* allocate an automation table */
2222 Table
= AllocateItem(NonPagedPool
, sizeof(KSAUTOMATION_TABLE
));
2224 return STATUS_INSUFFICIENT_RESOURCES
;
2228 /* add table to object bag */
2229 Status
= KsAddItemToObjectBag(Bag
, Table
, NULL
);
2230 /* check for success */
2231 if (!NT_SUCCESS(Status
))
2239 /* count property sets */
2240 Table
->PropertySetsCount
= KspCountPropertySets(AutomationTableA
, AutomationTableB
);
2242 if (Table
->PropertySetsCount
)
2244 if (AutomationTableA
)
2246 /* use item size from dominant automation table */
2247 Table
->PropertyItemSize
= AutomationTableA
->PropertyItemSize
;
2251 /* use item size from 2nd automation table */
2252 Table
->PropertyItemSize
= AutomationTableB
->PropertyItemSize
;
2255 /* now allocate the property sets */
2256 Table
->PropertySets
= AllocateItem(NonPagedPool
, sizeof(KSPROPERTY_SET
) * Table
->PropertySetsCount
);
2258 if (!Table
->PropertySets
)
2260 /* not enough memory */
2266 /* add set to property bag */
2267 Status
= KsAddItemToObjectBag(Bag
, (PVOID
)Table
->PropertySets
, NULL
);
2268 /* check for success */
2269 if (!NT_SUCCESS(Status
))
2275 /* now copy the property sets */
2276 Status
= KspCopyPropertySets(Table
, AutomationTableA
, AutomationTableB
);
2277 if(!NT_SUCCESS(Status
))
2282 /* now count the method sets */
2283 Table
->MethodSetsCount
= KspCountMethodSets(AutomationTableA
, AutomationTableB
);
2285 if (Table
->MethodSetsCount
)
2287 if (AutomationTableA
)
2289 /* use item size from dominant automation table */
2290 Table
->MethodItemSize
= AutomationTableA
->MethodItemSize
;
2294 /* use item size from 2nd automation table */
2295 Table
->MethodItemSize
= AutomationTableB
->MethodItemSize
;
2298 /* now allocate the property sets */
2299 Table
->MethodSets
= AllocateItem(NonPagedPool
, sizeof(KSMETHOD_SET
) * Table
->MethodSetsCount
);
2301 if (!Table
->MethodSets
)
2303 /* not enough memory */
2309 /* add set to property bag */
2310 Status
= KsAddItemToObjectBag(Bag
, (PVOID
)Table
->MethodSets
, NULL
);
2311 /* check for success */
2312 if (!NT_SUCCESS(Status
))
2318 /* now copy the property sets */
2319 Status
= KspCopyMethodSets(Table
, AutomationTableA
, AutomationTableB
);
2320 if(!NT_SUCCESS(Status
))
2325 /* now count the event sets */
2326 Table
->EventSetsCount
= KspCountEventSets(AutomationTableA
, AutomationTableB
);
2328 if (Table
->EventSetsCount
)
2330 if (AutomationTableA
)
2332 /* use item size from dominant automation table */
2333 Table
->EventItemSize
= AutomationTableA
->EventItemSize
;
2337 /* use item size from 2nd automation table */
2338 Table
->EventItemSize
= AutomationTableB
->EventItemSize
;
2341 /* now allocate the property sets */
2342 Table
->EventSets
= AllocateItem(NonPagedPool
, sizeof(KSEVENT_SET
) * Table
->EventSetsCount
);
2344 if (!Table
->EventSets
)
2346 /* not enough memory */
2352 /* add set to property bag */
2353 Status
= KsAddItemToObjectBag(Bag
, (PVOID
)Table
->EventSets
, NULL
);
2354 /* check for success */
2355 if (!NT_SUCCESS(Status
))
2361 /* now copy the property sets */
2362 Status
= KspCopyEventSets(Table
, AutomationTableA
, AutomationTableB
);
2363 if(!NT_SUCCESS(Status
))
2368 *AutomationTableAB
= Table
;
2377 if (Table
->PropertySets
)
2379 /* clean property sets */
2380 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, (PVOID
)Table
->PropertySets
, TRUE
)))
2381 FreeItem((PVOID
)Table
->PropertySets
);
2384 if (Table
->MethodSets
)
2386 /* clean property sets */
2387 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, (PVOID
)Table
->MethodSets
, TRUE
)))
2388 FreeItem((PVOID
)Table
->MethodSets
);
2391 if (Table
->EventSets
)
2393 /* clean property sets */
2394 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, (PVOID
)Table
->EventSets
, TRUE
)))
2395 FreeItem((PVOID
)Table
->EventSets
);
2398 if (!Bag
|| !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag
, Table
, TRUE
)))
2402 return STATUS_INSUFFICIENT_RESOURCES
;
2411 KsRegisterAggregatedClientUnknown(
2413 IN PUNKNOWN ClientUnknown
)
2415 PKSBASIC_HEADER BasicHeader
= (PKSBASIC_HEADER
)((ULONG_PTR
)Object
- sizeof(KSBASIC_HEADER
));
2418 ASSERT(BasicHeader
->Type
== KsObjectTypeDevice
|| BasicHeader
->Type
== KsObjectTypeFilterFactory
||
2419 BasicHeader
->Type
== KsObjectTypeFilter
|| BasicHeader
->Type
== KsObjectTypePin
);
2421 if (BasicHeader
->ClientAggregate
)
2423 /* release existing aggregate */
2424 BasicHeader
->ClientAggregate
->lpVtbl
->Release(BasicHeader
->ClientAggregate
);
2427 /* increment reference count */
2428 ClientUnknown
->lpVtbl
->AddRef(ClientUnknown
);
2430 /* store client aggregate */
2431 BasicHeader
->ClientAggregate
= ClientUnknown
;
2433 /* return objects outer unknown */
2434 return BasicHeader
->OuterUnknown
;
2442 KsRegisterFilterWithNoKSPins(
2443 IN PDEVICE_OBJECT DeviceObject
,
2444 IN
const GUID
* InterfaceClassGUID
,
2446 IN BOOL
* PinDirection
,
2447 IN KSPIN_MEDIUM
* MediumList
,
2448 IN GUID
* CategoryList OPTIONAL
)
2452 PWSTR SymbolicLinkList
;
2455 UNICODE_STRING InterfaceString
;
2456 //UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
2458 if (!InterfaceClassGUID
|| !PinCount
|| !PinDirection
|| !MediumList
)
2460 /* all these parameters are required */
2461 return STATUS_INVALID_PARAMETER
;
2464 /* calculate filter data value size */
2465 Size
= PinCount
* sizeof(KSPIN_MEDIUM
);
2468 /* add category list */
2469 Size
+= PinCount
* sizeof(GUID
);
2472 /* FIXME generate filter data blob */
2475 /* get symbolic link list */
2476 Status
= IoGetDeviceInterfaces(InterfaceClassGUID
, DeviceObject
, DEVICE_INTERFACE_INCLUDE_NONACTIVE
, &SymbolicLinkList
);
2477 if (NT_SUCCESS(Status
))
2479 /* initialize first symbolic link */
2480 RtlInitUnicodeString(&InterfaceString
, SymbolicLinkList
);
2482 /* open first device interface registry key */
2483 Status
= IoOpenDeviceInterfaceRegistryKey(&InterfaceString
, GENERIC_WRITE
, &hKey
);
2485 if (NT_SUCCESS(Status
))
2487 /* write filter data */
2488 //Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size);
2496 /* update medium cache */
2497 for(Index
= 0; Index
< PinCount
; Index
++)
2499 KsCacheMedium(&InterfaceString
, &MediumList
[Index
], PinDirection
[Index
]);
2503 /* free the symbolic link list */
2504 FreeItem(SymbolicLinkList
);