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
;
77 DeviceEntry
->DeviceState
= NotStarted
;
79 /* get current time */
80 KeQueryTickCount(&DeviceEntry
->TimeCreated
);
83 DeviceObject
->Flags
|= DO_POWER_PAGABLE
;
84 DeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
85 /* TODO: fire time when expired */
87 *OutDeviceObject
= DeviceObject
;
89 return STATUS_SUCCESS
;
93 KspRegisterDeviceAssociation(
94 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
95 IN PBUS_DEVICE_ENTRY DeviceEntry
,
96 IN OUT PBUS_INSTANCE_ENTRY BusInstanceEntry
)
99 UNICODE_STRING ReferenceString
;
101 /* initialize reference string */
102 RtlInitUnicodeString(&ReferenceString
, DeviceEntry
->DeviceName
);
104 /* register device interface */
105 Status
= IoRegisterDeviceInterface(BusDeviceExtension
->PhysicalDeviceObject
, &BusInstanceEntry
->InterfaceGuid
, &ReferenceString
, &BusInstanceEntry
->SymbolicLink
);
107 /* check for success */
108 if (!NT_SUCCESS(Status
))
114 /* now enable the interface */
115 Status
= IoSetDeviceInterfaceState(&BusInstanceEntry
->SymbolicLink
, TRUE
);
117 /* check for success */
118 if (!NT_SUCCESS(Status
))
120 /* failed, free memory */
121 FreeItem(BusInstanceEntry
->SymbolicLink
.Buffer
);
125 DPRINT("Registered DeviceInterface %wZ\n", &BusInstanceEntry
->SymbolicLink
);
133 KspRemoveDeviceAssociations(
134 IN PBUS_DEVICE_ENTRY DeviceEntry
)
137 PBUS_INSTANCE_ENTRY CurEntry
;
139 /* remove all entries */
140 Entry
= DeviceEntry
->DeviceInterfaceList
.Flink
;
142 while(Entry
!= &DeviceEntry
->DeviceInterfaceList
)
145 CurEntry
= (PBUS_INSTANCE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_INSTANCE_ENTRY
, Entry
);
148 ASSERT(CurEntry
->SymbolicLink
.Buffer
);
150 /* de-register interface */
151 IoSetDeviceInterfaceState(&CurEntry
->SymbolicLink
, FALSE
);
153 /* free symbolic link buffer */
154 FreeItem(CurEntry
->SymbolicLink
.Buffer
);
156 /* remove entry from list */
157 RemoveEntryList(Entry
);
159 /* move to next entry */
160 Entry
= Entry
->Flink
;
168 KspEnumerateBusRegistryKeys(
170 IN LPWSTR ReferenceString
,
171 IN PKSP_BUS_ENUM_CALLBACK Callback
,
172 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
173 IN PBUS_DEVICE_ENTRY DeviceEntry
)
175 UNICODE_STRING String
;
176 OBJECT_ATTRIBUTES ObjectAttributes
;
179 ULONG ResultLength
, Index
, KeyInfoLength
;
180 KEY_FULL_INFORMATION KeyInformation
;
181 PKEY_BASIC_INFORMATION KeyInfo
;
183 /* initialize key name */
184 RtlInitUnicodeString(&String
, ReferenceString
);
186 /* initialize object attributes */
187 InitializeObjectAttributes(&ObjectAttributes
, &String
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hKey
, NULL
);
190 Status
= ZwOpenKey(&hNewKey
, GENERIC_READ
, &ObjectAttributes
);
192 /* check for success */
193 if (!NT_SUCCESS(Status
))
195 /* failed to open key */
200 /* query key stats */
201 Status
= ZwQueryKey(hNewKey
, KeyFullInformation
, &KeyInformation
, sizeof(KeyInformation
), &ResultLength
);
203 if (!NT_SUCCESS(Status
))
212 /* calculate key info length */
213 KeyInfoLength
= KeyInformation
.MaxNameLen
+ sizeof(KEY_BASIC_INFORMATION
) + 1 * sizeof(WCHAR
);
215 /* allocate buffer */
216 KeyInfo
= (PKEY_BASIC_INFORMATION
)AllocateItem(NonPagedPool
, KeyInfoLength
);
224 return STATUS_INSUFFICIENT_RESOURCES
;
227 /* enumerate all keys */
228 for(Index
= 0; Index
< KeyInformation
.SubKeys
; Index
++)
232 Status
= ZwEnumerateKey(hNewKey
, Index
, KeyBasicInformation
, (PVOID
)KeyInfo
, KeyInfoLength
, &ResultLength
);
234 /* check for success */
235 if (NT_SUCCESS(Status
))
237 /* perform callback */
238 Status
= Callback(hNewKey
, BusDeviceExtension
, DeviceEntry
, KeyInfo
->Name
, ReferenceString
);
240 /* should enumeration stop */
241 if (!NT_SUCCESS(Status
))
246 /* free info buffer */
258 KspCreateDeviceAssociation(
260 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
261 IN PBUS_DEVICE_ENTRY DeviceEntry
,
262 IN LPWSTR InterfaceString
,
263 IN LPWSTR ReferenceString
)
268 PBUS_INSTANCE_ENTRY CurEntry
;
269 UNICODE_STRING DeviceName
;
271 /* initialize interface string */
272 RtlInitUnicodeString(&DeviceName
, InterfaceString
);
274 /* first convert device name to guid */
275 RtlGUIDFromString(&DeviceName
, &InterfaceGUID
);
277 /* check if the device is already present */
278 Entry
= DeviceEntry
->DeviceInterfaceList
.Flink
;
279 DPRINT("KspCreateDeviceAssociation ReferenceString %S\n", ReferenceString
);
280 DPRINT("KspCreateDeviceAssociation InterfaceString %S\n", InterfaceString
);
282 while(Entry
!= &DeviceEntry
->DeviceInterfaceList
)
285 CurEntry
= (PBUS_INSTANCE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_INSTANCE_ENTRY
, Entry
);
287 if (IsEqualGUIDAligned(&CurEntry
->InterfaceGuid
, &InterfaceGUID
))
289 /* entry already exists */
290 return STATUS_SUCCESS
;
293 /* move to next entry */
294 Entry
= Entry
->Flink
;
297 /* time to allocate new entry */
298 CurEntry
= (PBUS_INSTANCE_ENTRY
)AllocateItem(NonPagedPool
, sizeof(BUS_INSTANCE_ENTRY
));
303 return STATUS_INSUFFICIENT_RESOURCES
;
307 RtlMoveMemory(&CurEntry
->InterfaceGuid
, &InterfaceGUID
, sizeof(GUID
));
309 /* now register the association */
310 Status
= KspRegisterDeviceAssociation(BusDeviceExtension
, DeviceEntry
, CurEntry
);
312 /* check for success */
313 if (NT_SUCCESS(Status
))
316 InsertTailList(&DeviceEntry
->DeviceInterfaceList
, &CurEntry
->Entry
);
320 /* failed to associated device */
330 KspCreateDeviceReference(
332 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
333 IN PBUS_DEVICE_ENTRY DummyEntry
,
334 IN LPWSTR InterfaceId
,
340 PBUS_DEVICE_ENTRY DeviceEntry
= NULL
; /* GCC warning */
341 BOOLEAN ItemExists
= FALSE
;
342 UNICODE_STRING String
;
346 /* first construct device name & reference guid */
347 Length
= wcslen(DeviceId
) + wcslen(InterfaceId
);
349 /* append '&' and null byte */
352 /* allocate device name */
353 DeviceName
= AllocateItem(NonPagedPool
, Length
* sizeof(WCHAR
));
357 /* not enough memory */
358 return STATUS_INSUFFICIENT_RESOURCES
;
361 /* construct device name */
362 wcscpy(DeviceName
, DeviceId
);
363 wcscat(DeviceName
, L
"&");
364 wcscat(DeviceName
, InterfaceId
);
366 /* scan list and check if it is already present */
367 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
369 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
371 /* get real offset */
372 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
374 /* check if name matches */
375 if (!wcsicmp(DeviceEntry
->DeviceName
, DeviceName
))
377 /* item already exists */
382 /* move to next entry */
383 Entry
= Entry
->Flink
;
388 /* allocate new device entry */
389 DeviceEntry
= AllocateItem(NonPagedPool
, sizeof(BUS_DEVICE_ENTRY
));
393 FreeItem(DeviceName
);
394 return STATUS_INSUFFICIENT_RESOURCES
;
397 /* initialize device entry */
398 InitializeListHead(&DeviceEntry
->DeviceInterfaceList
);
399 InitializeListHead(&DeviceEntry
->IrpPendingList
);
401 /* copy device guid */
402 RtlInitUnicodeString(&String
, DeviceId
);
403 RtlGUIDFromString(&String
, &DeviceEntry
->DeviceGuid
);
405 /* copy device names */
406 DeviceEntry
->DeviceName
= DeviceName
;
407 DeviceEntry
->Instance
= (DeviceName
+ wcslen(DeviceId
) + 1);
410 DeviceEntry
->BusId
= AllocateItem(NonPagedPool
, (wcslen(DeviceId
) + 1) * sizeof(WCHAR
));
411 if (!DeviceEntry
->BusId
)
414 FreeItem(DeviceName
);
415 FreeItem(DeviceEntry
);
416 return STATUS_INSUFFICIENT_RESOURCES
;
418 wcscpy(DeviceEntry
->BusId
, DeviceId
);
421 /* now enumerate the interfaces */
422 Status
= KspEnumerateBusRegistryKeys(hKey
, InterfaceId
, KspCreateDeviceAssociation
, BusDeviceExtension
, DeviceEntry
);
424 /* check if list is empty */
425 if (IsListEmpty(&DeviceEntry
->DeviceInterfaceList
))
427 /* invalid device settings */
428 FreeItem(DeviceEntry
->BusId
);
429 FreeItem(DeviceEntry
->DeviceName
);
430 FreeItem(DeviceEntry
);
432 ASSERT(ItemExists
== FALSE
);
434 return STATUS_INVALID_DEVICE_STATE
;
437 /* check if enumeration failed */
438 if (!NT_SUCCESS(Status
))
441 KspRemoveDeviceAssociations(DeviceEntry
);
442 FreeItem(DeviceEntry
->BusId
);
443 FreeItem(DeviceEntry
->DeviceName
);
444 FreeItem(DeviceEntry
);
446 ASSERT(ItemExists
== FALSE
);
455 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
457 /* successfully initialized entry */
458 InsertTailList(&BusDeviceExtension
->Common
.Entry
, &DeviceEntry
->Entry
);
461 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
470 KspCreateDeviceReferenceTrampoline(
472 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
473 IN PBUS_DEVICE_ENTRY DummyEntry
,
474 IN LPWSTR DeviceCategory
,
475 IN LPWSTR ReferenceString
)
477 return KspEnumerateBusRegistryKeys(hKey
, DeviceCategory
, KspCreateDeviceReference
, BusDeviceExtension
, DummyEntry
);
482 KspOpenBusRegistryKey(
483 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
486 OBJECT_ATTRIBUTES ObjectAttributes
;
488 /* initialize object attributes */
489 InitializeObjectAttributes(&ObjectAttributes
, &BusDeviceExtension
->ServicePath
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
491 return ZwCreateKey(hKey
, GENERIC_READ
| GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
496 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
)
502 Status
= KspOpenBusRegistryKey(BusDeviceExtension
, &hKey
);
504 /* check for success */
505 if (!NT_SUCCESS(Status
))
512 /* TODO clear reference marks */
514 /* construct device entries */
515 Status
= KspEnumerateBusRegistryKeys(hKey
, NULL
, KspCreateDeviceReferenceTrampoline
, BusDeviceExtension
, NULL
);
517 /* TODO: delete unreferenced devices */
529 KspBusQueryReferenceString(
531 IN OUT PWCHAR
*String
)
535 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)Context
;
538 ASSERT(BusDeviceExtension
);
539 ASSERT(BusDeviceExtension
->BusIdentifier
);
541 /* calculate length */
542 Length
= wcslen(BusDeviceExtension
->BusIdentifier
) + 1;
544 /* allocate buffer */
545 Name
= AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
549 /* failed to allocate buffer */
550 return STATUS_INSUFFICIENT_RESOURCES
;
554 wcscpy(Name
, BusDeviceExtension
->BusIdentifier
);
560 return STATUS_SUCCESS
;
565 KspBusDeviceReference(
568 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
570 /* reference count */
571 InterlockedIncrement((PLONG
)&ChildDeviceExtension
->DeviceReferenceCount
);
576 KspBusDeviceDereference(
579 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
581 /* reference count */
582 InterlockedDecrement((PLONG
)&ChildDeviceExtension
->DeviceReferenceCount
);
587 KspBusReferenceDeviceObject(
590 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
592 /* reference count */
593 InterlockedIncrement((PLONG
)&ChildDeviceExtension
->DeviceObjectReferenceCount
);
598 KspBusDereferenceDeviceObject(
601 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
= (PCOMMON_DEVICE_EXTENSION
)Context
;
603 /* reference count */
604 InterlockedDecrement((PLONG
)&ChildDeviceExtension
->DeviceObjectReferenceCount
);
608 KspQueryBusDeviceInterface(
609 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
612 PBUS_INTERFACE_SWENUM Interface
;
613 PIO_STACK_LOCATION IoStack
;
615 /* get current irp stack location */
616 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
619 ASSERT(IoStack
->Parameters
.QueryInterface
.Size
== sizeof(BUS_INTERFACE_SWENUM
));
620 ASSERT(IoStack
->Parameters
.QueryInterface
.Interface
);
622 /* fill in interface */
623 Interface
= (PBUS_INTERFACE_SWENUM
)IoStack
->Parameters
.QueryInterface
.Interface
;
624 Interface
->Interface
.Size
= sizeof(BUS_INTERFACE_SWENUM
);
625 Interface
->Interface
.Version
= BUS_INTERFACE_SWENUM_VERSION
;
626 Interface
->Interface
.Context
= ChildDeviceExtension
;
627 Interface
->Interface
.InterfaceReference
= KspBusDeviceReference
;
628 Interface
->Interface
.InterfaceDereference
= KspBusDeviceDereference
;
629 Interface
->ReferenceDeviceObject
= KspBusReferenceDeviceObject
;
630 Interface
->DereferenceDeviceObject
= KspBusDereferenceDeviceObject
;
631 Interface
->QueryReferenceString
= KspBusQueryReferenceString
;
633 return STATUS_SUCCESS
;
637 KspEnableBusDeviceInterface(
638 PBUS_DEVICE_ENTRY DeviceEntry
,
642 PBUS_INSTANCE_ENTRY InstanceEntry
;
643 NTSTATUS Status
= STATUS_SUCCESS
;
645 /* enable now all interfaces */
646 Entry
= DeviceEntry
->DeviceInterfaceList
.Flink
;
648 while(Entry
!= &DeviceEntry
->DeviceInterfaceList
)
650 /* get bus instance entry */
651 InstanceEntry
= (PBUS_INSTANCE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_INSTANCE_ENTRY
, Entry
);
652 DPRINT("Enabling %u %wZ Irql %u\n", bEnable
, &InstanceEntry
->SymbolicLink
, KeGetCurrentIrql());
654 /* set interface state */
655 Status
= IoSetDeviceInterfaceState(&InstanceEntry
->SymbolicLink
, bEnable
);
657 if (!NT_SUCCESS(Status
))
659 /* failed to set interface */
663 /* move to next entry */
664 Entry
= Entry
->Flink
;
674 PBUS_DEVICE_ENTRY DeviceEntry
)
678 PIO_STACK_LOCATION IoStack
;
680 /* get stack location */
681 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
684 ASSERT(DeviceEntry
->PDODeviceName
);
685 ASSERT(DeviceEntry
->Instance
);
686 ASSERT(IoStack
->FileObject
);
687 ASSERT(IoStack
->FileObject
->FileName
.Buffer
);
689 /* calculate length */
690 Length
= wcslen(DeviceEntry
->PDODeviceName
);
691 Length
+= wcslen(DeviceEntry
->Instance
);
693 /* zero byte and '\\' */
696 /* allocate buffer */
697 Buffer
= ExAllocatePoolWithTag(NonPagedPool
, Length
* sizeof(WCHAR
), 'mNoI');
701 return STATUS_INSUFFICIENT_RESOURCES
;
704 /* construct buffer */
705 swprintf(Buffer
, L
"%s\\%s", DeviceEntry
->PDODeviceName
, DeviceEntry
->Instance
);
708 ExFreePoolWithTag(IoStack
->FileObject
->FileName
.Buffer
, 'mNoI');
710 /* store new file name */
711 RtlInitUnicodeString(&IoStack
->FileObject
->FileName
, Buffer
);
714 return STATUS_REPARSE
;
718 KspCompletePendingIrps(
719 IN PBUS_DEVICE_ENTRY DeviceEntry
,
720 IN OUT NTSTATUS ResultCode
)
726 /* go through list */
727 while(!IsListEmpty(&DeviceEntry
->IrpPendingList
))
729 /* get first entry */
730 Entry
= RemoveHeadList(&DeviceEntry
->IrpPendingList
);
733 Irp
= (PIRP
)CONTAINING_RECORD(Entry
, IRP
, Tail
.Overlay
.ListEntry
);
735 if (ResultCode
== STATUS_REPARSE
)
737 /* construct reparse information */
738 Status
= KspDoReparseForIrp(Irp
, DeviceEntry
);
742 /* use default code */
746 /* store result code */
747 Irp
->IoStatus
.Status
= Status
;
749 DPRINT("Completing IRP %p Status %x\n", Irp
, Status
);
751 /* complete the request */
752 CompleteRequest(Irp
, IO_NO_INCREMENT
);
761 IN PDEVICE_OBJECT DeviceObject
,
762 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
770 PBUS_DEVICE_ENTRY DeviceEntry
;
772 /* FIXME handle pending remove */
774 /* get full device name */
775 Status
= IoGetDeviceProperty(DeviceObject
, DevicePropertyPhysicalDeviceObjectName
, sizeof(PDOName
), PDOName
, &ResultLength
);
777 if (!NT_SUCCESS(Status
))
779 /* failed to get device name */
783 /* allocate device name buffer */
784 NameLength
= ResultLength
+ sizeof(UNICODE_NULL
);
785 Name
= AllocateItem(NonPagedPool
, NameLength
);
789 return STATUS_INSUFFICIENT_RESOURCES
;
793 NT_VERIFY(NT_SUCCESS(RtlStringCbCopyW(Name
, NameLength
, PDOName
)));
795 /* TODO: time stamp creation time */
797 /* get device entry */
798 DeviceEntry
= (PBUS_DEVICE_ENTRY
)ChildDeviceExtension
->DeviceEntry
;
803 /* store device name */
804 DeviceEntry
->PDODeviceName
= Name
;
806 /* mark device as started */
807 DeviceEntry
->DeviceState
= Started
;
809 /* reference start time */
810 KeQueryTickCount(&DeviceEntry
->TimeCreated
);
812 DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name
, DeviceEntry
->DeviceName
, DeviceEntry
->Instance
);
814 /* enable device classes */
815 //KspEnableBusDeviceInterface(DeviceEntry, TRUE);
818 return STATUS_SUCCESS
;
822 KspQueryBusDeviceCapabilities(
823 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
826 PDEVICE_CAPABILITIES Capabilities
;
827 PIO_STACK_LOCATION IoStack
;
829 /* get stack location */
830 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
832 /* get capabilities */
833 Capabilities
= IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
835 RtlZeroMemory(Capabilities
, sizeof(DEVICE_CAPABILITIES
));
837 /* setup capabilities */
838 Capabilities
->UniqueID
= TRUE
;
839 Capabilities
->SilentInstall
= TRUE
;
840 Capabilities
->SurpriseRemovalOK
= TRUE
;
841 Capabilities
->Address
= 0;
842 Capabilities
->UINumber
= 0;
843 Capabilities
->SystemWake
= PowerSystemWorking
; /* FIXME common device extension */
844 Capabilities
->DeviceWake
= PowerDeviceD0
;
847 return STATUS_SUCCESS
;
851 KspQueryBusInformation(
852 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
855 PPNP_BUS_INFORMATION BusInformation
;
857 /* allocate bus information */
858 BusInformation
= (PPNP_BUS_INFORMATION
)AllocateItem(PagedPool
, sizeof(PNP_BUS_INFORMATION
));
863 return STATUS_INSUFFICIENT_RESOURCES
;
867 BusInformation
->BusNumber
= 0;
868 BusInformation
->LegacyBusType
= InterfaceTypeUndefined
;
869 RtlMoveMemory(&BusInformation
->BusTypeGuid
, &KSMEDIUMSETID_Standard
, sizeof(GUID
));
872 Irp
->IoStatus
.Information
= (ULONG_PTR
)BusInformation
;
875 return STATUS_SUCCESS
;
879 KspQueryBusDevicePnpState(
880 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
883 /* set device flags */
884 Irp
->IoStatus
.Information
= PNP_DEVICE_DONT_DISPLAY_IN_UI
| PNP_DEVICE_NOT_DISABLEABLE
;
887 return STATUS_SUCCESS
;
892 IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
,
895 PIO_STACK_LOCATION IoStack
;
896 PBUS_DEVICE_ENTRY DeviceEntry
;
897 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
901 /* get current irp stack location */
902 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
904 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryInstanceID
)
906 /* get device entry */
907 DeviceEntry
= (PBUS_DEVICE_ENTRY
) ChildDeviceExtension
->DeviceEntry
;
911 ASSERT(DeviceEntry
->Instance
);
913 /* calculate length */
914 Length
= wcslen(DeviceEntry
->Instance
) + 2;
916 /* allocate buffer */
917 Name
= AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
921 /* failed to allocate buffer */
922 return STATUS_INSUFFICIENT_RESOURCES
;
926 wcscpy(Name
, DeviceEntry
->Instance
);
929 Irp
->IoStatus
.Information
= (ULONG_PTR
)Name
;
932 return STATUS_SUCCESS
;
934 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
||
935 IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
937 /* get device entry */
938 DeviceEntry
= (PBUS_DEVICE_ENTRY
) ChildDeviceExtension
->DeviceEntry
;
940 /* get bus device extension */
941 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
) ChildDeviceExtension
->BusDeviceExtension
;
945 ASSERT(DeviceEntry
->BusId
);
946 ASSERT(BusDeviceExtension
);
947 ASSERT(BusDeviceExtension
->BusIdentifier
);
949 /* calculate length */
950 Length
= wcslen(BusDeviceExtension
->BusIdentifier
);
951 Length
+= wcslen(DeviceEntry
->BusId
);
953 /* extra length for '\\' and 2 zero bytes */
956 /* allocate buffer */
957 Name
= AllocateItem(PagedPool
, Length
* sizeof(WCHAR
));
960 /* failed to allocate buffer */
961 return STATUS_INSUFFICIENT_RESOURCES
;
965 wcscpy(Name
, BusDeviceExtension
->BusIdentifier
);
967 wcscat(Name
, DeviceEntry
->BusId
);
968 //swprintf(Name, L"%s\\%s", BusDeviceExtension->BusIdentifier, DeviceEntry->BusId);
971 Irp
->IoStatus
.Information
= (ULONG_PTR
)Name
;
974 return STATUS_SUCCESS
;
978 /* other ids are not supported */
979 //DPRINT1("Not Supported ID Type %x\n", IoStack->Parameters.QueryId.IdType);
980 return Irp
->IoStatus
.Status
;
986 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
987 IN PSWENUM_INSTALL_INTERFACE InstallInterface
)
989 SIZE_T Length
, Index
;
990 UNICODE_STRING DeviceString
, InterfaceString
, ReferenceString
;
991 HANDLE hKey
, hDeviceKey
, hInterfaceKey
, hReferenceKey
;
993 OBJECT_ATTRIBUTES ObjectAttributes
;
996 ASSERT(InstallInterface
);
998 /* calculate length */
999 Length
= wcslen(InstallInterface
->ReferenceString
);
1001 /* check for invalid characters */
1002 for(Index
= 0; Index
< Length
; Index
++)
1004 if (InstallInterface
->ReferenceString
[Index
] <= L
' ' ||
1005 InstallInterface
->ReferenceString
[Index
] > L
'~' ||
1006 InstallInterface
->ReferenceString
[Index
] == L
',' ||
1007 InstallInterface
->ReferenceString
[Index
] == L
'\\' ||
1008 InstallInterface
->ReferenceString
[Index
] == L
'/')
1010 /* invalid character */
1011 return STATUS_INVALID_PARAMETER
;
1016 Status
= KspOpenBusRegistryKey(BusDeviceExtension
, &hKey
);
1017 if (NT_SUCCESS(Status
))
1019 /* convert device guid to string */
1020 Status
= RtlStringFromGUID(&InstallInterface
->DeviceId
, &DeviceString
);
1021 if (NT_SUCCESS(Status
))
1023 /* initialize object attributes */
1024 InitializeObjectAttributes(&ObjectAttributes
, &DeviceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hKey
, NULL
);
1026 /* construct device key */
1027 Status
= ZwCreateKey(&hDeviceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1028 if (NT_SUCCESS(Status
))
1030 /* convert interface guid to string */
1031 Status
= RtlStringFromGUID(&InstallInterface
->InterfaceId
, &InterfaceString
);
1032 if (NT_SUCCESS(Status
))
1034 /* initialize object attributes */
1035 InitializeObjectAttributes(&ObjectAttributes
, &InterfaceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hDeviceKey
, NULL
);
1037 /* construct device key */
1038 Status
= ZwCreateKey(&hInterfaceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1039 if (NT_SUCCESS(Status
))
1041 /* initialize reference string */
1042 RtlInitUnicodeString(&ReferenceString
, InstallInterface
->ReferenceString
);
1044 /* initialize object attributes */
1045 InitializeObjectAttributes(&ObjectAttributes
, &ReferenceString
, OBJ_KERNEL_HANDLE
| OBJ_CASE_INSENSITIVE
, hInterfaceKey
, NULL
);
1047 /* construct device key */
1048 Status
= ZwCreateKey(&hReferenceKey
, GENERIC_WRITE
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
1049 if (NT_SUCCESS(Status
))
1052 ZwClose(hReferenceKey
);
1055 /* free interface string */
1056 RtlFreeUnicodeString(&InterfaceString
);
1058 /* close reference key */
1059 ZwClose(hInterfaceKey
);
1061 /* close device key */
1062 ZwClose(hDeviceKey
);
1064 /* free device string */
1065 RtlFreeUnicodeString(&DeviceString
);
1077 KspInstallBusEnumInterface(
1080 PIO_STACK_LOCATION IoStack
;
1083 PBUS_DEVICE_ENTRY DeviceEntry
;
1084 PSWENUM_INSTALL_INTERFACE InstallInterface
;
1086 PBUS_INSTALL_ENUM_CONTEXT Context
= (PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1088 /* get current irp stack location */
1089 IoStack
= IoGetCurrentIrpStackLocation(Context
->Irp
);
1091 /* get install request */
1092 InstallInterface
= (PSWENUM_INSTALL_INTERFACE
)Context
->Irp
->AssociatedIrp
.SystemBuffer
;
1095 ASSERT(InstallInterface
);
1096 ASSERT(Context
->BusDeviceExtension
);
1098 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
< sizeof(SWENUM_INSTALL_INTERFACE
))
1100 /* buffer too small */
1101 Context
->Status
= STATUS_INVALID_PARAMETER
;
1103 /* signal completion */
1104 KeSetEvent(&Context
->Event
, 0, FALSE
);
1112 /* now install the interface */
1113 Status
= KspInstallInterface(Context
->BusDeviceExtension
, InstallInterface
);
1114 if (!NT_SUCCESS(Status
))
1116 /* failed to install interface */
1117 Context
->Status
= Status
;
1119 /* signal completion */
1120 KeSetEvent(&Context
->Event
, 0, FALSE
);
1126 /* now scan the bus */
1127 Status
= KspScanBus(Context
->BusDeviceExtension
);
1128 // FIXME: We may need to check for success here, and properly fail...
1129 ASSERT(NT_SUCCESS(Status
));
1131 /* acquire device entry lock */
1132 KeAcquireSpinLock(&Context
->BusDeviceExtension
->Lock
, &OldLevel
);
1134 /* now iterate all device entries */
1135 ASSERT(!IsListEmpty(&Context
->BusDeviceExtension
->Common
.Entry
));
1136 Entry
= Context
->BusDeviceExtension
->Common
.Entry
.Flink
;
1137 while(Entry
!= &Context
->BusDeviceExtension
->Common
.Entry
)
1139 /* get device entry */
1140 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1141 if (IsEqualGUIDAligned(&DeviceEntry
->DeviceGuid
, &InstallInterface
->DeviceId
))
1143 if (!DeviceEntry
->PDO
)
1145 /* release device entry lock */
1146 KeReleaseSpinLock(&Context
->BusDeviceExtension
->Lock
, OldLevel
);
1149 Status
= KspCreatePDO(Context
->BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1151 /* acquire device entry lock */
1152 KeAcquireSpinLock(&Context
->BusDeviceExtension
->Lock
, &OldLevel
);
1159 /* move to next entry */
1160 Entry
= Entry
->Flink
;
1163 /* release device entry lock */
1164 KeReleaseSpinLock(&Context
->BusDeviceExtension
->Lock
, OldLevel
);
1166 /* signal that bus driver relations has changed */
1167 IoInvalidateDeviceRelations(Context
->BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1170 Context
->Status
= Status
;
1172 /* signal completion */
1173 KeSetEvent(&Context
->Event
, 0, FALSE
);
1179 KspBusWorkerRoutine(
1182 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1183 PBUS_DEVICE_ENTRY DeviceEntry
;
1185 LARGE_INTEGER Time
, Diff
;
1186 BOOLEAN DoInvalidate
= FALSE
;
1189 /* get device extension */
1190 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)Parameter
;
1193 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1195 /* get current time */
1196 KeQueryTickCount(&Time
);
1198 /* enumerate all device entries */
1199 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1200 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1202 /* get offset to device entry */
1203 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1206 ASSERT(DeviceEntry
);
1208 //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState);
1210 if (DeviceEntry
->PDO
)
1212 if (DeviceEntry
->DeviceState
== NotStarted
)
1214 Diff
.QuadPart
= (Time
.QuadPart
- DeviceEntry
->TimeCreated
.QuadPart
) * KeQueryTimeIncrement();
1216 /* wait for 15 sec */
1217 if (Diff
.QuadPart
> Int32x32To64(15000, 10000))
1219 /* release spin lock */
1220 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1222 DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n",
1223 DeviceEntry
->DeviceName
,
1224 DeviceEntry
->Instance
,
1225 DeviceEntry
->TimeCreated
.QuadPart
* KeQueryTimeIncrement(),
1226 Time
.QuadPart
* KeQueryTimeIncrement(),
1229 /* deactivate interfaces */
1230 //KspEnableBusDeviceInterface(DeviceEntry, FALSE);
1232 /* re-acquire lock */
1233 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1235 /* pending remove device object */
1236 DeviceEntry
->DeviceState
= StopPending
;
1238 /* perform invalidation */
1239 DoInvalidate
= TRUE
;
1242 else if (DeviceEntry
->DeviceState
== Started
)
1244 /* release spin lock */
1245 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1247 /* found pending irps */
1248 KspCompletePendingIrps(DeviceEntry
, STATUS_REPARSE
);
1250 /* re-acquire lock */
1251 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1257 Entry
= Entry
->Flink
;
1261 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1265 /* invalidate device relations */
1266 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1269 Time
.QuadPart
= Int32x32To64(5000, -10000);
1270 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1277 IN PVOID DeferredContext OPTIONAL
,
1278 IN PVOID SystemArgument1 OPTIONAL
,
1279 IN PVOID SystemArgument2 OPTIONAL
)
1281 /* get device extension */
1282 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeferredContext
;
1284 /* queue the item */
1285 ExQueueWorkItem(&BusDeviceExtension
->WorkItem
, DelayedWorkQueue
);
1290 KspRemoveBusInterface(
1293 PBUS_INSTALL_ENUM_CONTEXT Context
=(PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1296 * get SWENUM_INSTALL_INTERFACE struct
1297 * open device key and delete the keys
1303 Context
->Status
= STATUS_NOT_IMPLEMENTED
;
1306 /* signal completion */
1307 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
1311 KspQueryBusRelations(
1312 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
1315 PDEVICE_RELATIONS DeviceRelations
;
1317 PBUS_DEVICE_ENTRY DeviceEntry
;
1318 ULONG Count
= 0, Length
;
1322 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1324 /* first scan all device entries */
1325 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1327 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1329 /* get offset to device entry */
1330 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1332 /* is there a pdo yet */
1333 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1335 /* increment count */
1339 /* move to next entry */
1340 Entry
= Entry
->Flink
;
1343 /* calculate length */
1344 Length
= sizeof(DEVICE_RELATIONS
) + (Count
> 1 ? sizeof(PDEVICE_OBJECT
) * (Count
-1) : 0);
1346 /* allocate device relations */
1347 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(NonPagedPool
, Length
);
1349 if (!DeviceRelations
)
1351 /* not enough memory */
1352 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1353 return STATUS_INSUFFICIENT_RESOURCES
;
1356 /* rescan device entries */
1357 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1359 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1361 /* get offset to device entry */
1362 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1364 /* is there a pdo yet */
1365 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1368 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceEntry
->PDO
;
1370 /* reference device object */
1371 ObReferenceObject(DeviceEntry
->PDO
);
1373 /* increment pdo count */
1374 DeviceRelations
->Count
++;
1377 /* move to next entry */
1378 Entry
= Entry
->Flink
;
1382 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1384 /* FIXME handle existing device relations */
1385 ASSERT(Irp
->IoStatus
.Information
== 0);
1387 /* store device relations */
1388 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
1391 return STATUS_SUCCESS
;
1394 //------------------------------------------------------------------------------------
1403 KsGetBusEnumIdentifier(
1406 PDEV_EXTENSION DeviceExtension
;
1407 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1408 PIO_STACK_LOCATION IoStack
;
1413 DPRINT("KsGetBusEnumIdentifier\n");
1415 /* get stack location */
1416 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1419 ASSERT(IoStack
->DeviceObject
);
1420 ASSERT(IoStack
->DeviceObject
->DeviceExtension
);
1422 /* get device extension */
1423 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1425 /* get bus device extension */
1426 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1429 ASSERT(BusDeviceExtension
);
1430 ASSERT(BusDeviceExtension
->Common
.IsBus
);
1432 if (!BusDeviceExtension
)
1434 /* invalid parameter */
1435 return STATUS_INVALID_PARAMETER
;
1439 Length
= (wcslen(BusDeviceExtension
->BusIdentifier
)+1) * sizeof(WCHAR
);
1441 /* is there an output buffer provided */
1442 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1444 if (Length
> IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1446 /* buffer is too small */
1447 return STATUS_BUFFER_TOO_SMALL
;
1450 /* now allocate buffer */
1451 Buffer
= AllocateItem(NonPagedPool
, Length
);
1455 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1459 /* copy bus identifier */
1460 wcscpy(Buffer
, BusDeviceExtension
->BusIdentifier
);
1463 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
1465 /* set flag that buffer gets copied back */
1466 Irp
->Flags
|= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
1469 Status
= STATUS_SUCCESS
;
1474 /* no buffer provided */
1475 Status
= STATUS_BUFFER_OVERFLOW
;
1479 Irp
->IoStatus
.Status
= Status
;
1489 KsGetBusEnumParentFDOFromChildPDO(
1490 IN PDEVICE_OBJECT DeviceObject
,
1491 OUT PDEVICE_OBJECT
*FunctionalDeviceObject
)
1493 PDEV_EXTENSION DeviceExtension
;
1495 DPRINT("KsGetBusEnumParentFDOFromChildPDO\n");
1497 /* get device extension */
1498 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1500 /* check if this is child pdo */
1501 if (DeviceExtension
->Ext
->IsBus
== FALSE
)
1503 /* return bus device object */
1504 *FunctionalDeviceObject
= DeviceExtension
->Ext
->BusDeviceExtension
->BusDeviceObject
;
1507 return STATUS_SUCCESS
;
1510 /* invalid parameter */
1511 return STATUS_INVALID_PARAMETER
;
1521 KsCreateBusEnumObject(
1522 IN PWCHAR BusIdentifier
,
1523 IN PDEVICE_OBJECT BusDeviceObject
,
1524 IN PDEVICE_OBJECT PhysicalDeviceObject
,
1525 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL
,
1526 IN REFGUID InterfaceGuid OPTIONAL
,
1527 IN PWCHAR ServiceRelativePath OPTIONAL
)
1530 NTSTATUS Status
= STATUS_SUCCESS
;
1531 UNICODE_STRING ServiceKeyPath
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
1532 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1533 PDEV_EXTENSION DeviceExtension
;
1534 PBUS_DEVICE_ENTRY DeviceEntry
;
1538 DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath
, BusDeviceObject
);
1540 /* calculate sizeof bus enum device extension */
1541 Length
= wcslen(BusIdentifier
) * sizeof(WCHAR
);
1542 Length
+= sizeof(BUS_ENUM_DEVICE_EXTENSION
);
1544 BusDeviceExtension
= AllocateItem(NonPagedPool
, Length
);
1545 if (!BusDeviceExtension
)
1547 /* not enough memory */
1549 return STATUS_INSUFFICIENT_RESOURCES
;
1552 /* get device extension */
1553 DeviceExtension
= (PDEV_EXTENSION
)BusDeviceObject
->DeviceExtension
;
1555 /* store bus device extension */
1556 DeviceExtension
->Ext
= (PCOMMON_DEVICE_EXTENSION
)BusDeviceExtension
;
1558 DPRINT("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1561 /* zero device extension */
1562 RtlZeroMemory(BusDeviceExtension
, sizeof(BUS_ENUM_DEVICE_EXTENSION
));
1564 /* initialize bus device extension */
1565 wcscpy(BusDeviceExtension
->BusIdentifier
, BusIdentifier
);
1567 /* allocate service path string */
1568 Length
= ServiceKeyPath
.MaximumLength
;
1569 Length
+= BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
.MaximumLength
;
1571 if (ServiceRelativePath
)
1573 /* relative path for devices */
1574 Length
+= (wcslen(ServiceRelativePath
) + 2) * sizeof(WCHAR
);
1577 BusDeviceExtension
->ServicePath
.Length
= 0;
1578 BusDeviceExtension
->ServicePath
.MaximumLength
= (USHORT
)Length
;
1579 BusDeviceExtension
->ServicePath
.Buffer
= AllocateItem(NonPagedPool
, Length
);
1581 if (!BusDeviceExtension
->ServicePath
.Buffer
)
1583 /* not enough memory */
1584 FreeItem(BusDeviceExtension
);
1586 return STATUS_INSUFFICIENT_RESOURCES
;
1589 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &ServiceKeyPath
);
1590 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
);
1592 if (ServiceRelativePath
)
1594 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, L
"\\");
1595 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, ServiceRelativePath
);
1600 /* register an device interface */
1601 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
, InterfaceGuid
, NULL
, &BusDeviceExtension
->DeviceInterfaceLink
);
1603 /* check for success */
1604 if (!NT_SUCCESS(Status
))
1606 DPRINT1("IoRegisterDeviceInterface failed Status %lx\n", Status
);
1607 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1608 FreeItem(BusDeviceExtension
);
1612 /* now enable device interface */
1613 Status
= IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, TRUE
);
1615 if (!NT_SUCCESS(Status
))
1617 DPRINT1("IoSetDeviceInterfaceState failed Status %lx\n", Status
);
1618 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1619 FreeItem(BusDeviceExtension
);
1624 /* initialize common device extension */
1625 BusDeviceExtension
->Common
.BusDeviceExtension
= NULL
;
1626 BusDeviceExtension
->Common
.DeviceObjectReferenceCount
= 1;
1627 BusDeviceExtension
->Common
.DeviceReferenceCount
= 1;
1628 BusDeviceExtension
->Common
.IsBus
= TRUE
;
1629 InitializeListHead(&BusDeviceExtension
->Common
.Entry
);
1631 /* store device objects */
1632 BusDeviceExtension
->BusDeviceObject
= BusDeviceObject
;
1633 BusDeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
1635 /* initialize lock */
1636 KeInitializeSpinLock(&BusDeviceExtension
->Lock
);
1638 /* initialize timer */
1639 KeInitializeTimer(&BusDeviceExtension
->Timer
);
1641 /* initialize dpc */
1642 KeInitializeDpc(&BusDeviceExtension
->Dpc
, KspBusDpcRoutine
, (PVOID
)BusDeviceExtension
);
1644 /* initialize event */
1645 KeInitializeEvent(&BusDeviceExtension
->Event
, SynchronizationEvent
, FALSE
);
1647 /* initialize work item */
1648 ExInitializeWorkItem(&BusDeviceExtension
->WorkItem
, KspBusWorkerRoutine
, (PVOID
)BusDeviceExtension
);
1650 if (!PnpDeviceObject
)
1653 BusDeviceExtension
->PnpDeviceObject
= IoAttachDeviceToDeviceStack(BusDeviceObject
, PhysicalDeviceObject
);
1655 if (!BusDeviceExtension
->PnpDeviceObject
)
1657 /* failed to attach device */
1658 DPRINT1("IoAttachDeviceToDeviceStack failed with %x\n", Status
);
1659 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1661 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1662 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1665 /* free device extension */
1666 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1667 FreeItem(BusDeviceExtension
);
1669 return STATUS_DEVICE_REMOVED
;
1672 /* mark device as attached */
1673 BusDeviceExtension
->DeviceAttached
= TRUE
;
1677 /* directly attach */
1678 BusDeviceExtension
->PnpDeviceObject
= PnpDeviceObject
;
1681 /* now scan the bus */
1682 Status
= KspScanBus(BusDeviceExtension
);
1684 /* check for success */
1685 if (!NT_SUCCESS(Status
))
1687 /* failed to scan bus */
1688 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1690 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1691 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1694 if (BusDeviceExtension
->DeviceAttached
)
1697 IoDetachDevice(BusDeviceExtension
->PnpDeviceObject
);
1700 /* free device extension */
1701 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1702 FreeItem(BusDeviceExtension
);
1707 /* acquire device entry lock */
1708 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1710 /* now iterate all device entries */
1711 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1712 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1714 /* get device entry */
1715 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1716 if (!DeviceEntry
->PDO
)
1718 /* release device entry lock */
1719 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1722 Status
= KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1724 /* acquire device entry lock */
1725 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1730 /* move to next entry */
1731 Entry
= Entry
->Flink
;
1734 /* release device entry lock */
1735 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1738 /* invalidate device relations */
1739 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1740 DPRINT("KsCreateBusEnumObject Status %x\n", Status
);
1751 KsGetBusEnumPnpDeviceObject(
1752 IN PDEVICE_OBJECT DeviceObject
,
1753 IN PDEVICE_OBJECT
*PnpDeviceObject
)
1755 PDEV_EXTENSION DeviceExtension
;
1756 PCOMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1757 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1759 DPRINT("KsGetBusEnumPnpDeviceObject\n");
1761 if (!DeviceObject
->DeviceExtension
)
1763 /* invalid parameter */
1764 return STATUS_INVALID_PARAMETER
;
1767 /* get device extension */
1768 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1770 /* get common device extension */
1771 CommonDeviceExtension
= DeviceExtension
->Ext
;
1773 if (!CommonDeviceExtension
)
1775 /* invalid parameter */
1776 return STATUS_INVALID_PARAMETER
;
1779 if (!CommonDeviceExtension
->IsBus
)
1781 /* getting pnp device object is only supported for software bus device object */
1782 return STATUS_INVALID_PARAMETER
;
1786 ASSERT(CommonDeviceExtension
);
1787 ASSERT(CommonDeviceExtension
->IsBus
);
1789 /* cast to bus device extension */
1790 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)CommonDeviceExtension
;
1793 *PnpDeviceObject
= BusDeviceExtension
->PnpDeviceObject
;
1796 return STATUS_SUCCESS
;
1805 KsInstallBusEnumInterface(
1808 BUS_INSTALL_ENUM_CONTEXT Context
;
1809 KPROCESSOR_MODE Mode
;
1811 PIO_STACK_LOCATION IoStack
;
1812 PDEV_EXTENSION DeviceExtension
;
1813 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1815 DPRINT("KsInstallBusEnumInterface\n");
1817 /* get current irp stack location */
1818 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1820 /* get previous mode */
1821 Mode
= ExGetPreviousMode();
1823 /* convert to luid */
1824 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
1826 /* perform access check */
1827 if (!SeSinglePrivilegeCheck(luid
, Mode
))
1829 /* FIXME insufficient privileges */
1830 //return STATUS_PRIVILEGE_NOT_HELD;
1833 /* get device extension */
1834 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1836 /* get bus device extension */
1837 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1840 /* initialize context */
1842 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
1843 Context
.BusDeviceExtension
= BusDeviceExtension
;
1844 ExInitializeWorkItem(&Context
.WorkItem
, KspInstallBusEnumInterface
, (PVOID
)&Context
);
1846 /* queue the work item */
1847 ExQueueWorkItem(&Context
.WorkItem
, DelayedWorkQueue
);
1848 /* wait for completion */
1849 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
1852 Irp
->IoStatus
.Status
= Context
.Status
;
1855 return Context
.Status
;
1864 KsIsBusEnumChildDevice(
1865 IN PDEVICE_OBJECT DeviceObject
,
1866 OUT PBOOLEAN ChildDevice
)
1868 PDEV_EXTENSION DeviceExtension
;
1869 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1871 DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject
);
1873 /* get device extension */
1874 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1876 /* get bus device extension */
1877 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1879 if (!BusDeviceExtension
)
1881 /* not a bus device */
1882 return STATUS_INVALID_PARAMETER
;
1886 *ChildDevice
= (BusDeviceExtension
->Common
.IsBus
== FALSE
);
1888 return STATUS_SUCCESS
;
1897 KsServiceBusEnumCreateRequest(
1898 IN PDEVICE_OBJECT DeviceObject
,
1902 PBUS_DEVICE_ENTRY DeviceEntry
= NULL
; /* fix gcc */
1903 PIO_STACK_LOCATION IoStack
;
1904 BOOLEAN ItemExists
= FALSE
;
1905 PDEV_EXTENSION DeviceExtension
;
1906 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1907 //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension;
1913 /* get device extension */
1914 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1916 /* get bus device extension */
1917 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1919 /* get current irp stack location */
1920 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1923 ASSERT(IoStack
->FileObject
);
1924 if (IoStack
->FileObject
->FileName
.Buffer
== NULL
)
1926 DPRINT("KsServiceBusEnumCreateRequest PNP Hack\n");
1927 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1928 return STATUS_SUCCESS
;
1931 ASSERT(IoStack
->FileObject
->FileName
.Buffer
);
1933 DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1935 /* scan list and check if it is already present */
1936 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1938 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1940 /* get real offset */
1941 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1943 /* check if name matches */
1944 if (!wcsicmp(DeviceEntry
->DeviceName
, IoStack
->FileObject
->FileName
.Buffer
+ 1))
1946 /* item already exists */
1951 /* move to next entry */
1952 Entry
= Entry
->Flink
;
1957 /* interface not registered */
1958 DPRINT1("Interface %wZ not registered\n", &IoStack
->FileObject
->FileName
);
1959 return STATUS_OBJECT_NAME_NOT_FOUND
;
1962 /* is there a pdo yet */
1963 if (DeviceEntry
->PDO
)
1965 if (DeviceEntry
->DeviceState
== Started
)
1968 Status
= KspDoReparseForIrp(Irp
, DeviceEntry
);
1969 DPRINT("REPARSE Irp %p '%wZ'\n", Irp
, &IoStack
->FileObject
->FileName
);
1971 Irp
->IoStatus
.Status
= Status
;
1972 Irp
->IoStatus
.Information
= IO_REPARSE
;
1976 /* delay processing until pnp is finished with enumeration */
1977 IoMarkIrpPending(Irp
);
1979 /* insert into irp pending list */
1980 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1982 Time
.QuadPart
= Int32x32To64(1500, -10000);
1983 DbgPrint("PENDING Irp %p %wZ DeviceState %d\n", Irp
, &IoStack
->FileObject
->FileName
, DeviceEntry
->DeviceState
);
1987 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1990 return STATUS_PENDING
;
1995 /* time to create PDO */
1996 Status
= KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1998 if (!NT_SUCCESS(Status
))
2000 /* failed to create PDO */
2001 DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status
);
2004 DPRINT("PENDING CREATE Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
2006 /* delay processing until pnp is finished with enumeration */
2007 IoMarkIrpPending(Irp
);
2009 /* insert into irp pending list */
2010 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
2012 /* invalidate device relations */
2013 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
2016 return STATUS_PENDING
;
2026 KsServiceBusEnumPnpRequest(
2027 IN PDEVICE_OBJECT DeviceObject
,
2030 PDEV_EXTENSION DeviceExtension
;
2031 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
2032 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
;
2033 PIO_STACK_LOCATION IoStack
;
2036 PDEVICE_RELATIONS DeviceRelation
;
2037 PBUS_DEVICE_ENTRY DeviceEntry
;
2039 /* get device extension */
2040 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
2042 /* get bus device extension */
2043 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
2045 /* get current irp stack location */
2046 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2048 if (BusDeviceExtension
->Common
.IsBus
)
2050 if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
2052 /* no op for bus driver */
2053 Status
= STATUS_SUCCESS
;
2055 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
)
2057 /* handle bus device relations */
2058 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== BusRelations
);
2060 Status
= KspQueryBusRelations(BusDeviceExtension
, Irp
);
2064 /* get default status */
2065 Status
= Irp
->IoStatus
.Status
;
2070 /* get child device extension */
2071 ChildDeviceExtension
= DeviceExtension
->Ext
;
2073 /* get bus device extension */
2074 BusDeviceExtension
= ChildDeviceExtension
->BusDeviceExtension
;
2076 if (IoStack
->MinorFunction
== IRP_MN_QUERY_ID
)
2079 Status
= KspQueryId(ChildDeviceExtension
, Irp
);
2081 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
2083 ASSERT(ChildDeviceExtension
->DeviceEntry
->DeviceState
!= Started
|| ChildDeviceExtension
->DeviceEntry
->DeviceState
== NotStarted
);
2084 ASSERT(ChildDeviceExtension
->DeviceEntry
->PDO
== DeviceObject
);
2086 /* backup device entry */
2087 DeviceEntry
= ChildDeviceExtension
->DeviceEntry
;
2089 /* free device extension */
2090 FreeItem(ChildDeviceExtension
);
2092 /* clear PDO reference */
2093 DeviceEntry
->PDO
= NULL
;
2095 /* delete the device */
2096 IoDeleteDevice(DeviceObject
);
2098 if (DeviceEntry
->PDODeviceName
)
2100 /* delete pdo device name */
2101 FreeItem(DeviceEntry
->PDODeviceName
);
2104 DeviceEntry
->PDODeviceName
= NULL
;
2107 /* set state no notstarted */
2108 DeviceEntry
->DeviceState
= NotStarted
;
2110 /* complete pending irps */
2111 KspCompletePendingIrps(DeviceEntry
, STATUS_DEVICE_REMOVED
);
2114 Status
= STATUS_SUCCESS
;
2116 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_BUS_INFORMATION
)
2118 /* query bus information */
2119 Status
= KspQueryBusInformation(ChildDeviceExtension
, Irp
);
2121 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCES
)
2124 Status
= STATUS_SUCCESS
;
2126 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCE_REQUIREMENTS
)
2129 Status
= STATUS_SUCCESS
;
2131 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
2134 Status
= KspStartBusDevice(DeviceObject
, ChildDeviceExtension
, Irp
);
2135 if (NT_SUCCESS(Status
))
2137 /* complete pending irps*/
2138 KspCompletePendingIrps(ChildDeviceExtension
->DeviceEntry
, STATUS_REPARSE
);
2142 Time
.QuadPart
= Int32x32To64(1500, -10000);
2145 ASSERT(BusDeviceExtension
);
2148 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
2150 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_CAPABILITIES
)
2152 /* query capabilities */
2153 Status
= KspQueryBusDeviceCapabilities(ChildDeviceExtension
, Irp
);
2155 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
2157 /* query pnp state */
2158 Status
= KspQueryBusDevicePnpState(ChildDeviceExtension
, Irp
);
2160 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_INTERFACE
)
2162 /* query interface */
2163 Status
= KspQueryBusDeviceInterface(ChildDeviceExtension
, Irp
);
2165 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
&& IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
2167 /* handle target device relations */
2168 ASSERT(Irp
->IoStatus
.Information
== 0);
2170 /* allocate device relation */
2171 DeviceRelation
= AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
));
2174 DeviceRelation
->Count
= 1;
2175 DeviceRelation
->Objects
[0] = DeviceObject
;
2177 /* reference self */
2178 ObReferenceObject(DeviceObject
);
2181 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelation
;
2184 Status
= STATUS_SUCCESS
;
2189 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2194 /* get default status */
2195 Status
= Irp
->IoStatus
.Status
;
2199 DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject
, BusDeviceExtension
->Common
.IsBus
, IoStack
->MinorFunction
, Status
);
2200 Irp
->IoStatus
.Status
= Status
;
2210 KsRemoveBusEnumInterface(
2213 KPROCESSOR_MODE Mode
;
2215 BUS_INSTALL_ENUM_CONTEXT Ctx
;
2216 PDEV_EXTENSION DeviceExtension
;
2217 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
2218 PIO_STACK_LOCATION IoStack
;
2220 DPRINT("KsRemoveBusEnumInterface\n");
2222 /* get io stack location */
2223 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2225 /* get device extension */
2226 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
2228 /* get bus device extension */
2229 BusDeviceExtension
= DeviceExtension
->Ext
->BusDeviceExtension
;
2231 /* get previous mode */
2232 Mode
= ExGetPreviousMode();
2234 /* convert to luid */
2235 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
2237 /* perform access check */
2238 if (!SeSinglePrivilegeCheck(luid
, Mode
))
2240 /* insufficient privileges */
2241 return STATUS_PRIVILEGE_NOT_HELD
;
2244 /* initialize context */
2245 KeInitializeEvent(&Ctx
.Event
, NotificationEvent
, FALSE
);
2247 Ctx
.BusDeviceExtension
= BusDeviceExtension
;
2248 ExInitializeWorkItem(&Ctx
.WorkItem
, KspRemoveBusInterface
, (PVOID
)&Ctx
);
2250 /* now queue the work item */
2251 ExQueueWorkItem(&Ctx
.WorkItem
, DelayedWorkQueue
);
2253 /* wait for completion */
2254 KeWaitForSingleObject(&Ctx
.Event
, Executive
, KernelMode
, FALSE
, NULL
);