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
,
760 PBUS_DEVICE_ENTRY DeviceEntry
;
762 /* FIXME handle pending remove */
764 /* get full device name */
765 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyPhysicalDeviceObjectName
, sizeof(PDOName
), (PVOID
)PDOName
, &ResultLength
);
767 if (!NT_SUCCESS(Status
))
769 /* failed to get device name */
773 /* allocate device name buffer */
774 Name
= AllocateItem(NonPagedPool
, (ResultLength
+ 1) * sizeof(WCHAR
));
778 return STATUS_INSUFFICIENT_RESOURCES
;
782 wcscpy(Name
, PDOName
);
784 /* TODO: time stamp creation time */
786 /* get device entry */
787 DeviceEntry
= (PBUS_DEVICE_ENTRY
)ChildDeviceExtension
->DeviceEntry
;
792 /* store device name */
793 DeviceEntry
->PDODeviceName
= Name
;
795 /* mark device as started */
796 DeviceEntry
->DeviceState
= Started
;
798 /* reference start time */
799 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
801 DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name
, DeviceEntry
->DeviceName
, DeviceEntry
->Instance
);
803 /* enable device classes */
804 //KspEnableBusDeviceInterface(DeviceEntry, TRUE);
807 return STATUS_SUCCESS
;
811 KspQueryBusDeviceCapabilities(
812 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
815 PDEVICE_CAPABILITIES Capabilities
;
816 PIO_STACK_LOCATION IoStack
;
818 /* get stack location */
819 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
821 /* get capabilities */
822 Capabilities
= IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
824 RtlZeroMemory(Capabilities
, sizeof(DEVICE_CAPABILITIES
));
826 /* setup capabilities */
827 Capabilities
->UniqueID
= TRUE
;
828 Capabilities
->SilentInstall
= TRUE
;
829 Capabilities
->SurpriseRemovalOK
= TRUE
;
830 Capabilities
->Address
= 0;
831 Capabilities
->UINumber
= 0;
832 Capabilities
->SystemWake
= PowerSystemWorking
; /* FIXME common device extension */
833 Capabilities
->DeviceWake
= PowerDeviceD0
;
836 return STATUS_SUCCESS
;
840 KspQueryBusInformation(
841 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
844 PPNP_BUS_INFORMATION BusInformation
;
846 /* allocate bus information */
847 BusInformation
= (PPNP_BUS_INFORMATION
)AllocateItem(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
852 return STATUS_INSUFFICIENT_RESOURCES
;
856 BusInformation
->BusNumber
= 0;
857 BusInformation
->LegacyBusType
= InterfaceTypeUndefined
;
858 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &KSMEDIUMSETID_Standard
, sizeof(GUID
));
861 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
864 return STATUS_SUCCESS
;
868 KspQueryBusDevicePnpState(
869 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
872 /* set device flags */
873 Irp
->IoStatus
.Information
= PNP_DEVICE_DONT_DISPLAY_IN_UI
| PNP_DEVICE_NOT_DISABLEABLE
;
876 return STATUS_SUCCESS
;
881 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
884 PIO_STACK_LOCATION IoStack
;
885 PBUS_DEVICE_ENTRY DeviceEntry
;
886 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
890 /* get current irp stack location */
891 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
893 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryInstanceID
)
895 /* get device entry */
896 DeviceEntry
= (PBUS_DEVICE_ENTRY
) ChildDeviceExtension
->DeviceEntry
;
900 ASSERT(DeviceEntry
->Instance
);
902 /* calculate length */
903 Length
= wcslen(DeviceEntry
->Instance
) + 1;
905 /* allocate buffer */
906 Name
= AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
910 /* failed to allocate buffer */
911 return STATUS_INSUFFICIENT_RESOURCES
;
915 wcscpy(Name
, DeviceEntry
->Instance
);
918 Irp
->IoStatus
.Information
= (ULONG_PTR
)Name
;
921 return STATUS_SUCCESS
;
923 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
||
924 IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
926 /* get device entry */
927 DeviceEntry
= (PBUS_DEVICE_ENTRY
) ChildDeviceExtension
->DeviceEntry
;
929 /* get bus device extension */
930 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
) ChildDeviceExtension
->BusDeviceExtension
;
934 ASSERT(DeviceEntry
->BusId
);
935 ASSERT(BusDeviceExtension
);
936 ASSERT(BusDeviceExtension
->BusIdentifier
);
938 /* calculate length */
939 Length
= wcslen(BusDeviceExtension
->BusIdentifier
);
940 Length
+= wcslen(DeviceEntry
->BusId
);
942 /* extra length for '\\' and zero byte */
945 /* allocate buffer */
946 Name
= ExAllocatePool(PagedPool
, Length
* sizeof(WCHAR
));
949 /* failed to allocate buffer */
950 return STATUS_INSUFFICIENT_RESOURCES
;
954 swprintf(Name
, L
"%s\\%s", BusDeviceExtension
->BusIdentifier
, DeviceEntry
->BusId
);
957 Irp
->IoStatus
.Information
= (ULONG_PTR
)Name
;
960 return STATUS_SUCCESS
;
964 /* other ids are not supported */
965 //DPRINT1("Not Supported ID Type %x\n", IoStack->Parameters.QueryId.IdType);
966 return Irp
->IoStatus
.Status
;
972 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
973 IN PSWENUM_INSTALL_INTERFACE InstallInterface
)
976 UNICODE_STRING DeviceString
, InterfaceString
, ReferenceString
;
977 HANDLE hKey
, hDeviceKey
, hInterfaceKey
, hReferenceKey
;
979 OBJECT_ATTRIBUTES ObjectAttributes
;
982 ASSERT(InstallInterface
);
984 /* calculate length */
985 Length
= wcslen(InstallInterface
->ReferenceString
);
987 /* check for invalid characters */
988 for(Index
= 0; Index
< Length
; Index
++)
990 if (InstallInterface
->ReferenceString
[Index
] <= L
' ' ||
991 InstallInterface
->ReferenceString
[Index
] > L
'~' ||
992 InstallInterface
->ReferenceString
[Index
] == L
',' ||
993 InstallInterface
->ReferenceString
[Index
] == L
'\\' ||
994 InstallInterface
->ReferenceString
[Index
] == L
'/')
996 /* invalid character */
997 return STATUS_INVALID_PARAMETER
;
1002 Status
= KspOpenBusRegistryKey(BusDeviceExtension
, &hKey
);
1003 if (NT_SUCCESS(Status
))
1005 /* convert device guid to string */
1006 Status
= RtlStringFromGUID(&InstallInterface
->DeviceId
, &DeviceString
);
1007 if (NT_SUCCESS(Status
))
1009 /* initialize object attributes */
1010 InitializeObjectAttributes(&ObjectAttributes
, &DeviceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hKey
, NULL
);
1012 /* construct device key */
1013 Status
= ZwCreateKey(&hDeviceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1014 if (NT_SUCCESS(Status
))
1016 /* initialize reference string */
1017 RtlInitUnicodeString(&ReferenceString
, InstallInterface
->ReferenceString
);
1019 /* initialize object attributes */
1020 InitializeObjectAttributes(&ObjectAttributes
, &ReferenceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceKey
, NULL
);
1022 /* construct device key */
1023 Status
= ZwCreateKey(&hReferenceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1024 if (NT_SUCCESS(Status
))
1026 /* convert interface guid to string */
1027 Status
= RtlStringFromGUID(&InstallInterface
->InterfaceId
, &InterfaceString
);
1028 if (NT_SUCCESS(Status
))
1030 /* initialize object attributes */
1031 InitializeObjectAttributes(&ObjectAttributes
, &InterfaceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hReferenceKey
, NULL
);
1033 /* construct device key */
1034 Status
= ZwCreateKey(&hInterfaceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1035 if (NT_SUCCESS(Status
))
1038 ZwClose(hInterfaceKey
);
1040 /* free interface string */
1041 RtlFreeUnicodeString(&InterfaceString
);
1043 /* close reference key */
1044 ZwClose(hReferenceKey
);
1046 /* close device key */
1047 ZwClose(hDeviceKey
);
1049 /* free device string */
1050 RtlFreeUnicodeString(&DeviceString
);
1062 KspInstallBusEnumInterface(
1065 PIO_STACK_LOCATION IoStack
;
1068 PBUS_DEVICE_ENTRY DeviceEntry
;
1069 PSWENUM_INSTALL_INTERFACE InstallInterface
;
1071 PBUS_INSTALL_ENUM_CONTEXT Context
= (PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1073 /* get current irp stack location */
1074 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
1076 /* get install request */
1077 InstallInterface
= (PSWENUM_INSTALL_INTERFACE
)Context
->Irp
->AssociatedIrp
.SystemBuffer
;
1080 ASSERT(InstallInterface
);
1081 ASSERT(Context
->BusDeviceExtension
);
1083 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(SWENUM_INSTALL_INTERFACE
))
1085 /* buffer too small */
1086 Context
->Status
= STATUS_INVALID_PARAMETER
;
1088 /* signal completion */
1089 KeSetEvent(&Context
->Event
, 0, FALSE
);
1097 /* now install the interface */
1098 Status
= KspInstallInterface(Context
->BusDeviceExtension
, InstallInterface
);
1099 if (!NT_SUCCESS(Status
))
1101 /* failed to install interface */
1102 Context
->Status
= Status
;
1104 /* signal completion */
1105 KeSetEvent(&Context
->Event
, 0, FALSE
);
1111 /* acquire device entry lock */
1112 KeAcquireSpinLock(&Context
->BusDeviceExtension
->Lock
, &OldLevel
);
1114 /* now iterate all device entries */
1115 Entry
= Context
->BusDeviceExtension
->Common
.Entry
.Flink
;
1116 while(Entry
!= &Context
->BusDeviceExtension
->Common
.Entry
)
1118 /* get device entry */
1119 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1121 if (IsEqualGUIDAligned(&DeviceEntry
->DeviceGuid
, &InstallInterface
->DeviceId
) &&
1122 !wcsicmp(DeviceEntry
->Instance
, InstallInterface
->ReferenceString
))
1124 if (!DeviceEntry
->PDO
)
1127 Status
= KspCreatePDO(Context
->BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1134 /* move to next entry */
1135 Entry
= Entry
->Flink
;
1138 /* release device entry lock */
1139 KeReleaseSpinLock(&Context
->BusDeviceExtension
->Lock
, OldLevel
);
1141 /* signal that bus driver relations has changed */
1142 IoInvalidateDeviceRelations(Context
->BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1145 Context
->Status
= Status
;
1147 /* signal completion */
1148 KeSetEvent(&Context
->Event
, 0, FALSE
);
1154 KspBusWorkerRoutine(
1157 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1158 PBUS_DEVICE_ENTRY DeviceEntry
;
1160 LARGE_INTEGER Time
, Diff
;
1161 BOOLEAN DoInvalidate
= FALSE
;
1164 /* get device extension */
1165 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)Parameter
;
1168 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1170 /* get current time */
1171 KeQuerySystemTime(&Time
);
1173 /* enumerate all device entries */
1174 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1175 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1177 /* get offset to device entry */
1178 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1181 ASSERT(DeviceEntry
);
1183 //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState);
1185 if (DeviceEntry
->PDO
)
1187 if (DeviceEntry
->DeviceState
== NotStarted
)
1189 Diff
.QuadPart
= Time
.QuadPart
- DeviceEntry
->TimeCreated
.QuadPart
;
1191 if (Diff
.QuadPart
> Int32x32To64(15000, 10000))
1193 DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry
->DeviceName
, DeviceEntry
->Instance
, DeviceEntry
->TimeCreated
.QuadPart
, Time
.QuadPart
, Diff
.QuadPart
);
1195 /* release spin lock */
1196 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1198 /* deactivate interfaces */
1199 //KspEnableBusDeviceInterface(DeviceEntry, FALSE);
1201 /* re-acquire lock */
1202 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1204 /* pending remove device object */
1205 DeviceEntry
->DeviceState
= StopPending
;
1207 /* perform invalidation */
1208 DoInvalidate
= TRUE
;
1211 else if (DeviceEntry
->DeviceState
== Started
)
1213 /* found pending irps */
1214 KspCompletePendingIrps(DeviceEntry
, STATUS_REPARSE
);
1220 Entry
= Entry
->Flink
;
1224 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1228 /* invalidate device relations */
1229 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1232 Time
.QuadPart
= Int32x32To64(5000, -10000);
1233 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1240 IN PVOID DeferredContext OPTIONAL
,
1241 IN PVOID SystemArgument1 OPTIONAL
,
1242 IN PVOID SystemArgument2 OPTIONAL
)
1244 /* get device extension */
1245 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeferredContext
;
1247 /* queue the item */
1248 ExQueueWorkItem(&BusDeviceExtension
->WorkItem
, DelayedWorkQueue
);
1253 KspRemoveBusInterface(
1256 PBUS_INSTALL_ENUM_CONTEXT Context
=(PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1259 * get SWENUM_INSTALL_INTERFACE struct
1260 * open device key and delete the keys
1266 Context
->Status
= STATUS_NOT_IMPLEMENTED
;
1269 /* signal completion */
1270 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
1274 KspQueryBusRelations(
1275 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
1278 PDEVICE_RELATIONS DeviceRelations
;
1280 PBUS_DEVICE_ENTRY DeviceEntry
;
1281 ULONG Count
= 0, Length
;
1285 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1287 /* first scan all device entries */
1288 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1290 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1292 /* get offset to device entry */
1293 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1295 /* is there a pdo yet */
1296 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1298 /* increment count */
1302 /* move to next entry */
1303 Entry
= Entry
->Flink
;
1306 /* calculate length */
1307 Length
= sizeof(DEVICE_RELATIONS
) + (Count
> 1 ? sizeof(PDEVICE_OBJECT
) * (Count
-1) : 0);
1309 /* allocate device relations */
1310 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(NonPagedPool
, Length
);
1312 if (!DeviceRelations
)
1314 /* not enough memory */
1315 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1316 return STATUS_INSUFFICIENT_RESOURCES
;
1319 /* rescan device entries */
1320 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1322 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1324 /* get offset to device entry */
1325 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1327 /* is there a pdo yet */
1328 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1331 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceEntry
->PDO
;
1333 /* reference device object */
1334 ObReferenceObject(DeviceEntry
->PDO
);
1336 /* increment pdo count */
1337 DeviceRelations
->Count
++;
1340 /* move to next entry */
1341 Entry
= Entry
->Flink
;
1345 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1347 /* FIXME handle existing device relations */
1348 ASSERT(Irp
->IoStatus
.Information
== 0);
1350 /* store device relations */
1351 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
1354 return STATUS_SUCCESS
;
1357 //------------------------------------------------------------------------------------
1366 KsGetBusEnumIdentifier(
1369 PDEV_EXTENSION DeviceExtension
;
1370 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1371 PIO_STACK_LOCATION IoStack
;
1376 DPRINT1("KsGetBusEnumIdentifier\n");
1378 /* get stack location */
1379 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1382 ASSERT(IoStack
->DeviceObject
);
1383 ASSERT(IoStack
->DeviceObject
->DeviceExtension
);
1385 /* get device extension */
1386 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1388 /* get bus device extension */
1389 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1392 ASSERT(BusDeviceExtension
);
1393 ASSERT(BusDeviceExtension
->Common
.IsBus
);
1395 if (!BusDeviceExtension
)
1397 /* invalid parameter */
1398 return STATUS_INVALID_PARAMETER
;
1402 Length
= (wcslen(BusDeviceExtension
->BusIdentifier
)+1) * sizeof(WCHAR
);
1404 /* is there an output buffer provided */
1405 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1407 if (Length
> IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1409 /* buffer is too small */
1410 return STATUS_BUFFER_TOO_SMALL
;
1413 /* now allocate buffer */
1414 Buffer
= AllocateItem(NonPagedPool
, Length
);
1418 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1422 /* copy bus identifier */
1423 wcscpy(Buffer
, BusDeviceExtension
->BusIdentifier
);
1426 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
1428 /* set flag that buffer gets copied back */
1429 Irp
->Flags
|= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
1432 Status
= STATUS_SUCCESS
;
1437 /* no buffer provided */
1438 Status
= STATUS_BUFFER_OVERFLOW
;
1442 Irp
->IoStatus
.Status
= Status
;
1452 KsGetBusEnumParentFDOFromChildPDO(
1453 IN PDEVICE_OBJECT DeviceObject
,
1454 OUT PDEVICE_OBJECT
*FunctionalDeviceObject
)
1456 PDEV_EXTENSION DeviceExtension
;
1458 DPRINT1("KsGetBusEnumParentFDOFromChildPDO\n");
1460 /* get device extension */
1461 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1463 /* check if this is child pdo */
1464 if (DeviceExtension
->Ext
->IsBus
== FALSE
)
1466 /* return bus device object */
1467 *FunctionalDeviceObject
= DeviceExtension
->Ext
->BusDeviceExtension
->BusDeviceObject
;
1470 return STATUS_SUCCESS
;
1473 /* invalid parameter */
1474 return STATUS_INVALID_PARAMETER
;
1484 KsCreateBusEnumObject(
1485 IN PWCHAR BusIdentifier
,
1486 IN PDEVICE_OBJECT BusDeviceObject
,
1487 IN PDEVICE_OBJECT PhysicalDeviceObject
,
1488 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL
,
1489 IN REFGUID InterfaceGuid OPTIONAL
,
1490 IN PWCHAR ServiceRelativePath OPTIONAL
)
1493 NTSTATUS Status
= STATUS_SUCCESS
;
1494 UNICODE_STRING ServiceKeyPath
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
1495 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1496 PDEV_EXTENSION DeviceExtension
;
1498 DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath
, BusDeviceObject
);
1500 /* calculate sizeof bus enum device extension */
1501 Length
= wcslen(BusIdentifier
) * sizeof(WCHAR
);
1502 Length
+= sizeof(BUS_ENUM_DEVICE_EXTENSION
);
1504 BusDeviceExtension
= AllocateItem(NonPagedPool
, Length
);
1505 if (!BusDeviceExtension
)
1507 /* not enough memory */
1509 return STATUS_INSUFFICIENT_RESOURCES
;
1512 /* get device extension */
1513 DeviceExtension
= (PDEV_EXTENSION
)BusDeviceObject
->DeviceExtension
;
1515 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1517 /* store bus device extension */
1518 DeviceExtension
->Ext
= (PCOMMON_DEVICE_EXTENSION
)BusDeviceExtension
;
1520 DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1523 /* zero device extension */
1524 RtlZeroMemory(BusDeviceExtension
, sizeof(BUS_ENUM_DEVICE_EXTENSION
));
1526 /* initialize bus device extension */
1527 wcscpy(BusDeviceExtension
->BusIdentifier
, BusIdentifier
);
1529 /* allocate service path string */
1530 Length
= ServiceKeyPath
.MaximumLength
;
1531 Length
+= BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
.MaximumLength
;
1533 if (ServiceRelativePath
)
1535 /* relative path for devices */
1536 Length
+= (wcslen(ServiceRelativePath
) + 2) * sizeof(WCHAR
);
1539 BusDeviceExtension
->ServicePath
.Length
= 0;
1540 BusDeviceExtension
->ServicePath
.MaximumLength
= (USHORT
)Length
;
1541 BusDeviceExtension
->ServicePath
.Buffer
= AllocateItem(NonPagedPool
, Length
);
1543 if (!BusDeviceExtension
->ServicePath
.Buffer
)
1545 /* not enough memory */
1546 FreeItem(BusDeviceExtension
);
1548 return STATUS_INSUFFICIENT_RESOURCES
;
1551 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &ServiceKeyPath
);
1552 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
);
1554 if (ServiceRelativePath
)
1556 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, L
"\\");
1557 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, ServiceRelativePath
);
1562 /* register an device interface */
1563 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
, InterfaceGuid
, NULL
, &BusDeviceExtension
->DeviceInterfaceLink
);
1565 /* check for success */
1566 if (!NT_SUCCESS(Status
))
1569 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1570 FreeItem(BusDeviceExtension
);
1574 /* now enable device interface */
1575 Status
= IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, TRUE
);
1577 if (!NT_SUCCESS(Status
))
1579 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1580 FreeItem(BusDeviceExtension
);
1585 /* initialize common device extension */
1586 BusDeviceExtension
->Common
.BusDeviceExtension
= NULL
;
1587 BusDeviceExtension
->Common
.DeviceObjectReferenceCount
= 1;
1588 BusDeviceExtension
->Common
.DeviceReferenceCount
= 1;
1589 BusDeviceExtension
->Common
.IsBus
= TRUE
;
1590 InitializeListHead(&BusDeviceExtension
->Common
.Entry
);
1592 /* store device objects */
1593 BusDeviceExtension
->BusDeviceObject
= BusDeviceObject
;
1594 BusDeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
1596 /* initialize lock */
1597 KeInitializeSpinLock(&BusDeviceExtension
->Lock
);
1599 /* initialize timer */
1600 KeInitializeTimer(&BusDeviceExtension
->Timer
);
1602 /* initialize dpc */
1603 KeInitializeDpc(&BusDeviceExtension
->Dpc
, KspBusDpcRoutine
, (PVOID
)BusDeviceExtension
);
1605 /* initialize event */
1606 KeInitializeEvent(&BusDeviceExtension
->Event
, SynchronizationEvent
, FALSE
);
1608 /* initialize work item */
1609 ExInitializeWorkItem(&BusDeviceExtension
->WorkItem
, KspBusWorkerRoutine
, (PVOID
)BusDeviceExtension
);
1611 if (!PnpDeviceObject
)
1614 BusDeviceExtension
->PnpDeviceObject
= IoAttachDeviceToDeviceStack(BusDeviceObject
, PhysicalDeviceObject
);
1616 if (!BusDeviceExtension
->PnpDeviceObject
)
1618 /* failed to attach device */
1619 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1621 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1622 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1625 /* free device extension */
1626 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1627 FreeItem(BusDeviceExtension
);
1629 return STATUS_DEVICE_REMOVED
;
1632 /* mark device as attached */
1633 BusDeviceExtension
->DeviceAttached
= TRUE
;
1637 /* directly attach */
1638 BusDeviceExtension
->PnpDeviceObject
= PnpDeviceObject
;
1641 /* now scan the bus */
1642 Status
= KspScanBus(BusDeviceExtension
);
1644 /* check for success */
1645 if (!NT_SUCCESS(Status
))
1647 /* failed to scan bus */
1648 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1650 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1651 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1654 if (BusDeviceExtension
->DeviceAttached
)
1657 IoDetachDevice(BusDeviceExtension
->PnpDeviceObject
);
1660 /* free device extension */
1661 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1662 FreeItem(BusDeviceExtension
);
1665 DPRINT("KsCreateBusEnumObject Status %x\n", Status
);
1676 KsGetBusEnumPnpDeviceObject(
1677 IN PDEVICE_OBJECT DeviceObject
,
1678 IN PDEVICE_OBJECT
*PnpDeviceObject
)
1680 PDEV_EXTENSION DeviceExtension
;
1681 PCOMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1682 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1684 DPRINT("KsGetBusEnumPnpDeviceObject\n");
1686 if (!DeviceObject
->DeviceExtension
)
1688 /* invalid parameter */
1689 return STATUS_INVALID_PARAMETER
;
1692 /* get device extension */
1693 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1695 /* get common device extension */
1696 CommonDeviceExtension
= DeviceExtension
->Ext
;
1698 if (!CommonDeviceExtension
)
1700 /* invalid parameter */
1701 return STATUS_INVALID_PARAMETER
;
1704 if (!CommonDeviceExtension
->IsBus
)
1706 /* getting pnp device object is only supported for software bus device object */
1707 return STATUS_INVALID_PARAMETER
;
1711 ASSERT(CommonDeviceExtension
);
1712 ASSERT(CommonDeviceExtension
->IsBus
);
1714 /* cast to bus device extension */
1715 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)CommonDeviceExtension
;
1718 *PnpDeviceObject
= BusDeviceExtension
->PnpDeviceObject
;
1721 return STATUS_SUCCESS
;
1730 KsInstallBusEnumInterface(
1733 BUS_INSTALL_ENUM_CONTEXT Context
;
1734 KPROCESSOR_MODE Mode
;
1736 PIO_STACK_LOCATION IoStack
;
1737 PDEV_EXTENSION DeviceExtension
;
1738 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1740 DPRINT1("KsInstallBusEnumInterface\n");
1742 /* get current irp stack location */
1743 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1745 /* get previous mode */
1746 Mode
= ExGetPreviousMode();
1748 /* convert to luid */
1749 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
1751 /* perform access check */
1752 if (!SeSinglePrivilegeCheck(luid
, Mode
))
1754 /* insufficient privileges */
1755 return STATUS_PRIVILEGE_NOT_HELD
;
1758 /* get device extension */
1759 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1761 /* get bus device extension */
1762 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1765 /* initialize context */
1767 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
1768 Context
.BusDeviceExtension
= BusDeviceExtension
;
1769 ExInitializeWorkItem(&Context
.WorkItem
, KspInstallBusEnumInterface
, (PVOID
)&Context
);
1771 /* queue the work item */
1772 ExQueueWorkItem(&Context
.WorkItem
, DelayedWorkQueue
);
1773 /* wait for completion */
1774 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
1777 Irp
->IoStatus
.Status
= Context
.Status
;
1780 return Context
.Status
;
1789 KsIsBusEnumChildDevice(
1790 IN PDEVICE_OBJECT DeviceObject
,
1791 OUT PBOOLEAN ChildDevice
)
1793 PDEV_EXTENSION DeviceExtension
;
1794 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1796 DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject
);
1798 /* get device extension */
1799 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1801 /* get bus device extension */
1802 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1804 if (!BusDeviceExtension
)
1806 /* not a bus device */
1807 return STATUS_INVALID_PARAMETER
;
1811 *ChildDevice
= (BusDeviceExtension
->Common
.IsBus
== FALSE
);
1813 return STATUS_SUCCESS
;
1822 KsServiceBusEnumCreateRequest(
1823 IN PDEVICE_OBJECT DeviceObject
,
1827 PBUS_DEVICE_ENTRY DeviceEntry
= NULL
; /* fix gcc */
1828 PIO_STACK_LOCATION IoStack
;
1829 BOOLEAN ItemExists
= FALSE
;
1830 PDEV_EXTENSION DeviceExtension
;
1831 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1832 //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension;
1838 /* get device extension */
1839 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1841 /* get bus device extension */
1842 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1844 /* get current irp stack location */
1845 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1848 ASSERT(IoStack
->FileObject
);
1849 ASSERT(IoStack
->FileObject
->FileName
.Buffer
);
1851 DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1853 /* scan list and check if it is already present */
1854 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1856 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1858 /* get real offset */
1859 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1861 /* check if name matches */
1862 if (!wcsicmp(DeviceEntry
->DeviceName
, IoStack
->FileObject
->FileName
.Buffer
+ 1))
1864 /* item already exists */
1869 /* move to next entry */
1870 Entry
= Entry
->Flink
;
1875 /* interface not registered */
1876 DPRINT1("Interface %wZ not registered\n", &IoStack
->FileObject
->FileName
);
1877 return STATUS_OBJECT_NAME_NOT_FOUND
;
1880 /* is there a pdo yet */
1881 if (DeviceEntry
->PDO
)
1883 if (DeviceEntry
->DeviceState
== Started
)
1886 Status
= KspDoReparseForIrp(Irp
, DeviceEntry
);
1887 DPRINT("REPARSE Irp %p '%wZ'\n", Irp
, &IoStack
->FileObject
->FileName
);
1889 Irp
->IoStatus
.Status
= Status
;
1893 /* delay processing until pnp is finished with enumeration */
1894 IoMarkIrpPending(Irp
);
1896 /* insert into irp pending list */
1897 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1899 Time
.QuadPart
= Int32x32To64(1500, -10000);
1900 DbgPrint("PENDING Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1902 /* query current time */
1903 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
1906 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1909 return STATUS_PENDING
;
1914 /* time to create PDO */
1915 Status
= KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1917 if (!NT_SUCCESS(Status
))
1919 /* failed to create PDO */
1920 DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status
);
1923 DPRINT1("PENDING CREATE Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1925 /* delay processing until pnp is finished with enumeration */
1926 IoMarkIrpPending(Irp
);
1928 /* insert into irp pending list */
1929 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1931 /* get current time */
1932 KeQuerySystemTime(&DeviceEntry
->TimeCreated
);
1934 /* invalidate device relations */
1935 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1938 return STATUS_PENDING
;
1948 KsServiceBusEnumPnpRequest(
1949 IN PDEVICE_OBJECT DeviceObject
,
1952 PDEV_EXTENSION DeviceExtension
;
1953 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1954 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
;
1955 PIO_STACK_LOCATION IoStack
;
1958 PDEVICE_RELATIONS DeviceRelation
;
1959 PBUS_DEVICE_ENTRY DeviceEntry
;
1961 /* get device extension */
1962 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1964 /* get bus device extension */
1965 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1967 /* get current irp stack location */
1968 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1970 if (BusDeviceExtension
->Common
.IsBus
)
1972 if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
1974 /* no op for bus driver */
1975 Status
= STATUS_SUCCESS
;
1977 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
)
1979 /* handle bus device relations */
1980 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== BusRelations
);
1982 Status
= KspQueryBusRelations(BusDeviceExtension
, Irp
);
1986 /* get default status */
1987 Status
= Irp
->IoStatus
.Status
;
1992 /* get child device extension */
1993 ChildDeviceExtension
= DeviceExtension
->Ext
;
1995 /* get bus device extension */
1996 BusDeviceExtension
= ChildDeviceExtension
->BusDeviceExtension
;
1998 if (IoStack
->MinorFunction
== IRP_MN_QUERY_ID
)
2001 Status
= KspQueryId(ChildDeviceExtension
, Irp
);
2003 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
2005 ASSERT(ChildDeviceExtension
->DeviceEntry
->DeviceState
!= Started
|| ChildDeviceExtension
->DeviceEntry
->DeviceState
== NotStarted
);
2006 ASSERT(ChildDeviceExtension
->DeviceEntry
->PDO
== DeviceObject
);
2008 /* backup device entry */
2009 DeviceEntry
= ChildDeviceExtension
->DeviceEntry
;
2011 /* free device extension */
2012 FreeItem(ChildDeviceExtension
);
2014 /* clear PDO reference */
2015 DeviceEntry
->PDO
= NULL
;
2017 /* delete the device */
2018 IoDeleteDevice(DeviceObject
);
2020 if (DeviceEntry
->PDODeviceName
)
2022 /* delete pdo device name */
2023 FreeItem(DeviceEntry
->PDODeviceName
);
2026 DeviceEntry
->PDODeviceName
= NULL
;
2029 /* set state no notstarted */
2030 DeviceEntry
->DeviceState
= NotStarted
;
2032 /* time to create PDO */
2033 KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
2035 /* invalidate device relations */
2036 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
2039 Status
= STATUS_SUCCESS
;
2041 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_BUS_INFORMATION
)
2043 /* query bus information */
2044 Status
= KspQueryBusInformation(ChildDeviceExtension
, Irp
);
2046 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCES
)
2049 Status
= STATUS_SUCCESS
;
2051 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCE_REQUIREMENTS
)
2054 Status
= STATUS_SUCCESS
;
2056 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
2059 Status
= KspStartBusDevice(DeviceObject
, ChildDeviceExtension
, Irp
);
2062 Time
.QuadPart
= Int32x32To64(1500, -10000);
2065 ASSERT(BusDeviceExtension
);
2068 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
2070 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_CAPABILITIES
)
2072 /* query capabilities */
2073 Status
= KspQueryBusDeviceCapabilities(ChildDeviceExtension
, Irp
);
2075 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
2077 /* query pnp state */
2078 Status
= KspQueryBusDevicePnpState(ChildDeviceExtension
, Irp
);
2080 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_INTERFACE
)
2082 /* query interface */
2083 Status
= KspQueryBusDeviceInterface(ChildDeviceExtension
, Irp
);
2085 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
&& IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
2087 /* handle target device relations */
2088 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
);
2089 ASSERT(Irp
->IoStatus
.Information
== 0);
2091 /* allocate device relation */
2092 DeviceRelation
= AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
));
2095 DeviceRelation
->Count
= 1;
2096 DeviceRelation
->Objects
[0] = DeviceObject
;
2098 /* reference self */
2099 ObReferenceObject(DeviceObject
);
2102 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelation
;
2105 Status
= STATUS_SUCCESS
;
2110 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2115 /* get default status */
2116 Status
= Irp
->IoStatus
.Status
;
2120 DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject
, BusDeviceExtension
->Common
.IsBus
, IoStack
->MinorFunction
, Status
);
2121 Irp
->IoStatus
.Status
= Status
;
2131 KsRemoveBusEnumInterface(
2134 KPROCESSOR_MODE Mode
;
2136 BUS_INSTALL_ENUM_CONTEXT Ctx
;
2137 PDEV_EXTENSION DeviceExtension
;
2138 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
2139 PIO_STACK_LOCATION IoStack
;
2141 DPRINT1("KsRemoveBusEnumInterface\n");
2143 /* get io stack location */
2144 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2146 /* get device extension */
2147 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
2149 /* get bus device extension */
2150 BusDeviceExtension
= DeviceExtension
->Ext
->BusDeviceExtension
;
2152 /* get previous mode */
2153 Mode
= ExGetPreviousMode();
2155 /* convert to luid */
2156 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
2158 /* perform access check */
2159 if (!SeSinglePrivilegeCheck(luid
, Mode
))
2161 /* insufficient privileges */
2162 return STATUS_PRIVILEGE_NOT_HELD
;
2165 /* initialize context */
2166 KeInitializeEvent(&Ctx
.Event
, NotificationEvent
, FALSE
);
2168 Ctx
.BusDeviceExtension
= BusDeviceExtension
;
2169 ExInitializeWorkItem(&Ctx
.WorkItem
, KspRemoveBusInterface
, (PVOID
)&Ctx
);
2171 /* now queue the work item */
2172 ExQueueWorkItem(&Ctx
.WorkItem
, DelayedWorkQueue
);
2174 /* wait for completion */
2175 KeWaitForSingleObject(&Ctx
.Event
, Executive
, KernelMode
, FALSE
, NULL
);