2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/swenum.c
5 * PURPOSE: KS Software BUS functions
6 * PROGRAMMER: Johannes Anderwald
12 LONG KsDeviceCount
= 0;
14 typedef NTSTATUS (NTAPI
*PKSP_BUS_ENUM_CALLBACK
)(
16 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
17 IN PBUS_DEVICE_ENTRY DummyEntry
,
19 IN LPWSTR DirectoryName
);
23 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
24 IN PBUS_DEVICE_ENTRY DeviceEntry
,
25 OUT PDEVICE_OBJECT
* OutDeviceObject
)
27 PDEVICE_OBJECT DeviceObject
;
30 UNICODE_STRING DeviceName
;
32 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
34 /* increment device count */
35 CurDeviceId
= InterlockedIncrement(&KsDeviceCount
);
37 /* generate new device id */
38 swprintf(Buffer
, L
"\\Device\\KSENUM%08x", CurDeviceId
);
40 /* initialize new device name */
41 RtlInitUnicodeString(&DeviceName
, Buffer
);
43 /* create new device object */
44 Status
= IoCreateDevice(BusDeviceExtension
->BusDeviceObject
->DriverObject
, sizeof(PVOID
), &DeviceName
, FILE_DEVICE_UNKNOWN
, 0, FALSE
, &DeviceObject
);
46 /* check for success */
47 if (!NT_SUCCESS(Status
))
49 /* failed to create pdo */
53 /* now allocate device extension */
54 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)AllocateItem(NonPagedPool
, sizeof(COMMON_DEVICE_EXTENSION
));
58 IoDeleteDevice(DeviceObject
);
59 return STATUS_INSUFFICIENT_RESOURCES
;
62 /* store device extension */
63 *((PVOID
*)DeviceObject
->DeviceExtension
) = DeviceExtension
;
65 /* initialize device extension */
66 DeviceExtension
->IsBus
= FALSE
;
67 DeviceExtension
->DeviceObject
= DeviceObject
;
68 DeviceExtension
->DeviceEntry
= DeviceEntry
;
69 DeviceExtension
->BusDeviceExtension
= BusDeviceExtension
;
71 /* TODO: update last creation time in bus device extension */
74 DeviceObject
->Flags
|= DO_POWER_PAGABLE
;
75 DeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
76 /* TODO: fire time when expired */
78 *OutDeviceObject
= DeviceObject
;
80 return STATUS_SUCCESS
;
84 KspRegisterDeviceAssociation(
85 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
86 IN PBUS_DEVICE_ENTRY DeviceEntry
,
87 IN OUT PBUS_INSTANCE_ENTRY BusInstanceEntry
)
90 UNICODE_STRING ReferenceString
;
92 /* initialize reference string */
93 RtlInitUnicodeString(&ReferenceString
, DeviceEntry
->DeviceName
);
95 /* register device interface */
96 Status
= IoRegisterDeviceInterface(BusDeviceExtension
->PhysicalDeviceObject
, &BusInstanceEntry
->InterfaceGuid
, &ReferenceString
, &BusInstanceEntry
->SymbolicLink
);
98 /* check for success */
99 if (!NT_SUCCESS(Status
))
105 /* now enable the interface */
106 Status
= IoSetDeviceInterfaceState(&BusInstanceEntry
->SymbolicLink
, TRUE
);
108 /* check for success */
109 if (!NT_SUCCESS(Status
))
111 /* failed, free memory */
112 FreeItem(BusInstanceEntry
->SymbolicLink
.Buffer
);
116 DPRINT1("Registered DeviceInterface %wZ\n", &BusInstanceEntry
->SymbolicLink
);
124 KspRemoveDeviceAssociations(
125 IN PBUS_DEVICE_ENTRY DeviceEntry
)
128 PBUS_INSTANCE_ENTRY CurEntry
;
130 /* remove all entries */
131 Entry
= DeviceEntry
->DeviceInterfaceList
.Flink
;
133 while(Entry
!= &DeviceEntry
->DeviceInterfaceList
)
136 CurEntry
= (PBUS_INSTANCE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_INSTANCE_ENTRY
, Entry
);
139 ASSERT(CurEntry
->SymbolicLink
.Buffer
);
141 /* de-register interface */
142 IoSetDeviceInterfaceState(&CurEntry
->SymbolicLink
, FALSE
);
144 /* free symbolic link buffer */
145 FreeItem(CurEntry
->SymbolicLink
.Buffer
);
147 /* remove entry from list */
148 RemoveEntryList(Entry
);
150 /* move to next entry */
151 Entry
= Entry
->Flink
;
159 KspEnumerateBusRegistryKeys(
161 IN LPWSTR ReferenceString
,
162 IN PKSP_BUS_ENUM_CALLBACK Callback
,
163 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
164 IN PBUS_DEVICE_ENTRY DeviceEntry
)
166 UNICODE_STRING String
;
167 OBJECT_ATTRIBUTES ObjectAttributes
;
170 ULONG ResultLength
, Index
, KeyInfoLength
;
171 KEY_FULL_INFORMATION KeyInformation
;
172 PKEY_BASIC_INFORMATION KeyInfo
;
174 /* initialize key name */
175 RtlInitUnicodeString(&String
, ReferenceString
);
177 /* initialize object attributes */
178 InitializeObjectAttributes(&ObjectAttributes
, &String
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hKey
, NULL
);
181 Status
= ZwOpenKey(&hNewKey
, GENERIC_READ
, &ObjectAttributes
);
183 /* check for success */
184 if (!NT_SUCCESS(Status
))
186 /* failed to open key */
191 /* query key stats */
192 Status
= ZwQueryKey(hNewKey
, KeyFullInformation
, &KeyInformation
, sizeof(KeyInformation
), &ResultLength
);
194 if (!NT_SUCCESS(Status
))
203 /* calculate key info length */
204 KeyInfoLength
= KeyInformation
.MaxNameLen
+ sizeof(KEY_BASIC_INFORMATION
) + 1 * sizeof(WCHAR
);
206 /* allocate buffer */
207 KeyInfo
= (PKEY_BASIC_INFORMATION
)AllocateItem(NonPagedPool
, KeyInfoLength
);
215 return STATUS_INSUFFICIENT_RESOURCES
;
218 /* enumerate all keys */
219 for(Index
= 0; Index
< KeyInformation
.SubKeys
; Index
++)
223 Status
= ZwEnumerateKey(hNewKey
, Index
, KeyBasicInformation
, (PVOID
)KeyInfo
, KeyInfoLength
, &ResultLength
);
225 /* check for success */
226 if (NT_SUCCESS(Status
))
228 /* perform callback */
229 Status
= Callback(hNewKey
, BusDeviceExtension
, DeviceEntry
, ReferenceString
, KeyInfo
->Name
);
231 /* should enumeration stop */
232 if (!NT_SUCCESS(Status
))
237 /* free info buffer */
249 KspCreateDeviceAssociation(
251 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
252 IN PBUS_DEVICE_ENTRY DeviceEntry
,
253 IN LPWSTR ReferenceString
,
254 IN LPWSTR InterfaceString
)
259 PBUS_INSTANCE_ENTRY CurEntry
;
260 UNICODE_STRING DeviceName
;
262 /* initialize interface string */
263 RtlInitUnicodeString(&DeviceName
, InterfaceString
);
265 /* first convert device name to guid */
266 RtlGUIDFromString(&DeviceName
, &DeviceGuid
);
268 /* check if the device is already present */
269 Entry
= DeviceEntry
->DeviceInterfaceList
.Flink
;
271 while(Entry
!= &DeviceEntry
->DeviceInterfaceList
)
274 CurEntry
= (PBUS_INSTANCE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_INSTANCE_ENTRY
, Entry
);
276 if (IsEqualGUIDAligned(&CurEntry
->InterfaceGuid
, &DeviceGuid
))
278 /* entry already exists */
279 return STATUS_SUCCESS
;
282 /* move to next entry */
283 Entry
= Entry
->Flink
;
286 /* time to allocate new entry */
287 CurEntry
= (PBUS_INSTANCE_ENTRY
)AllocateItem(NonPagedPool
, sizeof(BUS_INSTANCE_ENTRY
));
292 return STATUS_INSUFFICIENT_RESOURCES
;
296 RtlMoveMemory(&CurEntry
->InterfaceGuid
, &DeviceGuid
, sizeof(GUID
));
298 /* now register the association */
299 Status
= KspRegisterDeviceAssociation(BusDeviceExtension
, DeviceEntry
, CurEntry
);
301 /* check for success */
302 if (NT_SUCCESS(Status
))
305 InsertTailList(&DeviceEntry
->DeviceInterfaceList
, &CurEntry
->Entry
);
309 /* failed to associated device */
319 KspCreateDeviceReference(
321 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
322 IN PBUS_DEVICE_ENTRY DummyEntry
,
323 IN LPWSTR DeviceCategory
,
324 IN LPWSTR ReferenceString
)
329 PBUS_DEVICE_ENTRY DeviceEntry
= NULL
; /* GCC warning */
330 BOOLEAN ItemExists
= FALSE
;
331 UNICODE_STRING String
;
335 /* first construct device name & reference guid */
336 Length
= wcslen(DeviceCategory
) + wcslen(ReferenceString
);
338 /* append '&' and null byte */
341 /* allocate device name */
342 DeviceName
= AllocateItem(NonPagedPool
, Length
* sizeof(WCHAR
));
346 /* not enough memory */
347 return STATUS_INSUFFICIENT_RESOURCES
;
350 /* construct device name */
351 swprintf(DeviceName
, L
"%s&%s", DeviceCategory
, ReferenceString
);
353 /* scan list and check if it is already present */
354 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
356 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
358 /* get real offset */
359 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
361 /* check if name matches */
362 if (!wcsicmp(DeviceEntry
->DeviceName
, DeviceName
))
364 /* item already exists */
369 /* move to next entry */
370 Entry
= Entry
->Flink
;
375 /* allocate new device entry */
376 DeviceEntry
= AllocateItem(NonPagedPool
, sizeof(BUS_DEVICE_ENTRY
));
380 FreeItem(DeviceName
);
381 return STATUS_INSUFFICIENT_RESOURCES
;
384 /* initialize device entry */
385 InitializeListHead(&DeviceEntry
->DeviceInterfaceList
);
386 InitializeListHead(&DeviceEntry
->IrpPendingList
);
388 /* copy device guid */
389 RtlInitUnicodeString(&String
, ReferenceString
);
390 RtlGUIDFromString(&String
, &DeviceEntry
->DeviceGuid
);
392 /* copy device names */
393 DeviceEntry
->DeviceName
= DeviceName
;
394 DeviceEntry
->Instance
= (DeviceName
+ wcslen(DeviceCategory
) + 1);
397 DeviceEntry
->BusId
= AllocateItem(NonPagedPool
, (wcslen(DeviceCategory
) + 1) * sizeof(WCHAR
));
398 if (!DeviceEntry
->BusId
)
401 FreeItem(DeviceName
);
402 FreeItem(DeviceEntry
);
403 return STATUS_INSUFFICIENT_RESOURCES
;
405 wcscpy(DeviceEntry
->BusId
, DeviceCategory
);
408 /* now enumerate the devices */
409 Status
= KspEnumerateBusRegistryKeys(hKey
, ReferenceString
, KspCreateDeviceAssociation
, BusDeviceExtension
, DeviceEntry
);
411 /* check if list is empty */
412 if (IsListEmpty(&DeviceEntry
->DeviceInterfaceList
))
414 /* invalid device settings */
415 FreeItem(DeviceEntry
->BusId
);
416 FreeItem(DeviceEntry
->DeviceName
);
417 FreeItem(DeviceEntry
);
419 ASSERT(ItemExists
== FALSE
);
421 return STATUS_INVALID_DEVICE_STATE
;
424 /* check if enumeration failed */
425 if (!NT_SUCCESS(Status
))
428 KspRemoveDeviceAssociations(DeviceEntry
);
429 FreeItem(DeviceEntry
->BusId
);
430 FreeItem(DeviceEntry
->DeviceName
);
431 FreeItem(DeviceEntry
);
433 ASSERT(ItemExists
== FALSE
);
442 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
444 /* successfully initialized entry */
445 InsertTailList(&BusDeviceExtension
->Common
.Entry
, &DeviceEntry
->Entry
);
448 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
457 KspCreateDeviceReferenceTrampoline(
459 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
460 IN PBUS_DEVICE_ENTRY DummyEntry
,
461 IN LPWSTR DeviceCategory
,
462 IN LPWSTR ReferenceString
)
464 return KspEnumerateBusRegistryKeys(hKey
, ReferenceString
, KspCreateDeviceReference
, BusDeviceExtension
, DummyEntry
);
469 KspOpenBusRegistryKey(
470 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
473 OBJECT_ATTRIBUTES ObjectAttributes
;
475 /* initialize object attributes */
476 InitializeObjectAttributes(&ObjectAttributes
, &BusDeviceExtension
->ServicePath
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
478 return ZwCreateKey(hKey
, GENERIC_READ
| GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
483 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
)
489 Status
= KspOpenBusRegistryKey(BusDeviceExtension
, &hKey
);
491 /* check for success */
492 if (!NT_SUCCESS(Status
))
499 /* TODO clear reference marks */
501 /* construct device entries */
502 Status
= KspEnumerateBusRegistryKeys(hKey
, NULL
, KspCreateDeviceReferenceTrampoline
, BusDeviceExtension
, NULL
);
504 /* TODO: delete unreferenced devices */
516 KspBusQueryReferenceString(
518 IN OUT PWCHAR
*String
)
522 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)Context
;
525 ASSERT(BusDeviceExtension
);
526 ASSERT(BusDeviceExtension
->BusIdentifier
);
528 /* calculate length */
529 Length
= wcslen(BusDeviceExtension
->BusIdentifier
) + 1;
531 /* allocate buffer */
532 Name
= AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
536 /* failed to allocate buffer */
537 return STATUS_INSUFFICIENT_RESOURCES
;
541 wcscpy(Name
, BusDeviceExtension
->BusIdentifier
);
547 return STATUS_SUCCESS
;
552 KspBusDeviceReference(
555 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
557 /* reference count */
558 InterlockedIncrement((PLONG
)&ChildDeviceExtension
->DeviceReferenceCount
);
563 KspBusDeviceDereference(
566 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
568 /* reference count */
569 InterlockedDecrement((PLONG
)&ChildDeviceExtension
->DeviceReferenceCount
);
574 KspBusReferenceDeviceObject(
577 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
579 /* reference count */
580 InterlockedIncrement((PLONG
)&ChildDeviceExtension
->DeviceObjectReferenceCount
);
585 KspBusDereferenceDeviceObject(
588 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
590 /* reference count */
591 InterlockedDecrement((PLONG
)&ChildDeviceExtension
->DeviceObjectReferenceCount
);
595 KspQueryBusDeviceInterface(
596 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
599 PBUS_INTERFACE_SWENUM Interface
;
600 PIO_STACK_LOCATION IoStack
;
602 /* get current irp stack location */
603 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
606 ASSERT(IoStack
->Parameters
.QueryInterface
.Size
== sizeof(BUS_INTERFACE_SWENUM
));
607 ASSERT(IoStack
->Parameters
.QueryInterface
.Interface
);
609 /* fill in interface */
610 Interface
= (PBUS_INTERFACE_SWENUM
)IoStack
->Parameters
.QueryInterface
.Interface
;
611 Interface
->Interface
.Size
= sizeof(BUS_INTERFACE_SWENUM
);
612 Interface
->Interface
.Version
= BUS_INTERFACE_SWENUM_VERSION
;
613 Interface
->Interface
.Context
= ChildDeviceExtension
;
614 Interface
->Interface
.InterfaceReference
= KspBusDeviceReference
;
615 Interface
->Interface
.InterfaceDereference
= KspBusDeviceDereference
;
616 Interface
->ReferenceDeviceObject
= KspBusReferenceDeviceObject
;
617 Interface
->DereferenceDeviceObject
= KspBusDereferenceDeviceObject
;
618 Interface
->QueryReferenceString
= KspBusQueryReferenceString
;
620 return STATUS_SUCCESS
;
624 KspEnableBusDeviceInterface(
625 PBUS_DEVICE_ENTRY DeviceEntry
,
629 PBUS_INSTANCE_ENTRY InstanceEntry
;
630 NTSTATUS Status
= STATUS_SUCCESS
;
632 /* enable now all interfaces */
633 Entry
= DeviceEntry
->DeviceInterfaceList
.Flink
;
635 while(Entry
!= &DeviceEntry
->DeviceInterfaceList
)
637 /* get bus instance entry */
638 InstanceEntry
= (PBUS_INSTANCE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_INSTANCE_ENTRY
, Entry
);
639 DPRINT1("Enabling %u %wZ Irql %u\n", bEnable
, &InstanceEntry
->SymbolicLink
, KeGetCurrentIrql());
641 /* set interface state */
642 Status
= IoSetDeviceInterfaceState(&InstanceEntry
->SymbolicLink
, bEnable
);
644 if (!NT_SUCCESS(Status
))
646 /* failed to set interface */
650 /* move to next entry */
651 Entry
= Entry
->Flink
;
661 PBUS_DEVICE_ENTRY DeviceEntry
)
665 PIO_STACK_LOCATION IoStack
;
667 /* get stack location */
668 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
671 ASSERT(DeviceEntry
->PDODeviceName
);
672 ASSERT(DeviceEntry
->Instance
);
673 ASSERT(IoStack
->FileObject
);
674 ASSERT(IoStack
->FileObject
->FileName
.Buffer
);
676 /* calculate length */
677 Length
= wcslen(DeviceEntry
->PDODeviceName
);
678 Length
+= wcslen(DeviceEntry
->Instance
);
680 /* zero byte and '\\' */
683 /* allocate buffer */
684 Buffer
= AllocateItem(NonPagedPool
, Length
* sizeof(WCHAR
));
688 return STATUS_INSUFFICIENT_RESOURCES
;
691 /* construct buffer */
692 swprintf(Buffer
, L
"%s\\%s", DeviceEntry
->PDODeviceName
, DeviceEntry
->Instance
);
694 ExFreePool(IoStack
->FileObject
->FileName
.Buffer
);
696 /* store new file name */
697 RtlInitUnicodeString(&IoStack
->FileObject
->FileName
, Buffer
);
700 return STATUS_REPARSE
;
704 KspCompletePendingIrps(
705 IN PBUS_DEVICE_ENTRY DeviceEntry
,
706 IN OUT NTSTATUS ResultCode
)
712 /* go through list */
713 while(!IsListEmpty(&DeviceEntry
->IrpPendingList
))
715 /* get first entry */
716 Entry
= RemoveHeadList(&DeviceEntry
->IrpPendingList
);
719 Irp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
721 if (ResultCode
== STATUS_REPARSE
)
723 /* construct reparse information */
724 Status
= KspDoReparseForIrp(Irp
, DeviceEntry
);
728 /* use default code */
732 /* store result code */
733 Irp
->IoStatus
.Status
= Status
;
735 DPRINT1("Completing IRP %p Status %x\n", Irp
, Status
);
737 /* complete the request */
738 CompleteRequest(Irp
, IO_NO_INCREMENT
);
747 IN PDEVICE_OBJECT DeviceObject
,
748 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
755 PBUS_DEVICE_ENTRY DeviceEntry
;
757 /* FIXME handle pending remove */
759 /* get full device name */
760 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyPhysicalDeviceObjectName
, sizeof(PDOName
), (PVOID
)PDOName
, &ResultLength
);
762 if (!NT_SUCCESS(Status
))
764 /* failed to get device name */
768 /* allocate device name buffer */
769 Name
= AllocateItem(NonPagedPool
, (ResultLength
+ 1) * sizeof(WCHAR
));
773 return STATUS_INSUFFICIENT_RESOURCES
;
777 wcscpy(Name
, PDOName
);
779 /* TODO: time stamp creation time */
781 /* get device entry */
782 DeviceEntry
= (PBUS_DEVICE_ENTRY
)ChildDeviceExtension
->DeviceEntry
;
787 /* store device name */
788 DeviceEntry
->PDODeviceName
= Name
;
790 /* mark device as started */
791 DeviceEntry
->DeviceState
= Started
;
793 /* reference start time */
794 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
796 DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name
, DeviceEntry
->DeviceName
, DeviceEntry
->Instance
);
798 /* enable device classes */
799 //KspEnableBusDeviceInterface(DeviceEntry, TRUE);
802 return STATUS_SUCCESS
;
806 KspQueryBusDeviceCapabilities(
807 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
810 PDEVICE_CAPABILITIES Capabilities
;
811 PIO_STACK_LOCATION IoStack
;
813 /* get stack location */
814 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
816 /* get capabilities */
817 Capabilities
= IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
819 RtlZeroMemory(Capabilities
, sizeof(DEVICE_CAPABILITIES
));
821 /* setup capabilities */
822 Capabilities
->UniqueID
= TRUE
;
823 Capabilities
->SilentInstall
= TRUE
;
824 Capabilities
->SurpriseRemovalOK
= TRUE
;
825 Capabilities
->Address
= 0;
826 Capabilities
->UINumber
= 0;
827 Capabilities
->SystemWake
= PowerSystemWorking
; /* FIXME common device extension */
828 Capabilities
->DeviceWake
= PowerDeviceD0
;
831 return STATUS_SUCCESS
;
835 KspQueryBusInformation(
836 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
839 PPNP_BUS_INFORMATION BusInformation
;
841 /* allocate bus information */
842 BusInformation
= (PPNP_BUS_INFORMATION
)AllocateItem(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
847 return STATUS_INSUFFICIENT_RESOURCES
;
851 BusInformation
->BusNumber
= 0;
852 BusInformation
->LegacyBusType
= InterfaceTypeUndefined
;
853 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &KSMEDIUMSETID_Standard
, sizeof(GUID
));
856 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
859 return STATUS_SUCCESS
;
863 KspQueryBusDevicePnpState(
864 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
867 /* set device flags */
868 Irp
->IoStatus
.Information
= PNP_DEVICE_DONT_DISPLAY_IN_UI
| PNP_DEVICE_NOT_DISABLEABLE
;
871 return STATUS_SUCCESS
;
876 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
879 PIO_STACK_LOCATION IoStack
;
880 PBUS_DEVICE_ENTRY DeviceEntry
;
881 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
885 /* get current irp stack location */
886 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
888 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryInstanceID
)
890 /* get device entry */
891 DeviceEntry
= (PBUS_DEVICE_ENTRY
) ChildDeviceExtension
->DeviceEntry
;
895 ASSERT(DeviceEntry
->Instance
);
897 /* calculate length */
898 Length
= wcslen(DeviceEntry
->Instance
) + 1;
900 /* allocate buffer */
901 Name
= AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
905 /* failed to allocate buffer */
906 return STATUS_INSUFFICIENT_RESOURCES
;
910 wcscpy(Name
, DeviceEntry
->Instance
);
913 Irp
->IoStatus
.Information
= (ULONG_PTR
)Name
;
916 return STATUS_SUCCESS
;
918 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
||
919 IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
921 /* get device entry */
922 DeviceEntry
= (PBUS_DEVICE_ENTRY
) ChildDeviceExtension
->DeviceEntry
;
924 /* get bus device extension */
925 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
) ChildDeviceExtension
->BusDeviceExtension
;
929 ASSERT(DeviceEntry
->BusId
);
930 ASSERT(BusDeviceExtension
);
931 ASSERT(BusDeviceExtension
->BusIdentifier
);
933 /* calculate length */
934 Length
= wcslen(BusDeviceExtension
->BusIdentifier
);
935 Length
+= wcslen(DeviceEntry
->BusId
);
937 /* extra length for '\\' and zero byte */
940 /* allocate buffer */
941 Name
= ExAllocatePool(PagedPool
, Length
* sizeof(WCHAR
));
944 /* failed to allocate buffer */
945 return STATUS_INSUFFICIENT_RESOURCES
;
949 swprintf(Name
, L
"%s\\%s", BusDeviceExtension
->BusIdentifier
, DeviceEntry
->BusId
);
952 Irp
->IoStatus
.Information
= (ULONG_PTR
)Name
;
955 return STATUS_SUCCESS
;
959 /* other ids are not supported */
960 //DPRINT1("Not Supported ID Type %x\n", IoStack->Parameters.QueryId.IdType);
961 return Irp
->IoStatus
.Status
;
967 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
968 IN PSWENUM_INSTALL_INTERFACE InstallInterface
)
971 UNICODE_STRING DeviceString
, InterfaceString
, ReferenceString
;
972 HANDLE hKey
, hDeviceKey
, hInterfaceKey
, hReferenceKey
;
974 OBJECT_ATTRIBUTES ObjectAttributes
;
977 ASSERT(InstallInterface
);
979 /* calculate length */
980 Length
= wcslen(InstallInterface
->ReferenceString
);
982 /* check for invalid characters */
983 for(Index
= 0; Index
< Length
; Index
++)
985 if (InstallInterface
->ReferenceString
[Index
] <= L
' ' ||
986 InstallInterface
->ReferenceString
[Index
] > L
'~' ||
987 InstallInterface
->ReferenceString
[Index
] == L
',' ||
988 InstallInterface
->ReferenceString
[Index
] == L
'\\' ||
989 InstallInterface
->ReferenceString
[Index
] == L
'/')
991 /* invalid character */
992 return STATUS_INVALID_PARAMETER
;
997 Status
= KspOpenBusRegistryKey(BusDeviceExtension
, &hKey
);
998 if (NT_SUCCESS(Status
))
1000 /* convert device guid to string */
1001 Status
= RtlStringFromGUID(&InstallInterface
->DeviceId
, &DeviceString
);
1002 if (NT_SUCCESS(Status
))
1004 /* initialize object attributes */
1005 InitializeObjectAttributes(&ObjectAttributes
, &DeviceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hKey
, NULL
);
1007 /* construct device key */
1008 Status
= ZwCreateKey(&hDeviceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1009 if (NT_SUCCESS(Status
))
1011 /* initialize reference string */
1012 RtlInitUnicodeString(&ReferenceString
, InstallInterface
->ReferenceString
);
1014 /* initialize object attributes */
1015 InitializeObjectAttributes(&ObjectAttributes
, &ReferenceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceKey
, NULL
);
1017 /* construct device key */
1018 Status
= ZwCreateKey(&hReferenceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1019 if (NT_SUCCESS(Status
))
1021 /* convert interface guid to string */
1022 Status
= RtlStringFromGUID(&InstallInterface
->InterfaceId
, &InterfaceString
);
1023 if (NT_SUCCESS(Status
))
1025 /* initialize object attributes */
1026 InitializeObjectAttributes(&ObjectAttributes
, &InterfaceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hReferenceKey
, NULL
);
1028 /* construct device key */
1029 Status
= ZwCreateKey(&hInterfaceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1030 if (NT_SUCCESS(Status
))
1033 ZwClose(hInterfaceKey
);
1035 /* free interface string */
1036 RtlFreeUnicodeString(&InterfaceString
);
1038 /* close reference key */
1039 ZwClose(hReferenceKey
);
1041 /* close device key */
1042 ZwClose(hDeviceKey
);
1044 /* free device string */
1045 RtlFreeUnicodeString(&DeviceString
);
1057 KspInstallBusEnumInterface(
1060 PIO_STACK_LOCATION IoStack
;
1063 PBUS_DEVICE_ENTRY DeviceEntry
;
1064 PSWENUM_INSTALL_INTERFACE InstallInterface
;
1066 PBUS_INSTALL_ENUM_CONTEXT Context
= (PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1068 /* get current irp stack location */
1069 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
1071 /* get install request */
1072 InstallInterface
= (PSWENUM_INSTALL_INTERFACE
)Context
->Irp
->AssociatedIrp
.SystemBuffer
;
1075 ASSERT(InstallInterface
);
1076 ASSERT(Context
->BusDeviceExtension
);
1078 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(SWENUM_INSTALL_INTERFACE
))
1080 /* buffer too small */
1081 Context
->Status
= STATUS_INVALID_PARAMETER
;
1083 /* signal completion */
1084 KeSetEvent(&Context
->Event
, 0, FALSE
);
1092 /* now install the interface */
1093 Status
= KspInstallInterface(Context
->BusDeviceExtension
, InstallInterface
);
1094 if (!NT_SUCCESS(Status
))
1096 /* failed to install interface */
1097 Context
->Status
= Status
;
1099 /* signal completion */
1100 KeSetEvent(&Context
->Event
, 0, FALSE
);
1106 /* acquire device entry lock */
1107 KeAcquireSpinLock(&Context
->BusDeviceExtension
->Lock
, &OldLevel
);
1109 /* now iterate all device entries */
1110 Entry
= Context
->BusDeviceExtension
->Common
.Entry
.Flink
;
1111 while(Entry
!= &Context
->BusDeviceExtension
->Common
.Entry
)
1113 /* get device entry */
1114 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1116 if (IsEqualGUIDAligned(&DeviceEntry
->DeviceGuid
, &InstallInterface
->DeviceId
) &&
1117 !wcsicmp(DeviceEntry
->Instance
, InstallInterface
->ReferenceString
))
1119 if (!DeviceEntry
->PDO
)
1122 Status
= KspCreatePDO(Context
->BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1129 /* move to next entry */
1130 Entry
= Entry
->Flink
;
1133 /* release device entry lock */
1134 KeReleaseSpinLock(&Context
->BusDeviceExtension
->Lock
, OldLevel
);
1136 /* signal that bus driver relations has changed */
1137 IoInvalidateDeviceRelations(Context
->BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1140 Context
->Status
= Status
;
1142 /* signal completion */
1143 KeSetEvent(&Context
->Event
, 0, FALSE
);
1149 KspBusWorkerRoutine(
1152 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1153 PBUS_DEVICE_ENTRY DeviceEntry
;
1155 LARGE_INTEGER Time
, Diff
;
1156 BOOLEAN DoInvalidate
= FALSE
;
1159 /* get device extension */
1160 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)Parameter
;
1163 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1165 /* get current time */
1166 KeQuerySystemTime(&Time
);
1168 /* enumerate all device entries */
1169 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1170 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1172 /* get offset to device entry */
1173 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1176 ASSERT(DeviceEntry
);
1178 //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState);
1180 if (DeviceEntry
->PDO
)
1182 if (DeviceEntry
->DeviceState
== NotStarted
)
1184 Diff
.QuadPart
= Time
.QuadPart
- DeviceEntry
->TimeCreated
.QuadPart
;
1186 if (Diff
.QuadPart
> Int32x32To64(15000, 10000))
1188 DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry
->DeviceName
, DeviceEntry
->Instance
, DeviceEntry
->TimeCreated
.QuadPart
, Time
.QuadPart
, Diff
.QuadPart
);
1190 /* release spin lock */
1191 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1193 /* deactivate interfaces */
1194 //KspEnableBusDeviceInterface(DeviceEntry, FALSE);
1196 /* re-acquire lock */
1197 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1199 /* pending remove device object */
1200 DeviceEntry
->DeviceState
= StopPending
;
1202 /* perform invalidation */
1203 DoInvalidate
= TRUE
;
1206 else if (DeviceEntry
->DeviceState
== Started
)
1208 /* found pending irps */
1209 KspCompletePendingIrps(DeviceEntry
, STATUS_REPARSE
);
1215 Entry
= Entry
->Flink
;
1219 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1223 /* invalidate device relations */
1224 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1227 Time
.QuadPart
= Int32x32To64(5000, -10000);
1228 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1235 IN PVOID DeferredContext OPTIONAL
,
1236 IN PVOID SystemArgument1 OPTIONAL
,
1237 IN PVOID SystemArgument2 OPTIONAL
)
1239 /* get device extension */
1240 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeferredContext
;
1242 /* queue the item */
1243 ExQueueWorkItem(&BusDeviceExtension
->WorkItem
, DelayedWorkQueue
);
1248 KspRemoveBusInterface(
1251 PBUS_INSTALL_ENUM_CONTEXT Context
=(PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1254 * get SWENUM_INSTALL_INTERFACE struct
1255 * open device key and delete the keys
1261 Context
->Status
= STATUS_NOT_IMPLEMENTED
;
1264 /* signal completion */
1265 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
1269 KspQueryBusRelations(
1270 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
1273 PDEVICE_RELATIONS DeviceRelations
;
1275 PBUS_DEVICE_ENTRY DeviceEntry
;
1276 ULONG Count
= 0, Length
;
1280 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1282 /* first scan all device entries */
1283 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1285 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1287 /* get offset to device entry */
1288 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1290 /* is there a pdo yet */
1291 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1293 /* increment count */
1297 /* move to next entry */
1298 Entry
= Entry
->Flink
;
1301 /* calculate length */
1302 Length
= sizeof(DEVICE_RELATIONS
) + (Count
> 1 ? sizeof(PDEVICE_OBJECT
) * (Count
-1) : 0);
1304 /* allocate device relations */
1305 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(NonPagedPool
, Length
);
1307 if (!DeviceRelations
)
1309 /* not enough memory */
1310 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1311 return STATUS_INSUFFICIENT_RESOURCES
;
1314 /* rescan device entries */
1315 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1317 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1319 /* get offset to device entry */
1320 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1322 /* is there a pdo yet */
1323 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1326 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceEntry
->PDO
;
1328 /* reference device object */
1329 ObReferenceObject(DeviceEntry
->PDO
);
1331 /* increment pdo count */
1332 DeviceRelations
->Count
++;
1335 /* move to next entry */
1336 Entry
= Entry
->Flink
;
1340 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1342 /* FIXME handle existing device relations */
1343 ASSERT(Irp
->IoStatus
.Information
== 0);
1345 /* store device relations */
1346 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
1349 return STATUS_SUCCESS
;
1352 //------------------------------------------------------------------------------------
1361 KsGetBusEnumIdentifier(
1364 PDEV_EXTENSION DeviceExtension
;
1365 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1366 PIO_STACK_LOCATION IoStack
;
1371 DPRINT1("KsGetBusEnumIdentifier\n");
1373 /* get stack location */
1374 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1377 ASSERT(IoStack
->DeviceObject
);
1378 ASSERT(IoStack
->DeviceObject
->DeviceExtension
);
1380 /* get device extension */
1381 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1383 /* get bus device extension */
1384 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1387 ASSERT(BusDeviceExtension
);
1388 ASSERT(BusDeviceExtension
->Common
.IsBus
);
1390 if (!BusDeviceExtension
)
1392 /* invalid parameter */
1393 return STATUS_INVALID_PARAMETER
;
1397 Length
= (wcslen(BusDeviceExtension
->BusIdentifier
)+1) * sizeof(WCHAR
);
1399 /* is there an output buffer provided */
1400 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1402 if (Length
> IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1404 /* buffer is too small */
1405 return STATUS_BUFFER_TOO_SMALL
;
1408 /* now allocate buffer */
1409 Buffer
= AllocateItem(NonPagedPool
, Length
);
1413 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1417 /* copy bus identifier */
1418 wcscpy(Buffer
, BusDeviceExtension
->BusIdentifier
);
1421 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
1423 /* set flag that buffer gets copied back */
1424 Irp
->Flags
|= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
1427 Status
= STATUS_SUCCESS
;
1432 /* no buffer provided */
1433 Status
= STATUS_BUFFER_OVERFLOW
;
1437 Irp
->IoStatus
.Status
= Status
;
1447 KsGetBusEnumParentFDOFromChildPDO(
1448 IN PDEVICE_OBJECT DeviceObject
,
1449 OUT PDEVICE_OBJECT
*FunctionalDeviceObject
)
1451 PDEV_EXTENSION DeviceExtension
;
1453 DPRINT1("KsGetBusEnumParentFDOFromChildPDO\n");
1455 /* get device extension */
1456 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1458 /* check if this is child pdo */
1459 if (DeviceExtension
->Ext
->IsBus
== FALSE
)
1461 /* return bus device object */
1462 *FunctionalDeviceObject
= DeviceExtension
->Ext
->BusDeviceExtension
->BusDeviceObject
;
1465 return STATUS_SUCCESS
;
1468 /* invalid parameter */
1469 return STATUS_INVALID_PARAMETER
;
1479 KsCreateBusEnumObject(
1480 IN PWCHAR BusIdentifier
,
1481 IN PDEVICE_OBJECT BusDeviceObject
,
1482 IN PDEVICE_OBJECT PhysicalDeviceObject
,
1483 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL
,
1484 IN REFGUID InterfaceGuid OPTIONAL
,
1485 IN PWCHAR ServiceRelativePath OPTIONAL
)
1488 NTSTATUS Status
= STATUS_SUCCESS
;
1489 UNICODE_STRING ServiceKeyPath
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
1490 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1491 PDEV_EXTENSION DeviceExtension
;
1493 DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath
, BusDeviceObject
);
1495 /* calculate sizeof bus enum device extension */
1496 Length
= wcslen(BusIdentifier
) * sizeof(WCHAR
);
1497 Length
+= sizeof(BUS_ENUM_DEVICE_EXTENSION
);
1499 BusDeviceExtension
= AllocateItem(NonPagedPool
, Length
);
1500 if (!BusDeviceExtension
)
1502 /* not enough memory */
1504 return STATUS_INSUFFICIENT_RESOURCES
;
1507 /* get device extension */
1508 DeviceExtension
= (PDEV_EXTENSION
)BusDeviceObject
->DeviceExtension
;
1510 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1512 /* store bus device extension */
1513 DeviceExtension
->Ext
= (PCOMMON_DEVICE_EXTENSION
)BusDeviceExtension
;
1515 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1518 /* zero device extension */
1519 RtlZeroMemory(BusDeviceExtension
, sizeof(BUS_ENUM_DEVICE_EXTENSION
));
1521 /* initialize bus device extension */
1522 wcscpy(BusDeviceExtension
->BusIdentifier
, BusIdentifier
);
1524 /* allocate service path string */
1525 Length
= ServiceKeyPath
.MaximumLength
;
1526 Length
+= BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
.MaximumLength
;
1528 if (ServiceRelativePath
)
1530 /* relative path for devices */
1531 Length
+= (wcslen(ServiceRelativePath
) + 2) * sizeof(WCHAR
);
1534 BusDeviceExtension
->ServicePath
.Length
= 0;
1535 BusDeviceExtension
->ServicePath
.MaximumLength
= Length
;
1536 BusDeviceExtension
->ServicePath
.Buffer
= AllocateItem(NonPagedPool
, Length
);
1538 if (!BusDeviceExtension
->ServicePath
.Buffer
)
1540 /* not enough memory */
1541 FreeItem(BusDeviceExtension
);
1543 return STATUS_INSUFFICIENT_RESOURCES
;
1546 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &ServiceKeyPath
);
1547 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
);
1549 if (ServiceRelativePath
)
1551 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, L
"\\");
1552 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, ServiceRelativePath
);
1557 /* register an device interface */
1558 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
, InterfaceGuid
, NULL
, &BusDeviceExtension
->DeviceInterfaceLink
);
1560 /* check for success */
1561 if (!NT_SUCCESS(Status
))
1564 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1565 FreeItem(BusDeviceExtension
);
1569 /* now enable device interface */
1570 Status
= IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, TRUE
);
1572 if (!NT_SUCCESS(Status
))
1574 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1575 FreeItem(BusDeviceExtension
);
1580 /* initialize common device extension */
1581 BusDeviceExtension
->Common
.BusDeviceExtension
= NULL
;
1582 BusDeviceExtension
->Common
.DeviceObjectReferenceCount
= 1;
1583 BusDeviceExtension
->Common
.DeviceReferenceCount
= 1;
1584 BusDeviceExtension
->Common
.IsBus
= TRUE
;
1585 InitializeListHead(&BusDeviceExtension
->Common
.Entry
);
1587 /* store device objects */
1588 BusDeviceExtension
->BusDeviceObject
= BusDeviceObject
;
1589 BusDeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
1591 /* initialize lock */
1592 KeInitializeSpinLock(&BusDeviceExtension
->Lock
);
1594 /* initialize timer */
1595 KeInitializeTimer(&BusDeviceExtension
->Timer
);
1597 /* initialize dpc */
1598 KeInitializeDpc(&BusDeviceExtension
->Dpc
, KspBusDpcRoutine
, (PVOID
)BusDeviceExtension
);
1600 /* initialize event */
1601 KeInitializeEvent(&BusDeviceExtension
->Event
, SynchronizationEvent
, FALSE
);
1603 /* initialize work item */
1604 ExInitializeWorkItem(&BusDeviceExtension
->WorkItem
, KspBusWorkerRoutine
, (PVOID
)BusDeviceExtension
);
1606 if (!PnpDeviceObject
)
1609 BusDeviceExtension
->PnpDeviceObject
= IoAttachDeviceToDeviceStack(BusDeviceObject
, PhysicalDeviceObject
);
1611 if (!BusDeviceExtension
->PnpDeviceObject
)
1613 /* failed to attach device */
1614 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1616 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1617 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1620 /* free device extension */
1621 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1622 FreeItem(BusDeviceExtension
);
1624 return STATUS_DEVICE_REMOVED
;
1627 /* mark device as attached */
1628 BusDeviceExtension
->DeviceAttached
= TRUE
;
1632 /* directly attach */
1633 BusDeviceExtension
->PnpDeviceObject
= PnpDeviceObject
;
1636 /* now scan the bus */
1637 Status
= KspScanBus(BusDeviceExtension
);
1639 /* check for success */
1640 if (!NT_SUCCESS(Status
))
1642 /* failed to scan bus */
1643 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1645 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1646 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1649 if (BusDeviceExtension
->DeviceAttached
)
1652 IoDetachDevice(BusDeviceExtension
->PnpDeviceObject
);
1655 /* free device extension */
1656 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1657 FreeItem(BusDeviceExtension
);
1660 DPRINT("KsCreateBusEnumObject Status %x\n", Status
);
1671 KsGetBusEnumPnpDeviceObject(
1672 IN PDEVICE_OBJECT DeviceObject
,
1673 IN PDEVICE_OBJECT
*PnpDeviceObject
)
1675 PDEV_EXTENSION DeviceExtension
;
1676 PCOMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1677 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1679 DPRINT("KsGetBusEnumPnpDeviceObject\n");
1681 if (!DeviceObject
->DeviceExtension
)
1683 /* invalid parameter */
1684 return STATUS_INVALID_PARAMETER
;
1687 /* get device extension */
1688 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1690 /* get common device extension */
1691 CommonDeviceExtension
= DeviceExtension
->Ext
;
1693 if (!CommonDeviceExtension
)
1695 /* invalid parameter */
1696 return STATUS_INVALID_PARAMETER
;
1699 if (!CommonDeviceExtension
->IsBus
)
1701 /* getting pnp device object is only supported for software bus device object */
1702 return STATUS_INVALID_PARAMETER
;
1706 ASSERT(CommonDeviceExtension
);
1707 ASSERT(CommonDeviceExtension
->IsBus
);
1709 /* cast to bus device extension */
1710 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)CommonDeviceExtension
;
1713 *PnpDeviceObject
= BusDeviceExtension
->PnpDeviceObject
;
1716 return STATUS_SUCCESS
;
1725 KsInstallBusEnumInterface(
1728 BUS_INSTALL_ENUM_CONTEXT Context
;
1729 KPROCESSOR_MODE Mode
;
1731 PIO_STACK_LOCATION IoStack
;
1732 PDEV_EXTENSION DeviceExtension
;
1733 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1735 DPRINT1("KsInstallBusEnumInterface\n");
1737 /* get current irp stack location */
1738 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1740 /* get previous mode */
1741 Mode
= ExGetPreviousMode();
1743 /* convert to luid */
1744 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
1746 /* perform access check */
1747 if (!SeSinglePrivilegeCheck(luid
, Mode
))
1749 /* insufficient privileges */
1750 return STATUS_PRIVILEGE_NOT_HELD
;
1753 /* get device extension */
1754 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1756 /* get bus device extension */
1757 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1760 /* initialize context */
1762 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
1763 Context
.BusDeviceExtension
= BusDeviceExtension
;
1764 ExInitializeWorkItem(&Context
.WorkItem
, KspInstallBusEnumInterface
, (PVOID
)&Context
);
1766 /* queue the work item */
1767 ExQueueWorkItem(&Context
.WorkItem
, DelayedWorkQueue
);
1768 /* wait for completion */
1769 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
1772 Irp
->IoStatus
.Status
= Context
.Status
;
1775 return Context
.Status
;
1784 KsIsBusEnumChildDevice(
1785 IN PDEVICE_OBJECT DeviceObject
,
1786 OUT PBOOLEAN ChildDevice
)
1788 PDEV_EXTENSION DeviceExtension
;
1789 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1791 DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject
);
1793 /* get device extension */
1794 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1796 /* get bus device extension */
1797 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1799 if (!BusDeviceExtension
)
1801 /* not a bus device */
1802 return STATUS_INVALID_PARAMETER
;
1806 *ChildDevice
= (BusDeviceExtension
->Common
.IsBus
== FALSE
);
1808 return STATUS_SUCCESS
;
1817 KsServiceBusEnumCreateRequest(
1818 IN PDEVICE_OBJECT DeviceObject
,
1822 PBUS_DEVICE_ENTRY DeviceEntry
= NULL
; /* fix gcc */
1823 PIO_STACK_LOCATION IoStack
;
1824 BOOLEAN ItemExists
= FALSE
;
1825 PDEV_EXTENSION DeviceExtension
;
1826 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1827 //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension;
1833 /* get device extension */
1834 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1836 /* get bus device extension */
1837 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1839 /* get current irp stack location */
1840 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1843 ASSERT(IoStack
->FileObject
);
1844 ASSERT(IoStack
->FileObject
->FileName
.Buffer
);
1846 DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1848 /* scan list and check if it is already present */
1849 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1851 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1853 /* get real offset */
1854 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1856 /* check if name matches */
1857 if (!wcsicmp(DeviceEntry
->DeviceName
, IoStack
->FileObject
->FileName
.Buffer
+ 1))
1859 /* item already exists */
1864 /* move to next entry */
1865 Entry
= Entry
->Flink
;
1870 /* interface not registered */
1871 DPRINT1("Interface %wZ not registered\n", &IoStack
->FileObject
->FileName
);
1872 return STATUS_OBJECT_NAME_NOT_FOUND
;
1875 /* is there a pdo yet */
1876 if (DeviceEntry
->PDO
)
1878 if (DeviceEntry
->DeviceState
== Started
)
1881 Status
= KspDoReparseForIrp(Irp
, DeviceEntry
);
1882 DPRINT("REPARSE Irp %p '%wZ'\n", Irp
, &IoStack
->FileObject
->FileName
);
1884 Irp
->IoStatus
.Status
= Status
;
1888 /* delay processing until pnp is finished with enumeration */
1889 IoMarkIrpPending(Irp
);
1891 /* insert into irp pending list */
1892 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1894 Time
.QuadPart
= Int32x32To64(1500, -10000);
1895 DbgPrint("PENDING Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1897 /* query current time */
1898 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
1901 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1904 return STATUS_PENDING
;
1909 /* time to create PDO */
1910 Status
= KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1912 if (!NT_SUCCESS(Status
))
1914 /* failed to create PDO */
1915 DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status
);
1918 DPRINT1("PENDING CREATE Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1920 /* delay processing until pnp is finished with enumeration */
1921 IoMarkIrpPending(Irp
);
1923 /* insert into irp pending list */
1924 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1926 /* get current time */
1927 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
1929 /* invalidate device relations */
1930 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1933 return STATUS_PENDING
;
1943 KsServiceBusEnumPnpRequest(
1944 IN PDEVICE_OBJECT DeviceObject
,
1947 PDEV_EXTENSION DeviceExtension
;
1948 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1949 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
;
1950 PIO_STACK_LOCATION IoStack
;
1953 PDEVICE_RELATIONS DeviceRelation
;
1954 PBUS_DEVICE_ENTRY DeviceEntry
;
1956 /* get device extension */
1957 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1959 /* get bus device extension */
1960 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1962 /* get current irp stack location */
1963 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1965 if (BusDeviceExtension
->Common
.IsBus
)
1967 if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
1969 /* no op for bus driver */
1970 Status
= STATUS_SUCCESS
;
1972 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
)
1974 /* handle bus device relations */
1975 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== BusRelations
);
1977 Status
= KspQueryBusRelations(BusDeviceExtension
, Irp
);
1981 /* get default status */
1982 Status
= Irp
->IoStatus
.Status
;
1987 /* get child device extension */
1988 ChildDeviceExtension
= DeviceExtension
->Ext
;
1990 /* get bus device extension */
1991 BusDeviceExtension
= ChildDeviceExtension
->BusDeviceExtension
;
1993 if (IoStack
->MinorFunction
== IRP_MN_QUERY_ID
)
1996 Status
= KspQueryId(ChildDeviceExtension
, Irp
);
1998 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
2000 ASSERT(ChildDeviceExtension
->DeviceEntry
->DeviceState
!= Started
|| ChildDeviceExtension
->DeviceEntry
->DeviceState
== NotStarted
);
2001 ASSERT(ChildDeviceExtension
->DeviceEntry
->PDO
== DeviceObject
);
2003 /* backup device entry */
2004 DeviceEntry
= ChildDeviceExtension
->DeviceEntry
;
2006 /* free device extension */
2007 FreeItem(ChildDeviceExtension
);
2009 /* clear PDO reference */
2010 DeviceEntry
->PDO
= NULL
;
2012 /* delete the device */
2013 IoDeleteDevice(DeviceObject
);
2015 if (DeviceEntry
->PDODeviceName
)
2017 /* delete pdo device name */
2018 FreeItem(DeviceEntry
->PDODeviceName
);
2021 DeviceEntry
->PDODeviceName
= NULL
;
2024 /* set state no notstarted */
2025 DeviceEntry
->DeviceState
= NotStarted
;
2027 /* time to create PDO */
2028 KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
2030 /* invalidate device relations */
2031 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
2034 Status
= STATUS_SUCCESS
;
2036 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_BUS_INFORMATION
)
2038 /* query bus information */
2039 Status
= KspQueryBusInformation(ChildDeviceExtension
, Irp
);
2041 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCES
)
2044 Status
= STATUS_SUCCESS
;
2046 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCE_REQUIREMENTS
)
2049 Status
= STATUS_SUCCESS
;
2051 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
2054 Status
= KspStartBusDevice(DeviceObject
, ChildDeviceExtension
, Irp
);
2057 Time
.QuadPart
= Int32x32To64(1500, -10000);
2060 ASSERT(BusDeviceExtension
);
2063 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
2065 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_CAPABILITIES
)
2067 /* query capabilities */
2068 Status
= KspQueryBusDeviceCapabilities(ChildDeviceExtension
, Irp
);
2070 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
2072 /* query pnp state */
2073 Status
= KspQueryBusDevicePnpState(ChildDeviceExtension
, Irp
);
2075 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_INTERFACE
)
2077 /* query interface */
2078 Status
= KspQueryBusDeviceInterface(ChildDeviceExtension
, Irp
);
2080 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
&& IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
2082 /* handle target device relations */
2083 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
);
2084 ASSERT(Irp
->IoStatus
.Information
== 0);
2086 /* allocate device relation */
2087 DeviceRelation
= AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
));
2090 DeviceRelation
->Count
= 1;
2091 DeviceRelation
->Objects
[0] = DeviceObject
;
2093 /* reference self */
2094 ObReferenceObject(DeviceObject
);
2097 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelation
;
2100 Status
= STATUS_SUCCESS
;
2105 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2110 /* get default status */
2111 Status
= Irp
->IoStatus
.Status
;
2115 DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject
, BusDeviceExtension
->Common
.IsBus
, IoStack
->MinorFunction
, Status
);
2116 Irp
->IoStatus
.Status
= Status
;
2126 KsRemoveBusEnumInterface(
2129 KPROCESSOR_MODE Mode
;
2131 BUS_INSTALL_ENUM_CONTEXT Ctx
;
2132 PDEV_EXTENSION DeviceExtension
;
2133 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
2134 PIO_STACK_LOCATION IoStack
;
2136 DPRINT1("KsRemoveBusEnumInterface\n");
2138 /* get io stack location */
2139 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2141 /* get device extension */
2142 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
2144 /* get bus device extension */
2145 BusDeviceExtension
= DeviceExtension
->Ext
->BusDeviceExtension
;
2147 /* get previous mode */
2148 Mode
= ExGetPreviousMode();
2150 /* convert to luid */
2151 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
2153 /* perform access check */
2154 if (!SeSinglePrivilegeCheck(luid
, Mode
))
2156 /* insufficient privileges */
2157 return STATUS_PRIVILEGE_NOT_HELD
;
2160 /* initialize context */
2161 KeInitializeEvent(&Ctx
.Event
, NotificationEvent
, FALSE
);
2163 Ctx
.BusDeviceExtension
= BusDeviceExtension
;
2164 ExInitializeWorkItem(&Ctx
.WorkItem
, KspRemoveBusInterface
, (PVOID
)&Ctx
);
2166 /* now queue the work item */
2167 ExQueueWorkItem(&Ctx
.WorkItem
, DelayedWorkQueue
);
2169 /* wait for completion */
2170 KeWaitForSingleObject(&Ctx
.Event
, Executive
, KernelMode
, FALSE
, NULL
);