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
17 LONG KsDeviceCount
= 0;
19 typedef NTSTATUS (NTAPI
*PKSP_BUS_ENUM_CALLBACK
)(
21 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
22 IN PBUS_DEVICE_ENTRY DummyEntry
,
24 IN LPWSTR DirectoryName
);
28 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
29 IN PBUS_DEVICE_ENTRY DeviceEntry
,
30 OUT PDEVICE_OBJECT
* OutDeviceObject
)
32 PDEVICE_OBJECT DeviceObject
;
35 UNICODE_STRING DeviceName
;
37 PCOMMON_DEVICE_EXTENSION DeviceExtension
;
39 /* increment device count */
40 CurDeviceId
= InterlockedIncrement(&KsDeviceCount
);
42 /* generate new device id */
43 swprintf(Buffer
, L
"\\Device\\KSENUM%08x", CurDeviceId
);
45 /* initialize new device name */
46 RtlInitUnicodeString(&DeviceName
, Buffer
);
48 /* create new device object */
49 Status
= IoCreateDevice(BusDeviceExtension
->BusDeviceObject
->DriverObject
, sizeof(PVOID
), &DeviceName
, FILE_DEVICE_UNKNOWN
, 0, FALSE
, &DeviceObject
);
51 /* check for success */
52 if (!NT_SUCCESS(Status
))
54 /* failed to create pdo */
58 /* now allocate device extension */
59 DeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)AllocateItem(NonPagedPool
, sizeof(COMMON_DEVICE_EXTENSION
));
63 IoDeleteDevice(DeviceObject
);
64 return STATUS_INSUFFICIENT_RESOURCES
;
67 /* store device extension */
68 *((PVOID
*)DeviceObject
->DeviceExtension
) = DeviceExtension
;
70 /* initialize device extension */
71 DeviceExtension
->IsBus
= FALSE
;
72 DeviceExtension
->DeviceObject
= DeviceObject
;
73 DeviceExtension
->DeviceEntry
= DeviceEntry
;
74 DeviceExtension
->BusDeviceExtension
= BusDeviceExtension
;
76 /* TODO: update last creation time in bus device extension */
79 DeviceObject
->Flags
|= DO_POWER_PAGABLE
;
80 DeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
81 /* TODO: fire time when expired */
83 *OutDeviceObject
= DeviceObject
;
85 return STATUS_SUCCESS
;
89 KspRegisterDeviceAssociation(
90 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
91 IN PBUS_DEVICE_ENTRY DeviceEntry
,
92 IN OUT PBUS_INSTANCE_ENTRY BusInstanceEntry
)
95 UNICODE_STRING ReferenceString
;
97 /* initialize reference string */
98 RtlInitUnicodeString(&ReferenceString
, DeviceEntry
->DeviceName
);
100 /* register device interface */
101 Status
= IoRegisterDeviceInterface(BusDeviceExtension
->PhysicalDeviceObject
, &BusInstanceEntry
->InterfaceGuid
, &ReferenceString
, &BusInstanceEntry
->SymbolicLink
);
103 /* check for success */
104 if (!NT_SUCCESS(Status
))
110 /* now enable the interface */
111 Status
= IoSetDeviceInterfaceState(&BusInstanceEntry
->SymbolicLink
, TRUE
);
113 /* check for success */
114 if (!NT_SUCCESS(Status
))
116 /* failed, free memory */
117 FreeItem(BusInstanceEntry
->SymbolicLink
.Buffer
);
121 DPRINT1("Registered DeviceInterface %wZ\n", &BusInstanceEntry
->SymbolicLink
);
129 KspRemoveDeviceAssociations(
130 IN PBUS_DEVICE_ENTRY DeviceEntry
)
133 PBUS_INSTANCE_ENTRY CurEntry
;
135 /* remove all entries */
136 Entry
= DeviceEntry
->DeviceInterfaceList
.Flink
;
138 while(Entry
!= &DeviceEntry
->DeviceInterfaceList
)
141 CurEntry
= (PBUS_INSTANCE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_INSTANCE_ENTRY
, Entry
);
144 ASSERT(CurEntry
->SymbolicLink
.Buffer
);
146 /* de-register interface */
147 IoSetDeviceInterfaceState(&CurEntry
->SymbolicLink
, FALSE
);
149 /* free symbolic link buffer */
150 FreeItem(CurEntry
->SymbolicLink
.Buffer
);
152 /* remove entry from list */
153 RemoveEntryList(Entry
);
155 /* move to next entry */
156 Entry
= Entry
->Flink
;
164 KspEnumerateBusRegistryKeys(
166 IN LPWSTR ReferenceString
,
167 IN PKSP_BUS_ENUM_CALLBACK Callback
,
168 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
169 IN PBUS_DEVICE_ENTRY DeviceEntry
)
171 UNICODE_STRING String
;
172 OBJECT_ATTRIBUTES ObjectAttributes
;
175 ULONG ResultLength
, Index
, KeyInfoLength
;
176 KEY_FULL_INFORMATION KeyInformation
;
177 PKEY_BASIC_INFORMATION KeyInfo
;
179 /* initialize key name */
180 RtlInitUnicodeString(&String
, ReferenceString
);
182 /* initialize object attributes */
183 InitializeObjectAttributes(&ObjectAttributes
, &String
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hKey
, NULL
);
186 Status
= ZwOpenKey(&hNewKey
, GENERIC_READ
, &ObjectAttributes
);
188 /* check for success */
189 if (!NT_SUCCESS(Status
))
191 /* failed to open key */
196 /* query key stats */
197 Status
= ZwQueryKey(hNewKey
, KeyFullInformation
, &KeyInformation
, sizeof(KeyInformation
), &ResultLength
);
199 if (!NT_SUCCESS(Status
))
208 /* calculate key info length */
209 KeyInfoLength
= KeyInformation
.MaxNameLen
+ sizeof(KEY_BASIC_INFORMATION
) + 1 * sizeof(WCHAR
);
211 /* allocate buffer */
212 KeyInfo
= (PKEY_BASIC_INFORMATION
)AllocateItem(NonPagedPool
, KeyInfoLength
);
220 return STATUS_INSUFFICIENT_RESOURCES
;
223 /* enumerate all keys */
224 for(Index
= 0; Index
< KeyInformation
.SubKeys
; Index
++)
228 Status
= ZwEnumerateKey(hNewKey
, Index
, KeyBasicInformation
, (PVOID
)KeyInfo
, KeyInfoLength
, &ResultLength
);
230 /* check for success */
231 if (NT_SUCCESS(Status
))
233 /* perform callback */
234 Status
= Callback(hNewKey
, BusDeviceExtension
, DeviceEntry
, ReferenceString
, KeyInfo
->Name
);
236 /* should enumeration stop */
237 if (!NT_SUCCESS(Status
))
242 /* free info buffer */
254 KspCreateDeviceAssociation(
256 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
257 IN PBUS_DEVICE_ENTRY DeviceEntry
,
258 IN LPWSTR ReferenceString
,
259 IN LPWSTR InterfaceString
)
264 PBUS_INSTANCE_ENTRY CurEntry
;
265 UNICODE_STRING DeviceName
;
267 /* initialize interface string */
268 RtlInitUnicodeString(&DeviceName
, InterfaceString
);
270 /* first convert device name to guid */
271 RtlGUIDFromString(&DeviceName
, &DeviceGuid
);
273 /* check if the device is already present */
274 Entry
= DeviceEntry
->DeviceInterfaceList
.Flink
;
276 while(Entry
!= &DeviceEntry
->DeviceInterfaceList
)
279 CurEntry
= (PBUS_INSTANCE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_INSTANCE_ENTRY
, Entry
);
281 if (IsEqualGUIDAligned(&CurEntry
->InterfaceGuid
, &DeviceGuid
))
283 /* entry already exists */
284 return STATUS_SUCCESS
;
287 /* move to next entry */
288 Entry
= Entry
->Flink
;
291 /* time to allocate new entry */
292 CurEntry
= (PBUS_INSTANCE_ENTRY
)AllocateItem(NonPagedPool
, sizeof(BUS_INSTANCE_ENTRY
));
297 return STATUS_INSUFFICIENT_RESOURCES
;
301 RtlMoveMemory(&CurEntry
->InterfaceGuid
, &DeviceGuid
, sizeof(GUID
));
303 /* now register the association */
304 Status
= KspRegisterDeviceAssociation(BusDeviceExtension
, DeviceEntry
, CurEntry
);
306 /* check for success */
307 if (NT_SUCCESS(Status
))
310 InsertTailList(&DeviceEntry
->DeviceInterfaceList
, &CurEntry
->Entry
);
314 /* failed to associated device */
324 KspCreateDeviceReference(
326 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
327 IN PBUS_DEVICE_ENTRY DummyEntry
,
328 IN LPWSTR DeviceCategory
,
329 IN LPWSTR ReferenceString
)
334 PBUS_DEVICE_ENTRY DeviceEntry
= NULL
; /* GCC warning */
335 BOOLEAN ItemExists
= FALSE
;
336 UNICODE_STRING String
;
340 /* first construct device name & reference guid */
341 Length
= wcslen(DeviceCategory
) + wcslen(ReferenceString
);
343 /* append '&' and null byte */
346 /* allocate device name */
347 DeviceName
= AllocateItem(NonPagedPool
, Length
* sizeof(WCHAR
));
351 /* not enough memory */
352 return STATUS_INSUFFICIENT_RESOURCES
;
355 /* construct device name */
356 swprintf(DeviceName
, L
"%s&%s", DeviceCategory
, ReferenceString
);
358 /* scan list and check if it is already present */
359 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
361 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
363 /* get real offset */
364 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
366 /* check if name matches */
367 if (!wcsicmp(DeviceEntry
->DeviceName
, DeviceName
))
369 /* item already exists */
374 /* move to next entry */
375 Entry
= Entry
->Flink
;
380 /* allocate new device entry */
381 DeviceEntry
= AllocateItem(NonPagedPool
, sizeof(BUS_DEVICE_ENTRY
));
385 FreeItem(DeviceName
);
386 return STATUS_INSUFFICIENT_RESOURCES
;
389 /* initialize device entry */
390 InitializeListHead(&DeviceEntry
->DeviceInterfaceList
);
391 InitializeListHead(&DeviceEntry
->IrpPendingList
);
393 /* copy device guid */
394 RtlInitUnicodeString(&String
, ReferenceString
);
395 RtlGUIDFromString(&String
, &DeviceEntry
->DeviceGuid
);
397 /* copy device names */
398 DeviceEntry
->DeviceName
= DeviceName
;
399 DeviceEntry
->Instance
= (DeviceName
+ wcslen(DeviceCategory
) + 1);
402 DeviceEntry
->BusId
= AllocateItem(NonPagedPool
, (wcslen(DeviceCategory
) + 1) * sizeof(WCHAR
));
403 if (!DeviceEntry
->BusId
)
406 FreeItem(DeviceName
);
407 FreeItem(DeviceEntry
);
408 return STATUS_INSUFFICIENT_RESOURCES
;
410 wcscpy(DeviceEntry
->BusId
, DeviceCategory
);
413 /* now enumerate the devices */
414 Status
= KspEnumerateBusRegistryKeys(hKey
, ReferenceString
, KspCreateDeviceAssociation
, BusDeviceExtension
, DeviceEntry
);
416 /* check if list is empty */
417 if (IsListEmpty(&DeviceEntry
->DeviceInterfaceList
))
419 /* invalid device settings */
420 FreeItem(DeviceEntry
->BusId
);
421 FreeItem(DeviceEntry
->DeviceName
);
422 FreeItem(DeviceEntry
);
424 ASSERT(ItemExists
== FALSE
);
426 return STATUS_INVALID_DEVICE_STATE
;
429 /* check if enumeration failed */
430 if (!NT_SUCCESS(Status
))
433 KspRemoveDeviceAssociations(DeviceEntry
);
434 FreeItem(DeviceEntry
->BusId
);
435 FreeItem(DeviceEntry
->DeviceName
);
436 FreeItem(DeviceEntry
);
438 ASSERT(ItemExists
== FALSE
);
447 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
449 /* successfully initialized entry */
450 InsertTailList(&BusDeviceExtension
->Common
.Entry
, &DeviceEntry
->Entry
);
453 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
462 KspCreateDeviceReferenceTrampoline(
464 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
465 IN PBUS_DEVICE_ENTRY DummyEntry
,
466 IN LPWSTR DeviceCategory
,
467 IN LPWSTR ReferenceString
)
469 return KspEnumerateBusRegistryKeys(hKey
, ReferenceString
, KspCreateDeviceReference
, BusDeviceExtension
, DummyEntry
);
474 KspOpenBusRegistryKey(
475 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
478 OBJECT_ATTRIBUTES ObjectAttributes
;
480 /* initialize object attributes */
481 InitializeObjectAttributes(&ObjectAttributes
, &BusDeviceExtension
->ServicePath
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
483 return ZwCreateKey(hKey
, GENERIC_READ
| GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
488 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
)
494 Status
= KspOpenBusRegistryKey(BusDeviceExtension
, &hKey
);
496 /* check for success */
497 if (!NT_SUCCESS(Status
))
504 /* TODO clear reference marks */
506 /* construct device entries */
507 Status
= KspEnumerateBusRegistryKeys(hKey
, NULL
, KspCreateDeviceReferenceTrampoline
, BusDeviceExtension
, NULL
);
509 /* TODO: delete unreferenced devices */
521 KspBusQueryReferenceString(
523 IN OUT PWCHAR
*String
)
527 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)Context
;
530 ASSERT(BusDeviceExtension
);
531 ASSERT(BusDeviceExtension
->BusIdentifier
);
533 /* calculate length */
534 Length
= wcslen(BusDeviceExtension
->BusIdentifier
) + 1;
536 /* allocate buffer */
537 Name
= AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
541 /* failed to allocate buffer */
542 return STATUS_INSUFFICIENT_RESOURCES
;
546 wcscpy(Name
, BusDeviceExtension
->BusIdentifier
);
552 return STATUS_SUCCESS
;
557 KspBusDeviceReference(
560 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
562 /* reference count */
563 InterlockedIncrement((PLONG
)&ChildDeviceExtension
->DeviceReferenceCount
);
568 KspBusDeviceDereference(
571 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
573 /* reference count */
574 InterlockedDecrement((PLONG
)&ChildDeviceExtension
->DeviceReferenceCount
);
579 KspBusReferenceDeviceObject(
582 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
584 /* reference count */
585 InterlockedIncrement((PLONG
)&ChildDeviceExtension
->DeviceObjectReferenceCount
);
590 KspBusDereferenceDeviceObject(
593 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
595 /* reference count */
596 InterlockedDecrement((PLONG
)&ChildDeviceExtension
->DeviceObjectReferenceCount
);
600 KspQueryBusDeviceInterface(
601 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
604 PBUS_INTERFACE_SWENUM Interface
;
605 PIO_STACK_LOCATION IoStack
;
607 /* get current irp stack location */
608 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
611 ASSERT(IoStack
->Parameters
.QueryInterface
.Size
== sizeof(BUS_INTERFACE_SWENUM
));
612 ASSERT(IoStack
->Parameters
.QueryInterface
.Interface
);
614 /* fill in interface */
615 Interface
= (PBUS_INTERFACE_SWENUM
)IoStack
->Parameters
.QueryInterface
.Interface
;
616 Interface
->Interface
.Size
= sizeof(BUS_INTERFACE_SWENUM
);
617 Interface
->Interface
.Version
= BUS_INTERFACE_SWENUM_VERSION
;
618 Interface
->Interface
.Context
= ChildDeviceExtension
;
619 Interface
->Interface
.InterfaceReference
= KspBusDeviceReference
;
620 Interface
->Interface
.InterfaceDereference
= KspBusDeviceDereference
;
621 Interface
->ReferenceDeviceObject
= KspBusReferenceDeviceObject
;
622 Interface
->DereferenceDeviceObject
= KspBusDereferenceDeviceObject
;
623 Interface
->QueryReferenceString
= KspBusQueryReferenceString
;
625 return STATUS_SUCCESS
;
629 KspEnableBusDeviceInterface(
630 PBUS_DEVICE_ENTRY DeviceEntry
,
634 PBUS_INSTANCE_ENTRY InstanceEntry
;
635 NTSTATUS Status
= STATUS_SUCCESS
;
637 /* enable now all interfaces */
638 Entry
= DeviceEntry
->DeviceInterfaceList
.Flink
;
640 while(Entry
!= &DeviceEntry
->DeviceInterfaceList
)
642 /* get bus instance entry */
643 InstanceEntry
= (PBUS_INSTANCE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_INSTANCE_ENTRY
, Entry
);
644 DPRINT1("Enabling %u %wZ Irql %u\n", bEnable
, &InstanceEntry
->SymbolicLink
, KeGetCurrentIrql());
646 /* set interface state */
647 Status
= IoSetDeviceInterfaceState(&InstanceEntry
->SymbolicLink
, bEnable
);
649 if (!NT_SUCCESS(Status
))
651 /* failed to set interface */
655 /* move to next entry */
656 Entry
= Entry
->Flink
;
666 PBUS_DEVICE_ENTRY DeviceEntry
)
670 PIO_STACK_LOCATION IoStack
;
672 /* get stack location */
673 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
676 ASSERT(DeviceEntry
->PDODeviceName
);
677 ASSERT(DeviceEntry
->Instance
);
678 ASSERT(IoStack
->FileObject
);
679 ASSERT(IoStack
->FileObject
->FileName
.Buffer
);
681 /* calculate length */
682 Length
= wcslen(DeviceEntry
->PDODeviceName
);
683 Length
+= wcslen(DeviceEntry
->Instance
);
685 /* zero byte and '\\' */
688 /* allocate buffer */
689 Buffer
= AllocateItem(NonPagedPool
, Length
* sizeof(WCHAR
));
693 return STATUS_INSUFFICIENT_RESOURCES
;
696 /* construct buffer */
697 swprintf(Buffer
, L
"%s\\%s", DeviceEntry
->PDODeviceName
, DeviceEntry
->Instance
);
699 ExFreePool(IoStack
->FileObject
->FileName
.Buffer
);
701 /* store new file name */
702 RtlInitUnicodeString(&IoStack
->FileObject
->FileName
, Buffer
);
705 return STATUS_REPARSE
;
709 KspCompletePendingIrps(
710 IN PBUS_DEVICE_ENTRY DeviceEntry
,
711 IN OUT NTSTATUS ResultCode
)
717 /* go through list */
718 while(!IsListEmpty(&DeviceEntry
->IrpPendingList
))
720 /* get first entry */
721 Entry
= RemoveHeadList(&DeviceEntry
->IrpPendingList
);
724 Irp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
726 if (ResultCode
== STATUS_REPARSE
)
728 /* construct reparse information */
729 Status
= KspDoReparseForIrp(Irp
, DeviceEntry
);
733 /* use default code */
737 /* store result code */
738 Irp
->IoStatus
.Status
= Status
;
740 DPRINT1("Completing IRP %p Status %x\n", Irp
, Status
);
742 /* complete the request */
743 CompleteRequest(Irp
, IO_NO_INCREMENT
);
752 IN PDEVICE_OBJECT DeviceObject
,
753 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
761 PBUS_DEVICE_ENTRY DeviceEntry
;
763 /* FIXME handle pending remove */
765 /* get full device name */
766 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyPhysicalDeviceObjectName
, sizeof(PDOName
), PDOName
, &ResultLength
);
768 if (!NT_SUCCESS(Status
))
770 /* failed to get device name */
774 /* allocate device name buffer */
775 NameLength
= ResultLength
+ sizeof(UNICODE_NULL
);
776 Name
= AllocateItem(NonPagedPool
, NameLength
);
780 return STATUS_INSUFFICIENT_RESOURCES
;
784 NT_VERIFY(NT_SUCCESS(RtlStringCbCopyW(Name
, NameLength
, PDOName
)));
786 /* TODO: time stamp creation time */
788 /* get device entry */
789 DeviceEntry
= (PBUS_DEVICE_ENTRY
)ChildDeviceExtension
->DeviceEntry
;
794 /* store device name */
795 DeviceEntry
->PDODeviceName
= Name
;
797 /* mark device as started */
798 DeviceEntry
->DeviceState
= Started
;
800 /* reference start time */
801 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
803 DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name
, DeviceEntry
->DeviceName
, DeviceEntry
->Instance
);
805 /* enable device classes */
806 //KspEnableBusDeviceInterface(DeviceEntry, TRUE);
809 return STATUS_SUCCESS
;
813 KspQueryBusDeviceCapabilities(
814 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
817 PDEVICE_CAPABILITIES Capabilities
;
818 PIO_STACK_LOCATION IoStack
;
820 /* get stack location */
821 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
823 /* get capabilities */
824 Capabilities
= IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
826 RtlZeroMemory(Capabilities
, sizeof(DEVICE_CAPABILITIES
));
828 /* setup capabilities */
829 Capabilities
->UniqueID
= TRUE
;
830 Capabilities
->SilentInstall
= TRUE
;
831 Capabilities
->SurpriseRemovalOK
= TRUE
;
832 Capabilities
->Address
= 0;
833 Capabilities
->UINumber
= 0;
834 Capabilities
->SystemWake
= PowerSystemWorking
; /* FIXME common device extension */
835 Capabilities
->DeviceWake
= PowerDeviceD0
;
838 return STATUS_SUCCESS
;
842 KspQueryBusInformation(
843 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
846 PPNP_BUS_INFORMATION BusInformation
;
848 /* allocate bus information */
849 BusInformation
= (PPNP_BUS_INFORMATION
)AllocateItem(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
854 return STATUS_INSUFFICIENT_RESOURCES
;
858 BusInformation
->BusNumber
= 0;
859 BusInformation
->LegacyBusType
= InterfaceTypeUndefined
;
860 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &KSMEDIUMSETID_Standard
, sizeof(GUID
));
863 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
866 return STATUS_SUCCESS
;
870 KspQueryBusDevicePnpState(
871 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
874 /* set device flags */
875 Irp
->IoStatus
.Information
= PNP_DEVICE_DONT_DISPLAY_IN_UI
| PNP_DEVICE_NOT_DISABLEABLE
;
878 return STATUS_SUCCESS
;
883 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
886 PIO_STACK_LOCATION IoStack
;
887 PBUS_DEVICE_ENTRY DeviceEntry
;
888 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
892 /* get current irp stack location */
893 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
895 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryInstanceID
)
897 /* get device entry */
898 DeviceEntry
= (PBUS_DEVICE_ENTRY
) ChildDeviceExtension
->DeviceEntry
;
902 ASSERT(DeviceEntry
->Instance
);
904 /* calculate length */
905 Length
= wcslen(DeviceEntry
->Instance
) + 1;
907 /* allocate buffer */
908 Name
= AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
912 /* failed to allocate buffer */
913 return STATUS_INSUFFICIENT_RESOURCES
;
917 wcscpy(Name
, DeviceEntry
->Instance
);
920 Irp
->IoStatus
.Information
= (ULONG_PTR
)Name
;
923 return STATUS_SUCCESS
;
925 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
||
926 IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
928 /* get device entry */
929 DeviceEntry
= (PBUS_DEVICE_ENTRY
) ChildDeviceExtension
->DeviceEntry
;
931 /* get bus device extension */
932 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
) ChildDeviceExtension
->BusDeviceExtension
;
936 ASSERT(DeviceEntry
->BusId
);
937 ASSERT(BusDeviceExtension
);
938 ASSERT(BusDeviceExtension
->BusIdentifier
);
940 /* calculate length */
941 Length
= wcslen(BusDeviceExtension
->BusIdentifier
);
942 Length
+= wcslen(DeviceEntry
->BusId
);
944 /* extra length for '\\' and zero byte */
947 /* allocate buffer */
948 Name
= ExAllocatePool(PagedPool
, Length
* sizeof(WCHAR
));
951 /* failed to allocate buffer */
952 return STATUS_INSUFFICIENT_RESOURCES
;
956 swprintf(Name
, L
"%s\\%s", BusDeviceExtension
->BusIdentifier
, DeviceEntry
->BusId
);
959 Irp
->IoStatus
.Information
= (ULONG_PTR
)Name
;
962 return STATUS_SUCCESS
;
966 /* other ids are not supported */
967 //DPRINT1("Not Supported ID Type %x\n", IoStack->Parameters.QueryId.IdType);
968 return Irp
->IoStatus
.Status
;
974 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
975 IN PSWENUM_INSTALL_INTERFACE InstallInterface
)
977 SIZE_T Length
, Index
;
978 UNICODE_STRING DeviceString
, InterfaceString
, ReferenceString
;
979 HANDLE hKey
, hDeviceKey
, hInterfaceKey
, hReferenceKey
;
981 OBJECT_ATTRIBUTES ObjectAttributes
;
984 ASSERT(InstallInterface
);
986 /* calculate length */
987 Length
= wcslen(InstallInterface
->ReferenceString
);
989 /* check for invalid characters */
990 for(Index
= 0; Index
< Length
; Index
++)
992 if (InstallInterface
->ReferenceString
[Index
] <= L
' ' ||
993 InstallInterface
->ReferenceString
[Index
] > L
'~' ||
994 InstallInterface
->ReferenceString
[Index
] == L
',' ||
995 InstallInterface
->ReferenceString
[Index
] == L
'\\' ||
996 InstallInterface
->ReferenceString
[Index
] == L
'/')
998 /* invalid character */
999 return STATUS_INVALID_PARAMETER
;
1004 Status
= KspOpenBusRegistryKey(BusDeviceExtension
, &hKey
);
1005 if (NT_SUCCESS(Status
))
1007 /* convert device guid to string */
1008 Status
= RtlStringFromGUID(&InstallInterface
->DeviceId
, &DeviceString
);
1009 if (NT_SUCCESS(Status
))
1011 /* initialize object attributes */
1012 InitializeObjectAttributes(&ObjectAttributes
, &DeviceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hKey
, NULL
);
1014 /* construct device key */
1015 Status
= ZwCreateKey(&hDeviceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1016 if (NT_SUCCESS(Status
))
1018 /* initialize reference string */
1019 RtlInitUnicodeString(&ReferenceString
, InstallInterface
->ReferenceString
);
1021 /* initialize object attributes */
1022 InitializeObjectAttributes(&ObjectAttributes
, &ReferenceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceKey
, NULL
);
1024 /* construct device key */
1025 Status
= ZwCreateKey(&hReferenceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1026 if (NT_SUCCESS(Status
))
1028 /* convert interface guid to string */
1029 Status
= RtlStringFromGUID(&InstallInterface
->InterfaceId
, &InterfaceString
);
1030 if (NT_SUCCESS(Status
))
1032 /* initialize object attributes */
1033 InitializeObjectAttributes(&ObjectAttributes
, &InterfaceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hReferenceKey
, NULL
);
1035 /* construct device key */
1036 Status
= ZwCreateKey(&hInterfaceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1037 if (NT_SUCCESS(Status
))
1040 ZwClose(hInterfaceKey
);
1042 /* free interface string */
1043 RtlFreeUnicodeString(&InterfaceString
);
1045 /* close reference key */
1046 ZwClose(hReferenceKey
);
1048 /* close device key */
1049 ZwClose(hDeviceKey
);
1051 /* free device string */
1052 RtlFreeUnicodeString(&DeviceString
);
1064 KspInstallBusEnumInterface(
1067 PIO_STACK_LOCATION IoStack
;
1070 PBUS_DEVICE_ENTRY DeviceEntry
;
1071 PSWENUM_INSTALL_INTERFACE InstallInterface
;
1073 PBUS_INSTALL_ENUM_CONTEXT Context
= (PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1075 /* get current irp stack location */
1076 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
1078 /* get install request */
1079 InstallInterface
= (PSWENUM_INSTALL_INTERFACE
)Context
->Irp
->AssociatedIrp
.SystemBuffer
;
1082 ASSERT(InstallInterface
);
1083 ASSERT(Context
->BusDeviceExtension
);
1085 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(SWENUM_INSTALL_INTERFACE
))
1087 /* buffer too small */
1088 Context
->Status
= STATUS_INVALID_PARAMETER
;
1090 /* signal completion */
1091 KeSetEvent(&Context
->Event
, 0, FALSE
);
1099 /* now install the interface */
1100 Status
= KspInstallInterface(Context
->BusDeviceExtension
, InstallInterface
);
1101 if (!NT_SUCCESS(Status
))
1103 /* failed to install interface */
1104 Context
->Status
= Status
;
1106 /* signal completion */
1107 KeSetEvent(&Context
->Event
, 0, FALSE
);
1113 /* acquire device entry lock */
1114 KeAcquireSpinLock(&Context
->BusDeviceExtension
->Lock
, &OldLevel
);
1116 /* now iterate all device entries */
1117 Entry
= Context
->BusDeviceExtension
->Common
.Entry
.Flink
;
1118 while(Entry
!= &Context
->BusDeviceExtension
->Common
.Entry
)
1120 /* get device entry */
1121 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1123 if (IsEqualGUIDAligned(&DeviceEntry
->DeviceGuid
, &InstallInterface
->DeviceId
) &&
1124 !wcsicmp(DeviceEntry
->Instance
, InstallInterface
->ReferenceString
))
1126 if (!DeviceEntry
->PDO
)
1129 Status
= KspCreatePDO(Context
->BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1136 /* move to next entry */
1137 Entry
= Entry
->Flink
;
1140 /* release device entry lock */
1141 KeReleaseSpinLock(&Context
->BusDeviceExtension
->Lock
, OldLevel
);
1143 /* signal that bus driver relations has changed */
1144 IoInvalidateDeviceRelations(Context
->BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1147 Context
->Status
= Status
;
1149 /* signal completion */
1150 KeSetEvent(&Context
->Event
, 0, FALSE
);
1156 KspBusWorkerRoutine(
1159 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1160 PBUS_DEVICE_ENTRY DeviceEntry
;
1162 LARGE_INTEGER Time
, Diff
;
1163 BOOLEAN DoInvalidate
= FALSE
;
1166 /* get device extension */
1167 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)Parameter
;
1170 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1172 /* get current time */
1173 KeQuerySystemTime(&Time
);
1175 /* enumerate all device entries */
1176 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1177 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1179 /* get offset to device entry */
1180 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1183 ASSERT(DeviceEntry
);
1185 //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState);
1187 if (DeviceEntry
->PDO
)
1189 if (DeviceEntry
->DeviceState
== NotStarted
)
1191 Diff
.QuadPart
= Time
.QuadPart
- DeviceEntry
->TimeCreated
.QuadPart
;
1193 if (Diff
.QuadPart
> Int32x32To64(15000, 10000))
1195 DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry
->DeviceName
, DeviceEntry
->Instance
, DeviceEntry
->TimeCreated
.QuadPart
, Time
.QuadPart
, Diff
.QuadPart
);
1197 /* release spin lock */
1198 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1200 /* deactivate interfaces */
1201 //KspEnableBusDeviceInterface(DeviceEntry, FALSE);
1203 /* re-acquire lock */
1204 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1206 /* pending remove device object */
1207 DeviceEntry
->DeviceState
= StopPending
;
1209 /* perform invalidation */
1210 DoInvalidate
= TRUE
;
1213 else if (DeviceEntry
->DeviceState
== Started
)
1215 /* found pending irps */
1216 KspCompletePendingIrps(DeviceEntry
, STATUS_REPARSE
);
1222 Entry
= Entry
->Flink
;
1226 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1230 /* invalidate device relations */
1231 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1234 Time
.QuadPart
= Int32x32To64(5000, -10000);
1235 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1242 IN PVOID DeferredContext OPTIONAL
,
1243 IN PVOID SystemArgument1 OPTIONAL
,
1244 IN PVOID SystemArgument2 OPTIONAL
)
1246 /* get device extension */
1247 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeferredContext
;
1249 /* queue the item */
1250 ExQueueWorkItem(&BusDeviceExtension
->WorkItem
, DelayedWorkQueue
);
1255 KspRemoveBusInterface(
1258 PBUS_INSTALL_ENUM_CONTEXT Context
=(PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1261 * get SWENUM_INSTALL_INTERFACE struct
1262 * open device key and delete the keys
1268 Context
->Status
= STATUS_NOT_IMPLEMENTED
;
1271 /* signal completion */
1272 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
1276 KspQueryBusRelations(
1277 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
1280 PDEVICE_RELATIONS DeviceRelations
;
1282 PBUS_DEVICE_ENTRY DeviceEntry
;
1283 ULONG Count
= 0, Length
;
1287 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1289 /* first scan all device entries */
1290 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1292 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1294 /* get offset to device entry */
1295 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1297 /* is there a pdo yet */
1298 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1300 /* increment count */
1304 /* move to next entry */
1305 Entry
= Entry
->Flink
;
1308 /* calculate length */
1309 Length
= sizeof(DEVICE_RELATIONS
) + (Count
> 1 ? sizeof(PDEVICE_OBJECT
) * (Count
-1) : 0);
1311 /* allocate device relations */
1312 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(NonPagedPool
, Length
);
1314 if (!DeviceRelations
)
1316 /* not enough memory */
1317 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1318 return STATUS_INSUFFICIENT_RESOURCES
;
1321 /* rescan device entries */
1322 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1324 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1326 /* get offset to device entry */
1327 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1329 /* is there a pdo yet */
1330 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1333 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceEntry
->PDO
;
1335 /* reference device object */
1336 ObReferenceObject(DeviceEntry
->PDO
);
1338 /* increment pdo count */
1339 DeviceRelations
->Count
++;
1342 /* move to next entry */
1343 Entry
= Entry
->Flink
;
1347 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1349 /* FIXME handle existing device relations */
1350 ASSERT(Irp
->IoStatus
.Information
== 0);
1352 /* store device relations */
1353 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
1356 return STATUS_SUCCESS
;
1359 //------------------------------------------------------------------------------------
1368 KsGetBusEnumIdentifier(
1371 PDEV_EXTENSION DeviceExtension
;
1372 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1373 PIO_STACK_LOCATION IoStack
;
1378 DPRINT1("KsGetBusEnumIdentifier\n");
1380 /* get stack location */
1381 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1384 ASSERT(IoStack
->DeviceObject
);
1385 ASSERT(IoStack
->DeviceObject
->DeviceExtension
);
1387 /* get device extension */
1388 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1390 /* get bus device extension */
1391 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1394 ASSERT(BusDeviceExtension
);
1395 ASSERT(BusDeviceExtension
->Common
.IsBus
);
1397 if (!BusDeviceExtension
)
1399 /* invalid parameter */
1400 return STATUS_INVALID_PARAMETER
;
1404 Length
= (wcslen(BusDeviceExtension
->BusIdentifier
)+1) * sizeof(WCHAR
);
1406 /* is there an output buffer provided */
1407 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1409 if (Length
> IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1411 /* buffer is too small */
1412 return STATUS_BUFFER_TOO_SMALL
;
1415 /* now allocate buffer */
1416 Buffer
= AllocateItem(NonPagedPool
, Length
);
1420 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1424 /* copy bus identifier */
1425 wcscpy(Buffer
, BusDeviceExtension
->BusIdentifier
);
1428 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
1430 /* set flag that buffer gets copied back */
1431 Irp
->Flags
|= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
1434 Status
= STATUS_SUCCESS
;
1439 /* no buffer provided */
1440 Status
= STATUS_BUFFER_OVERFLOW
;
1444 Irp
->IoStatus
.Status
= Status
;
1454 KsGetBusEnumParentFDOFromChildPDO(
1455 IN PDEVICE_OBJECT DeviceObject
,
1456 OUT PDEVICE_OBJECT
*FunctionalDeviceObject
)
1458 PDEV_EXTENSION DeviceExtension
;
1460 DPRINT1("KsGetBusEnumParentFDOFromChildPDO\n");
1462 /* get device extension */
1463 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1465 /* check if this is child pdo */
1466 if (DeviceExtension
->Ext
->IsBus
== FALSE
)
1468 /* return bus device object */
1469 *FunctionalDeviceObject
= DeviceExtension
->Ext
->BusDeviceExtension
->BusDeviceObject
;
1472 return STATUS_SUCCESS
;
1475 /* invalid parameter */
1476 return STATUS_INVALID_PARAMETER
;
1486 KsCreateBusEnumObject(
1487 IN PWCHAR BusIdentifier
,
1488 IN PDEVICE_OBJECT BusDeviceObject
,
1489 IN PDEVICE_OBJECT PhysicalDeviceObject
,
1490 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL
,
1491 IN REFGUID InterfaceGuid OPTIONAL
,
1492 IN PWCHAR ServiceRelativePath OPTIONAL
)
1495 NTSTATUS Status
= STATUS_SUCCESS
;
1496 UNICODE_STRING ServiceKeyPath
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
1497 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1498 PDEV_EXTENSION DeviceExtension
;
1500 DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath
, BusDeviceObject
);
1502 /* calculate sizeof bus enum device extension */
1503 Length
= wcslen(BusIdentifier
) * sizeof(WCHAR
);
1504 Length
+= sizeof(BUS_ENUM_DEVICE_EXTENSION
);
1506 BusDeviceExtension
= AllocateItem(NonPagedPool
, Length
);
1507 if (!BusDeviceExtension
)
1509 /* not enough memory */
1511 return STATUS_INSUFFICIENT_RESOURCES
;
1514 /* get device extension */
1515 DeviceExtension
= (PDEV_EXTENSION
)BusDeviceObject
->DeviceExtension
;
1517 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1519 /* store bus device extension */
1520 DeviceExtension
->Ext
= (PCOMMON_DEVICE_EXTENSION
)BusDeviceExtension
;
1522 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1525 /* zero device extension */
1526 RtlZeroMemory(BusDeviceExtension
, sizeof(BUS_ENUM_DEVICE_EXTENSION
));
1528 /* initialize bus device extension */
1529 wcscpy(BusDeviceExtension
->BusIdentifier
, BusIdentifier
);
1531 /* allocate service path string */
1532 Length
= ServiceKeyPath
.MaximumLength
;
1533 Length
+= BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
.MaximumLength
;
1535 if (ServiceRelativePath
)
1537 /* relative path for devices */
1538 Length
+= (wcslen(ServiceRelativePath
) + 2) * sizeof(WCHAR
);
1541 BusDeviceExtension
->ServicePath
.Length
= 0;
1542 BusDeviceExtension
->ServicePath
.MaximumLength
= (USHORT
)Length
;
1543 BusDeviceExtension
->ServicePath
.Buffer
= AllocateItem(NonPagedPool
, Length
);
1545 if (!BusDeviceExtension
->ServicePath
.Buffer
)
1547 /* not enough memory */
1548 FreeItem(BusDeviceExtension
);
1550 return STATUS_INSUFFICIENT_RESOURCES
;
1553 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &ServiceKeyPath
);
1554 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
);
1556 if (ServiceRelativePath
)
1558 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, L
"\\");
1559 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, ServiceRelativePath
);
1564 /* register an device interface */
1565 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
, InterfaceGuid
, NULL
, &BusDeviceExtension
->DeviceInterfaceLink
);
1567 /* check for success */
1568 if (!NT_SUCCESS(Status
))
1571 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1572 FreeItem(BusDeviceExtension
);
1576 /* now enable device interface */
1577 Status
= IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, TRUE
);
1579 if (!NT_SUCCESS(Status
))
1581 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1582 FreeItem(BusDeviceExtension
);
1587 /* initialize common device extension */
1588 BusDeviceExtension
->Common
.BusDeviceExtension
= NULL
;
1589 BusDeviceExtension
->Common
.DeviceObjectReferenceCount
= 1;
1590 BusDeviceExtension
->Common
.DeviceReferenceCount
= 1;
1591 BusDeviceExtension
->Common
.IsBus
= TRUE
;
1592 InitializeListHead(&BusDeviceExtension
->Common
.Entry
);
1594 /* store device objects */
1595 BusDeviceExtension
->BusDeviceObject
= BusDeviceObject
;
1596 BusDeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
1598 /* initialize lock */
1599 KeInitializeSpinLock(&BusDeviceExtension
->Lock
);
1601 /* initialize timer */
1602 KeInitializeTimer(&BusDeviceExtension
->Timer
);
1604 /* initialize dpc */
1605 KeInitializeDpc(&BusDeviceExtension
->Dpc
, KspBusDpcRoutine
, (PVOID
)BusDeviceExtension
);
1607 /* initialize event */
1608 KeInitializeEvent(&BusDeviceExtension
->Event
, SynchronizationEvent
, FALSE
);
1610 /* initialize work item */
1611 ExInitializeWorkItem(&BusDeviceExtension
->WorkItem
, KspBusWorkerRoutine
, (PVOID
)BusDeviceExtension
);
1613 if (!PnpDeviceObject
)
1616 BusDeviceExtension
->PnpDeviceObject
= IoAttachDeviceToDeviceStack(BusDeviceObject
, PhysicalDeviceObject
);
1618 if (!BusDeviceExtension
->PnpDeviceObject
)
1620 /* failed to attach device */
1621 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1623 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1624 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1627 /* free device extension */
1628 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1629 FreeItem(BusDeviceExtension
);
1631 return STATUS_DEVICE_REMOVED
;
1634 /* mark device as attached */
1635 BusDeviceExtension
->DeviceAttached
= TRUE
;
1639 /* directly attach */
1640 BusDeviceExtension
->PnpDeviceObject
= PnpDeviceObject
;
1643 /* now scan the bus */
1644 Status
= KspScanBus(BusDeviceExtension
);
1646 /* check for success */
1647 if (!NT_SUCCESS(Status
))
1649 /* failed to scan bus */
1650 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1652 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1653 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1656 if (BusDeviceExtension
->DeviceAttached
)
1659 IoDetachDevice(BusDeviceExtension
->PnpDeviceObject
);
1662 /* free device extension */
1663 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1664 FreeItem(BusDeviceExtension
);
1667 DPRINT("KsCreateBusEnumObject Status %x\n", Status
);
1678 KsGetBusEnumPnpDeviceObject(
1679 IN PDEVICE_OBJECT DeviceObject
,
1680 IN PDEVICE_OBJECT
*PnpDeviceObject
)
1682 PDEV_EXTENSION DeviceExtension
;
1683 PCOMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1684 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1686 DPRINT("KsGetBusEnumPnpDeviceObject\n");
1688 if (!DeviceObject
->DeviceExtension
)
1690 /* invalid parameter */
1691 return STATUS_INVALID_PARAMETER
;
1694 /* get device extension */
1695 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1697 /* get common device extension */
1698 CommonDeviceExtension
= DeviceExtension
->Ext
;
1700 if (!CommonDeviceExtension
)
1702 /* invalid parameter */
1703 return STATUS_INVALID_PARAMETER
;
1706 if (!CommonDeviceExtension
->IsBus
)
1708 /* getting pnp device object is only supported for software bus device object */
1709 return STATUS_INVALID_PARAMETER
;
1713 ASSERT(CommonDeviceExtension
);
1714 ASSERT(CommonDeviceExtension
->IsBus
);
1716 /* cast to bus device extension */
1717 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)CommonDeviceExtension
;
1720 *PnpDeviceObject
= BusDeviceExtension
->PnpDeviceObject
;
1723 return STATUS_SUCCESS
;
1732 KsInstallBusEnumInterface(
1735 BUS_INSTALL_ENUM_CONTEXT Context
;
1736 KPROCESSOR_MODE Mode
;
1738 PIO_STACK_LOCATION IoStack
;
1739 PDEV_EXTENSION DeviceExtension
;
1740 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1742 DPRINT1("KsInstallBusEnumInterface\n");
1744 /* get current irp stack location */
1745 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1747 /* get previous mode */
1748 Mode
= ExGetPreviousMode();
1750 /* convert to luid */
1751 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
1753 /* perform access check */
1754 if (!SeSinglePrivilegeCheck(luid
, Mode
))
1756 /* insufficient privileges */
1757 return STATUS_PRIVILEGE_NOT_HELD
;
1760 /* get device extension */
1761 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1763 /* get bus device extension */
1764 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1767 /* initialize context */
1769 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
1770 Context
.BusDeviceExtension
= BusDeviceExtension
;
1771 ExInitializeWorkItem(&Context
.WorkItem
, KspInstallBusEnumInterface
, (PVOID
)&Context
);
1773 /* queue the work item */
1774 ExQueueWorkItem(&Context
.WorkItem
, DelayedWorkQueue
);
1775 /* wait for completion */
1776 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
1779 Irp
->IoStatus
.Status
= Context
.Status
;
1782 return Context
.Status
;
1791 KsIsBusEnumChildDevice(
1792 IN PDEVICE_OBJECT DeviceObject
,
1793 OUT PBOOLEAN ChildDevice
)
1795 PDEV_EXTENSION DeviceExtension
;
1796 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1798 DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject
);
1800 /* get device extension */
1801 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1803 /* get bus device extension */
1804 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1806 if (!BusDeviceExtension
)
1808 /* not a bus device */
1809 return STATUS_INVALID_PARAMETER
;
1813 *ChildDevice
= (BusDeviceExtension
->Common
.IsBus
== FALSE
);
1815 return STATUS_SUCCESS
;
1824 KsServiceBusEnumCreateRequest(
1825 IN PDEVICE_OBJECT DeviceObject
,
1829 PBUS_DEVICE_ENTRY DeviceEntry
= NULL
; /* fix gcc */
1830 PIO_STACK_LOCATION IoStack
;
1831 BOOLEAN ItemExists
= FALSE
;
1832 PDEV_EXTENSION DeviceExtension
;
1833 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1834 //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension;
1840 /* get device extension */
1841 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1843 /* get bus device extension */
1844 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1846 /* get current irp stack location */
1847 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1850 ASSERT(IoStack
->FileObject
);
1851 ASSERT(IoStack
->FileObject
->FileName
.Buffer
);
1853 DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1855 /* scan list and check if it is already present */
1856 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1858 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1860 /* get real offset */
1861 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1863 /* check if name matches */
1864 if (!wcsicmp(DeviceEntry
->DeviceName
, IoStack
->FileObject
->FileName
.Buffer
+ 1))
1866 /* item already exists */
1871 /* move to next entry */
1872 Entry
= Entry
->Flink
;
1877 /* interface not registered */
1878 DPRINT1("Interface %wZ not registered\n", &IoStack
->FileObject
->FileName
);
1879 return STATUS_OBJECT_NAME_NOT_FOUND
;
1882 /* is there a pdo yet */
1883 if (DeviceEntry
->PDO
)
1885 if (DeviceEntry
->DeviceState
== Started
)
1888 Status
= KspDoReparseForIrp(Irp
, DeviceEntry
);
1889 DPRINT("REPARSE Irp %p '%wZ'\n", Irp
, &IoStack
->FileObject
->FileName
);
1891 Irp
->IoStatus
.Status
= Status
;
1895 /* delay processing until pnp is finished with enumeration */
1896 IoMarkIrpPending(Irp
);
1898 /* insert into irp pending list */
1899 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1901 Time
.QuadPart
= Int32x32To64(1500, -10000);
1902 DbgPrint("PENDING Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1904 /* query current time */
1905 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
1908 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1911 return STATUS_PENDING
;
1916 /* time to create PDO */
1917 Status
= KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1919 if (!NT_SUCCESS(Status
))
1921 /* failed to create PDO */
1922 DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status
);
1925 DPRINT1("PENDING CREATE Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1927 /* delay processing until pnp is finished with enumeration */
1928 IoMarkIrpPending(Irp
);
1930 /* insert into irp pending list */
1931 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1933 /* get current time */
1934 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
1936 /* invalidate device relations */
1937 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1940 return STATUS_PENDING
;
1950 KsServiceBusEnumPnpRequest(
1951 IN PDEVICE_OBJECT DeviceObject
,
1954 PDEV_EXTENSION DeviceExtension
;
1955 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1956 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
;
1957 PIO_STACK_LOCATION IoStack
;
1960 PDEVICE_RELATIONS DeviceRelation
;
1961 PBUS_DEVICE_ENTRY DeviceEntry
;
1963 /* get device extension */
1964 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1966 /* get bus device extension */
1967 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1969 /* get current irp stack location */
1970 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1972 if (BusDeviceExtension
->Common
.IsBus
)
1974 if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
1976 /* no op for bus driver */
1977 Status
= STATUS_SUCCESS
;
1979 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
)
1981 /* handle bus device relations */
1982 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== BusRelations
);
1984 Status
= KspQueryBusRelations(BusDeviceExtension
, Irp
);
1988 /* get default status */
1989 Status
= Irp
->IoStatus
.Status
;
1994 /* get child device extension */
1995 ChildDeviceExtension
= DeviceExtension
->Ext
;
1997 /* get bus device extension */
1998 BusDeviceExtension
= ChildDeviceExtension
->BusDeviceExtension
;
2000 if (IoStack
->MinorFunction
== IRP_MN_QUERY_ID
)
2003 Status
= KspQueryId(ChildDeviceExtension
, Irp
);
2005 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
2007 ASSERT(ChildDeviceExtension
->DeviceEntry
->DeviceState
!= Started
|| ChildDeviceExtension
->DeviceEntry
->DeviceState
== NotStarted
);
2008 ASSERT(ChildDeviceExtension
->DeviceEntry
->PDO
== DeviceObject
);
2010 /* backup device entry */
2011 DeviceEntry
= ChildDeviceExtension
->DeviceEntry
;
2013 /* free device extension */
2014 FreeItem(ChildDeviceExtension
);
2016 /* clear PDO reference */
2017 DeviceEntry
->PDO
= NULL
;
2019 /* delete the device */
2020 IoDeleteDevice(DeviceObject
);
2022 if (DeviceEntry
->PDODeviceName
)
2024 /* delete pdo device name */
2025 FreeItem(DeviceEntry
->PDODeviceName
);
2028 DeviceEntry
->PDODeviceName
= NULL
;
2031 /* set state no notstarted */
2032 DeviceEntry
->DeviceState
= NotStarted
;
2034 /* time to create PDO */
2035 KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
2037 /* invalidate device relations */
2038 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
2041 Status
= STATUS_SUCCESS
;
2043 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_BUS_INFORMATION
)
2045 /* query bus information */
2046 Status
= KspQueryBusInformation(ChildDeviceExtension
, Irp
);
2048 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCES
)
2051 Status
= STATUS_SUCCESS
;
2053 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCE_REQUIREMENTS
)
2056 Status
= STATUS_SUCCESS
;
2058 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
2061 Status
= KspStartBusDevice(DeviceObject
, ChildDeviceExtension
, Irp
);
2064 Time
.QuadPart
= Int32x32To64(1500, -10000);
2067 ASSERT(BusDeviceExtension
);
2070 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
2072 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_CAPABILITIES
)
2074 /* query capabilities */
2075 Status
= KspQueryBusDeviceCapabilities(ChildDeviceExtension
, Irp
);
2077 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
2079 /* query pnp state */
2080 Status
= KspQueryBusDevicePnpState(ChildDeviceExtension
, Irp
);
2082 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_INTERFACE
)
2084 /* query interface */
2085 Status
= KspQueryBusDeviceInterface(ChildDeviceExtension
, Irp
);
2087 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
&& IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
2089 /* handle target device relations */
2090 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
);
2091 ASSERT(Irp
->IoStatus
.Information
== 0);
2093 /* allocate device relation */
2094 DeviceRelation
= AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
));
2097 DeviceRelation
->Count
= 1;
2098 DeviceRelation
->Objects
[0] = DeviceObject
;
2100 /* reference self */
2101 ObReferenceObject(DeviceObject
);
2104 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelation
;
2107 Status
= STATUS_SUCCESS
;
2112 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2117 /* get default status */
2118 Status
= Irp
->IoStatus
.Status
;
2122 DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject
, BusDeviceExtension
->Common
.IsBus
, IoStack
->MinorFunction
, Status
);
2123 Irp
->IoStatus
.Status
= Status
;
2133 KsRemoveBusEnumInterface(
2136 KPROCESSOR_MODE Mode
;
2138 BUS_INSTALL_ENUM_CONTEXT Ctx
;
2139 PDEV_EXTENSION DeviceExtension
;
2140 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
2141 PIO_STACK_LOCATION IoStack
;
2143 DPRINT1("KsRemoveBusEnumInterface\n");
2145 /* get io stack location */
2146 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2148 /* get device extension */
2149 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
2151 /* get bus device extension */
2152 BusDeviceExtension
= DeviceExtension
->Ext
->BusDeviceExtension
;
2154 /* get previous mode */
2155 Mode
= ExGetPreviousMode();
2157 /* convert to luid */
2158 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
2160 /* perform access check */
2161 if (!SeSinglePrivilegeCheck(luid
, Mode
))
2163 /* insufficient privileges */
2164 return STATUS_PRIVILEGE_NOT_HELD
;
2167 /* initialize context */
2168 KeInitializeEvent(&Ctx
.Event
, NotificationEvent
, FALSE
);
2170 Ctx
.BusDeviceExtension
= BusDeviceExtension
;
2171 ExInitializeWorkItem(&Ctx
.WorkItem
, KspRemoveBusInterface
, (PVOID
)&Ctx
);
2173 /* now queue the work item */
2174 ExQueueWorkItem(&Ctx
.WorkItem
, DelayedWorkQueue
);
2176 /* wait for completion */
2177 KeWaitForSingleObject(&Ctx
.Event
, Executive
, KernelMode
, FALSE
, NULL
);