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
;
976 /* calculate length */
977 Length
= wcslen(InstallInterface
->ReferenceString
);
979 /* check for invalid characters */
980 for(Index
= 0; Index
< Length
; Index
++)
982 if (InstallInterface
->ReferenceString
[Index
] <= L
' ' ||
983 InstallInterface
->ReferenceString
[Index
] > L
'~' ||
984 InstallInterface
->ReferenceString
[Index
] == L
',' ||
985 InstallInterface
->ReferenceString
[Index
] == L
'\\' ||
986 InstallInterface
->ReferenceString
[Index
] == L
'/')
988 /* invalid character */
989 return STATUS_INVALID_PARAMETER
;
994 Status
= KspOpenBusRegistryKey(BusDeviceExtension
, &hKey
);
995 if (NT_SUCCESS(Status
))
997 /* convert device guid to string */
998 Status
= RtlStringFromGUID(&InstallInterface
->DeviceId
, &DeviceString
);
999 if (NT_SUCCESS(Status
))
1001 /* initialize object attributes */
1002 InitializeObjectAttributes(&ObjectAttributes
, &DeviceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hKey
, NULL
);
1004 /* construct device key */
1005 Status
= ZwCreateKey(&hDeviceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1006 if (NT_SUCCESS(Status
))
1008 /* initialize reference string */
1009 RtlInitUnicodeString(&ReferenceString
, InstallInterface
->ReferenceString
);
1011 /* initialize object attributes */
1012 InitializeObjectAttributes(&ObjectAttributes
, &ReferenceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceKey
, NULL
);
1014 /* construct device key */
1015 Status
= ZwCreateKey(&hReferenceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1016 if (NT_SUCCESS(Status
))
1018 /* convert interface guid to string */
1019 Status
= RtlStringFromGUID(&InstallInterface
->InterfaceId
, &InterfaceString
);
1020 if (NT_SUCCESS(Status
))
1022 /* initialize object attributes */
1023 InitializeObjectAttributes(&ObjectAttributes
, &InterfaceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hReferenceKey
, NULL
);
1025 /* construct device key */
1026 Status
= ZwCreateKey(&hInterfaceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1027 if (NT_SUCCESS(Status
))
1030 ZwClose(hInterfaceKey
);
1032 /* free interface string */
1033 RtlFreeUnicodeString(&InterfaceString
);
1035 /* close reference key */
1036 ZwClose(hReferenceKey
);
1038 /* close device key */
1039 ZwClose(hDeviceKey
);
1041 /* free device string */
1042 RtlFreeUnicodeString(&DeviceString
);
1054 KspInstallBusEnumInterface(
1057 PIO_STACK_LOCATION IoStack
;
1060 PBUS_DEVICE_ENTRY DeviceEntry
;
1061 PSWENUM_INSTALL_INTERFACE InstallInterface
;
1062 PBUS_INSTALL_ENUM_CONTEXT Context
= (PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1064 /* get current irp stack location */
1065 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
1067 /* get install request */
1068 InstallInterface
= (PSWENUM_INSTALL_INTERFACE
)IoStack
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
1070 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(SWENUM_INSTALL_INTERFACE
))
1072 /* buffer too small */
1073 Context
->Status
= STATUS_INVALID_PARAMETER
;
1075 /* signal completion */
1076 KeSetEvent(&Context
->Event
, 0, FALSE
);
1084 /* now install the interface */
1085 Status
= KspInstallInterface(Context
->BusDeviceExtension
, InstallInterface
);
1086 if (!NT_SUCCESS(Status
))
1088 /* failed to install interface */
1089 Context
->Status
= Status
;
1091 /* signal completion */
1092 KeSetEvent(&Context
->Event
, 0, FALSE
);
1098 /* now iterate all device entries */
1099 Entry
= Context
->BusDeviceExtension
->Common
.Entry
.Flink
;
1100 while(Entry
!= &Context
->BusDeviceExtension
->Common
.Entry
)
1102 /* get device entry */
1103 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1105 if (IsEqualGUIDAligned(&DeviceEntry
->DeviceGuid
, &InstallInterface
->DeviceId
) &&
1106 !wcsicmp(DeviceEntry
->Instance
, InstallInterface
->ReferenceString
))
1108 if (!DeviceEntry
->PDO
)
1111 Status
= KspCreatePDO(Context
->BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1119 /* signal that bus driver relations has changed */
1120 IoInvalidateDeviceRelations(Context
->BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1123 Context
->Status
= Status
;
1125 /* signal completion */
1126 KeSetEvent(&Context
->Event
, 0, FALSE
);
1132 KspBusWorkerRoutine(
1135 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1136 PBUS_DEVICE_ENTRY DeviceEntry
;
1138 LARGE_INTEGER Time
, Diff
;
1139 BOOLEAN DoInvalidate
= FALSE
;
1143 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1145 /* get device extension */
1146 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)Parameter
;
1148 /* get current time */
1149 KeQuerySystemTime(&Time
);
1151 /* enumerate all device entries */
1152 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1153 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1155 /* get offset to device entry */
1156 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1159 ASSERT(DeviceEntry
);
1161 //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState);
1163 if (DeviceEntry
->PDO
)
1165 if (DeviceEntry
->DeviceState
== NotStarted
)
1167 Diff
.QuadPart
= Time
.QuadPart
- DeviceEntry
->TimeCreated
.QuadPart
;
1169 if (Diff
.QuadPart
> Int32x32To64(15000, 10000))
1171 DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry
->DeviceName
, DeviceEntry
->Instance
, DeviceEntry
->TimeCreated
.QuadPart
, Time
.QuadPart
, Diff
.QuadPart
);
1173 /* release spin lock */
1174 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1176 /* deactivate interfaces */
1177 //KspEnableBusDeviceInterface(DeviceEntry, FALSE);
1179 /* re-acquire lock */
1180 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1182 /* pending remove device object */
1183 DeviceEntry
->DeviceState
= StopPending
;
1185 /* perform invalidation */
1186 DoInvalidate
= TRUE
;
1189 else if (DeviceEntry
->DeviceState
== Started
)
1191 /* found pending irps */
1192 KspCompletePendingIrps(DeviceEntry
, STATUS_REPARSE
);
1198 Entry
= Entry
->Flink
;
1202 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1206 /* invalidate device relations */
1207 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1210 Time
.QuadPart
= Int32x32To64(5000, -10000);
1211 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1218 IN PVOID DeferredContext OPTIONAL
,
1219 IN PVOID SystemArgument1 OPTIONAL
,
1220 IN PVOID SystemArgument2 OPTIONAL
)
1222 /* get device extension */
1223 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeferredContext
;
1225 /* queue the item */
1226 ExQueueWorkItem(&BusDeviceExtension
->WorkItem
, DelayedWorkQueue
);
1231 KspRemoveBusInterface(
1234 PBUS_INSTALL_ENUM_CONTEXT Context
=(PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1237 * get SWENUM_INSTALL_INTERFACE struct
1238 * open device key and delete the keys
1244 Context
->Status
= STATUS_NOT_IMPLEMENTED
;
1247 /* signal completion */
1248 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
1252 KspQueryBusRelations(
1253 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
1256 PDEVICE_RELATIONS DeviceRelations
;
1258 PBUS_DEVICE_ENTRY DeviceEntry
;
1259 ULONG Count
= 0, Length
;
1263 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1265 /* first scan all device entries */
1266 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1268 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1270 /* get offset to device entry */
1271 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1273 /* is there a pdo yet */
1274 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1276 /* increment count */
1280 /* move to next entry */
1281 Entry
= Entry
->Flink
;
1284 /* calculate length */
1285 Length
= sizeof(DEVICE_RELATIONS
) + (Count
> 1 ? sizeof(PDEVICE_OBJECT
) * (Count
-1) : 0);
1287 /* allocate device relations */
1288 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(NonPagedPool
, Length
);
1290 if (!DeviceRelations
)
1292 /* not enough memory */
1293 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1294 return STATUS_INSUFFICIENT_RESOURCES
;
1297 /* rescan device entries */
1298 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1300 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1302 /* get offset to device entry */
1303 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1305 /* is there a pdo yet */
1306 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1309 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceEntry
->PDO
;
1311 /* reference device object */
1312 ObReferenceObject(DeviceEntry
->PDO
);
1314 /* increment pdo count */
1315 DeviceRelations
->Count
++;
1318 /* move to next entry */
1319 Entry
= Entry
->Flink
;
1323 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1325 /* FIXME handle existing device relations */
1326 ASSERT(Irp
->IoStatus
.Information
== 0);
1328 /* store device relations */
1329 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
1332 return STATUS_SUCCESS
;
1335 //------------------------------------------------------------------------------------
1344 KsGetBusEnumIdentifier(
1347 PDEV_EXTENSION DeviceExtension
;
1348 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1349 PIO_STACK_LOCATION IoStack
;
1354 DPRINT1("KsGetBusEnumIdentifier\n");
1356 /* get stack location */
1357 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1360 ASSERT(IoStack
->DeviceObject
);
1361 ASSERT(IoStack
->DeviceObject
->DeviceExtension
);
1363 /* get device extension */
1364 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1366 /* get bus device extension */
1367 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
->BusDeviceExtension
;
1370 ASSERT(BusDeviceExtension
);
1371 ASSERT(BusDeviceExtension
->Common
.IsBus
);
1373 if (!BusDeviceExtension
)
1375 /* invalid parameter */
1376 return STATUS_INVALID_PARAMETER
;
1380 Length
= (wcslen(BusDeviceExtension
->BusIdentifier
)+1) * sizeof(WCHAR
);
1382 /* is there an output buffer provided */
1383 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1385 if (Length
> IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1387 /* buffer is too small */
1388 return STATUS_BUFFER_TOO_SMALL
;
1391 /* now allocate buffer */
1392 Buffer
= AllocateItem(NonPagedPool
, Length
);
1396 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1400 /* copy bus identifier */
1401 wcscpy(Buffer
, BusDeviceExtension
->BusIdentifier
);
1404 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
1406 /* set flag that buffer gets copied back */
1407 Irp
->Flags
|= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
1410 Status
= STATUS_SUCCESS
;
1415 /* no buffer provided */
1416 Status
= STATUS_BUFFER_OVERFLOW
;
1420 Irp
->IoStatus
.Status
= Status
;
1430 KsGetBusEnumParentFDOFromChildPDO(
1431 IN PDEVICE_OBJECT DeviceObject
,
1432 OUT PDEVICE_OBJECT
*FunctionalDeviceObject
)
1434 PDEV_EXTENSION DeviceExtension
;
1436 DPRINT1("KsGetBusEnumParentFDOFromChildPDO\n");
1438 /* get device extension */
1439 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1441 /* check if this is child pdo */
1442 if (DeviceExtension
->Ext
->IsBus
== FALSE
)
1444 /* return bus device object */
1445 *FunctionalDeviceObject
= DeviceExtension
->Ext
->BusDeviceExtension
->BusDeviceObject
;
1448 return STATUS_SUCCESS
;
1451 /* invalid parameter */
1452 return STATUS_INVALID_PARAMETER
;
1462 KsCreateBusEnumObject(
1463 IN PWCHAR BusIdentifier
,
1464 IN PDEVICE_OBJECT BusDeviceObject
,
1465 IN PDEVICE_OBJECT PhysicalDeviceObject
,
1466 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL
,
1467 IN REFGUID InterfaceGuid OPTIONAL
,
1468 IN PWCHAR ServiceRelativePath OPTIONAL
)
1471 NTSTATUS Status
= STATUS_SUCCESS
;
1472 UNICODE_STRING ServiceKeyPath
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
1473 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1474 PDEV_EXTENSION DeviceExtension
;
1476 DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath
, BusDeviceObject
);
1478 /* calculate sizeof bus enum device extension */
1479 Length
= wcslen(BusIdentifier
) * sizeof(WCHAR
);
1480 Length
+= sizeof(BUS_ENUM_DEVICE_EXTENSION
);
1482 BusDeviceExtension
= AllocateItem(NonPagedPool
, Length
);
1483 if (!BusDeviceExtension
)
1485 /* not enough memory */
1487 return STATUS_INSUFFICIENT_RESOURCES
;
1490 /* get device extension */
1491 DeviceExtension
= (PDEV_EXTENSION
)BusDeviceObject
->DeviceExtension
;
1493 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1495 /* store bus device extension */
1496 DeviceExtension
->Ext
= (PCOMMON_DEVICE_EXTENSION
)BusDeviceExtension
;
1498 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1501 /* zero device extension */
1502 RtlZeroMemory(BusDeviceExtension
, sizeof(BUS_ENUM_DEVICE_EXTENSION
));
1504 /* initialize bus device extension */
1505 wcscpy(BusDeviceExtension
->BusIdentifier
, BusIdentifier
);
1507 /* allocate service path string */
1508 Length
= ServiceKeyPath
.MaximumLength
;
1509 Length
+= BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
.MaximumLength
;
1511 if (ServiceRelativePath
)
1513 /* relative path for devices */
1514 Length
+= (wcslen(ServiceRelativePath
) + 2) * sizeof(WCHAR
);
1517 BusDeviceExtension
->ServicePath
.Length
= 0;
1518 BusDeviceExtension
->ServicePath
.MaximumLength
= Length
;
1519 BusDeviceExtension
->ServicePath
.Buffer
= AllocateItem(NonPagedPool
, Length
);
1521 if (!BusDeviceExtension
->ServicePath
.Buffer
)
1523 /* not enough memory */
1524 FreeItem(BusDeviceExtension
);
1526 return STATUS_INSUFFICIENT_RESOURCES
;
1529 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &ServiceKeyPath
);
1530 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
);
1532 if (ServiceRelativePath
)
1534 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, L
"\\");
1535 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, ServiceRelativePath
);
1540 /* register an device interface */
1541 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
, InterfaceGuid
, NULL
, &BusDeviceExtension
->DeviceInterfaceLink
);
1543 /* check for success */
1544 if (!NT_SUCCESS(Status
))
1547 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1548 FreeItem(BusDeviceExtension
);
1552 /* now enable device interface */
1553 Status
= IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, TRUE
);
1555 if (!NT_SUCCESS(Status
))
1557 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1558 FreeItem(BusDeviceExtension
);
1563 /* initialize common device extension */
1564 BusDeviceExtension
->Common
.BusDeviceExtension
= NULL
;
1565 BusDeviceExtension
->Common
.DeviceObjectReferenceCount
= 1;
1566 BusDeviceExtension
->Common
.DeviceReferenceCount
= 1;
1567 BusDeviceExtension
->Common
.IsBus
= TRUE
;
1568 InitializeListHead(&BusDeviceExtension
->Common
.Entry
);
1570 /* store device objects */
1571 BusDeviceExtension
->BusDeviceObject
= BusDeviceObject
;
1572 BusDeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
1574 /* initialize lock */
1575 KeInitializeSpinLock(&BusDeviceExtension
->Lock
);
1577 /* initialize timer */
1578 KeInitializeTimer(&BusDeviceExtension
->Timer
);
1580 /* initialize dpc */
1581 KeInitializeDpc(&BusDeviceExtension
->Dpc
, KspBusDpcRoutine
, (PVOID
)BusDeviceExtension
);
1583 /* initialize event */
1584 KeInitializeEvent(&BusDeviceExtension
->Event
, SynchronizationEvent
, FALSE
);
1586 /* initialize work item */
1587 ExInitializeWorkItem(&BusDeviceExtension
->WorkItem
, KspBusWorkerRoutine
, (PVOID
)BusDeviceExtension
);
1589 if (!PnpDeviceObject
)
1592 BusDeviceExtension
->PnpDeviceObject
= IoAttachDeviceToDeviceStack(BusDeviceObject
, PhysicalDeviceObject
);
1594 if (!BusDeviceExtension
->PnpDeviceObject
)
1596 /* failed to attach device */
1597 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1599 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1600 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1603 /* free device extension */
1604 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1605 FreeItem(BusDeviceExtension
);
1607 return STATUS_DEVICE_REMOVED
;
1610 /* mark device as attached */
1611 BusDeviceExtension
->DeviceAttached
= TRUE
;
1615 /* directly attach */
1616 BusDeviceExtension
->PnpDeviceObject
= PnpDeviceObject
;
1619 /* now scan the bus */
1620 Status
= KspScanBus(BusDeviceExtension
);
1622 /* check for success */
1623 if (!NT_SUCCESS(Status
))
1625 /* failed to scan bus */
1626 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1628 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1629 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1632 if (BusDeviceExtension
->DeviceAttached
)
1635 IoDetachDevice(BusDeviceExtension
->PnpDeviceObject
);
1638 /* free device extension */
1639 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1640 FreeItem(BusDeviceExtension
);
1643 DPRINT("KsCreateBusEnumObject Status %x\n", Status
);
1654 KsGetBusEnumPnpDeviceObject(
1655 IN PDEVICE_OBJECT DeviceObject
,
1656 IN PDEVICE_OBJECT
*PnpDeviceObject
)
1658 PDEV_EXTENSION DeviceExtension
;
1659 PCOMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1660 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1662 DPRINT("KsGetBusEnumPnpDeviceObject\n");
1664 if (!DeviceObject
->DeviceExtension
)
1666 /* invalid parameter */
1667 return STATUS_INVALID_PARAMETER
;
1670 /* get device extension */
1671 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1673 /* get common device extension */
1674 CommonDeviceExtension
= DeviceExtension
->Ext
;
1676 if (!CommonDeviceExtension
)
1678 /* invalid parameter */
1679 return STATUS_INVALID_PARAMETER
;
1682 if (!CommonDeviceExtension
->IsBus
)
1684 /* getting pnp device object is only supported for software bus device object */
1685 return STATUS_INVALID_PARAMETER
;
1689 ASSERT(CommonDeviceExtension
);
1690 ASSERT(CommonDeviceExtension
->IsBus
);
1692 /* cast to bus device extension */
1693 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)CommonDeviceExtension
;
1696 *PnpDeviceObject
= BusDeviceExtension
->PnpDeviceObject
;
1699 return STATUS_SUCCESS
;
1708 KsInstallBusEnumInterface(
1711 BUS_INSTALL_ENUM_CONTEXT Context
;
1712 KPROCESSOR_MODE Mode
;
1714 PIO_STACK_LOCATION IoStack
;
1715 PDEV_EXTENSION DeviceExtension
;
1716 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1718 DPRINT1("KsGetBusEnumPnpDeviceObject\n");
1720 /* get current irp stack location */
1721 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1723 /* get previous mode */
1724 Mode
= ExGetPreviousMode();
1726 /* convert to luid */
1727 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
1729 /* perform access check */
1730 if (!SeSinglePrivilegeCheck(luid
, Mode
))
1732 /* insufficient privileges */
1733 return STATUS_PRIVILEGE_NOT_HELD
;
1736 /* get device extension */
1737 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1739 /* get bus device extension */
1740 BusDeviceExtension
= DeviceExtension
->Ext
->BusDeviceExtension
;
1743 /* initialize context */
1745 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
1746 Context
.BusDeviceExtension
= BusDeviceExtension
;
1747 ExInitializeWorkItem(&Context
.WorkItem
, KspInstallBusEnumInterface
, (PVOID
)&Context
);
1749 /* queue the work item */
1750 ExQueueWorkItem(&Context
.WorkItem
, DelayedWorkQueue
);
1752 /* wait for completion */
1753 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
1756 return Context
.Status
;
1765 KsIsBusEnumChildDevice(
1766 IN PDEVICE_OBJECT DeviceObject
,
1767 OUT PBOOLEAN ChildDevice
)
1769 PDEV_EXTENSION DeviceExtension
;
1770 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1772 DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject
);
1774 /* get device extension */
1775 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1777 /* get bus device extension */
1778 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1780 if (!BusDeviceExtension
)
1782 /* not a bus device */
1783 return STATUS_INVALID_PARAMETER
;
1787 *ChildDevice
= (BusDeviceExtension
->Common
.IsBus
== FALSE
);
1789 return STATUS_SUCCESS
;
1798 KsServiceBusEnumCreateRequest(
1799 IN PDEVICE_OBJECT DeviceObject
,
1803 PBUS_DEVICE_ENTRY DeviceEntry
= NULL
; /* fix gcc */
1804 PIO_STACK_LOCATION IoStack
;
1805 BOOLEAN ItemExists
= FALSE
;
1806 PDEV_EXTENSION DeviceExtension
;
1807 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1808 //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension;
1814 /* get device extension */
1815 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1817 /* get bus device extension */
1818 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1820 /* get current irp stack location */
1821 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1824 ASSERT(IoStack
->FileObject
);
1825 ASSERT(IoStack
->FileObject
->FileName
.Buffer
);
1827 DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1829 /* scan list and check if it is already present */
1830 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1832 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1834 /* get real offset */
1835 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1837 /* check if name matches */
1838 if (!wcsicmp(DeviceEntry
->DeviceName
, IoStack
->FileObject
->FileName
.Buffer
+ 1))
1840 /* item already exists */
1845 /* move to next entry */
1846 Entry
= Entry
->Flink
;
1851 /* interface not registered */
1852 DPRINT1("Interface %wZ not registered\n", &IoStack
->FileObject
->FileName
);
1853 return STATUS_OBJECT_NAME_NOT_FOUND
;
1856 /* is there a pdo yet */
1857 if (DeviceEntry
->PDO
)
1859 if (DeviceEntry
->DeviceState
== Started
)
1862 Status
= KspDoReparseForIrp(Irp
, DeviceEntry
);
1863 DPRINT("REPARSE Irp %p '%wZ'\n", Irp
, &IoStack
->FileObject
->FileName
);
1865 Irp
->IoStatus
.Status
= Status
;
1869 /* delay processing until pnp is finished with enumeration */
1870 IoMarkIrpPending(Irp
);
1872 /* insert into irp pending list */
1873 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1875 Time
.QuadPart
= Int32x32To64(1500, -10000);
1876 DbgPrint("PENDING Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1878 /* query current time */
1879 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
1882 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1885 return STATUS_PENDING
;
1890 /* time to create PDO */
1891 Status
= KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1893 if (!NT_SUCCESS(Status
))
1895 /* failed to create PDO */
1896 DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status
);
1899 DPRINT1("PENDING CREATE Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1901 /* delay processing until pnp is finished with enumeration */
1902 IoMarkIrpPending(Irp
);
1904 /* insert into irp pending list */
1905 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1907 /* get current time */
1908 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
1910 /* invalidate device relations */
1911 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1914 return STATUS_PENDING
;
1924 KsServiceBusEnumPnpRequest(
1925 IN PDEVICE_OBJECT DeviceObject
,
1928 PDEV_EXTENSION DeviceExtension
;
1929 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1930 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
;
1931 PIO_STACK_LOCATION IoStack
;
1934 PDEVICE_RELATIONS DeviceRelation
;
1935 PBUS_DEVICE_ENTRY DeviceEntry
;
1937 /* get device extension */
1938 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1940 /* get bus device extension */
1941 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1943 /* get current irp stack location */
1944 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1946 if (BusDeviceExtension
->Common
.IsBus
)
1948 if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
1950 /* no op for bus driver */
1951 Status
= STATUS_SUCCESS
;
1953 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
)
1955 /* handle bus device relations */
1956 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== BusRelations
);
1958 Status
= KspQueryBusRelations(BusDeviceExtension
, Irp
);
1962 /* get default status */
1963 Status
= Irp
->IoStatus
.Status
;
1968 /* get child device extension */
1969 ChildDeviceExtension
= DeviceExtension
->Ext
;
1971 /* get bus device extension */
1972 BusDeviceExtension
= ChildDeviceExtension
->BusDeviceExtension
;
1974 if (IoStack
->MinorFunction
== IRP_MN_QUERY_ID
)
1977 Status
= KspQueryId(ChildDeviceExtension
, Irp
);
1979 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
1981 ASSERT(ChildDeviceExtension
->DeviceEntry
->DeviceState
!= Started
|| ChildDeviceExtension
->DeviceEntry
->DeviceState
== NotStarted
);
1982 ASSERT(ChildDeviceExtension
->DeviceEntry
->PDO
== DeviceObject
);
1984 /* backup device entry */
1985 DeviceEntry
= ChildDeviceExtension
->DeviceEntry
;
1987 /* free device extension */
1988 FreeItem(ChildDeviceExtension
);
1990 /* clear PDO reference */
1991 DeviceEntry
->PDO
= NULL
;
1993 /* delete the device */
1994 IoDeleteDevice(DeviceObject
);
1996 if (DeviceEntry
->PDODeviceName
)
1998 /* delete pdo device name */
1999 FreeItem(DeviceEntry
->PDODeviceName
);
2002 DeviceEntry
->PDODeviceName
= NULL
;
2005 /* set state no notstarted */
2006 DeviceEntry
->DeviceState
= NotStarted
;
2008 /* time to create PDO */
2009 KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
2011 /* invalidate device relations */
2012 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
2015 Status
= STATUS_SUCCESS
;
2017 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_BUS_INFORMATION
)
2019 /* query bus information */
2020 Status
= KspQueryBusInformation(ChildDeviceExtension
, Irp
);
2022 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCES
)
2025 Status
= STATUS_SUCCESS
;
2027 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCE_REQUIREMENTS
)
2030 Status
= STATUS_SUCCESS
;
2032 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
2035 Status
= KspStartBusDevice(DeviceObject
, ChildDeviceExtension
, Irp
);
2038 Time
.QuadPart
= Int32x32To64(1500, -10000);
2041 ASSERT(BusDeviceExtension
);
2044 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
2046 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_CAPABILITIES
)
2048 /* query capabilities */
2049 Status
= KspQueryBusDeviceCapabilities(ChildDeviceExtension
, Irp
);
2051 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
2053 /* query pnp state */
2054 Status
= KspQueryBusDevicePnpState(ChildDeviceExtension
, Irp
);
2056 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_INTERFACE
)
2058 /* query interface */
2059 Status
= KspQueryBusDeviceInterface(ChildDeviceExtension
, Irp
);
2061 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
&& IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
2063 /* handle target device relations */
2064 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
);
2065 ASSERT(Irp
->IoStatus
.Information
== 0);
2067 /* allocate device relation */
2068 DeviceRelation
= AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
));
2071 DeviceRelation
->Count
= 1;
2072 DeviceRelation
->Objects
[0] = DeviceObject
;
2074 /* reference self */
2075 ObReferenceObject(DeviceObject
);
2078 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelation
;
2081 Status
= STATUS_SUCCESS
;
2086 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2091 /* get default status */
2092 Status
= Irp
->IoStatus
.Status
;
2096 DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject
, BusDeviceExtension
->Common
.IsBus
, IoStack
->MinorFunction
, Status
);
2097 Irp
->IoStatus
.Status
= Status
;
2107 KsRemoveBusEnumInterface(
2110 KPROCESSOR_MODE Mode
;
2112 BUS_INSTALL_ENUM_CONTEXT Ctx
;
2113 PDEV_EXTENSION DeviceExtension
;
2114 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
2115 PIO_STACK_LOCATION IoStack
;
2117 DPRINT1("KsRemoveBusEnumInterface\n");
2119 /* get io stack location */
2120 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2122 /* get device extension */
2123 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
2125 /* get bus device extension */
2126 BusDeviceExtension
= DeviceExtension
->Ext
->BusDeviceExtension
;
2128 /* get previous mode */
2129 Mode
= ExGetPreviousMode();
2131 /* convert to luid */
2132 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
2134 /* perform access check */
2135 if (!SeSinglePrivilegeCheck(luid
, Mode
))
2137 /* insufficient privileges */
2138 return STATUS_PRIVILEGE_NOT_HELD
;
2141 /* initialize context */
2142 KeInitializeEvent(&Ctx
.Event
, NotificationEvent
, FALSE
);
2144 Ctx
.BusDeviceExtension
= BusDeviceExtension
;
2145 ExInitializeWorkItem(&Ctx
.WorkItem
, KspRemoveBusInterface
, (PVOID
)&Ctx
);
2147 /* now queue the work item */
2148 ExQueueWorkItem(&Ctx
.WorkItem
, DelayedWorkQueue
);
2150 /* wait for completion */
2151 KeWaitForSingleObject(&Ctx
.Event
, Executive
, KernelMode
, FALSE
, NULL
);