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 KeQuerySystemTime(&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 KeQuerySystemTime(&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 KeQuerySystemTime(&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
;
1216 if (Diff
.QuadPart
> Int32x32To64(15000, 10000))
1218 /* release spin lock */
1219 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1221 DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry
->DeviceName
, DeviceEntry
->Instance
, DeviceEntry
->TimeCreated
.QuadPart
, Time
.QuadPart
, Diff
.QuadPart
);
1223 /* deactivate interfaces */
1224 //KspEnableBusDeviceInterface(DeviceEntry, FALSE);
1226 /* re-acquire lock */
1227 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1229 /* pending remove device object */
1230 DeviceEntry
->DeviceState
= StopPending
;
1232 /* perform invalidation */
1233 DoInvalidate
= TRUE
;
1236 else if (DeviceEntry
->DeviceState
== Started
)
1238 /* release spin lock */
1239 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1241 /* found pending irps */
1242 KspCompletePendingIrps(DeviceEntry
, STATUS_REPARSE
);
1244 /* re-acquire lock */
1245 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1251 Entry
= Entry
->Flink
;
1255 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1259 /* invalidate device relations */
1260 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1263 Time
.QuadPart
= Int32x32To64(5000, -10000);
1264 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1271 IN PVOID DeferredContext OPTIONAL
,
1272 IN PVOID SystemArgument1 OPTIONAL
,
1273 IN PVOID SystemArgument2 OPTIONAL
)
1275 /* get device extension */
1276 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeferredContext
;
1278 /* queue the item */
1279 ExQueueWorkItem(&BusDeviceExtension
->WorkItem
, DelayedWorkQueue
);
1284 KspRemoveBusInterface(
1287 PBUS_INSTALL_ENUM_CONTEXT Context
=(PBUS_INSTALL_ENUM_CONTEXT
)Ctx
;
1290 * get SWENUM_INSTALL_INTERFACE struct
1291 * open device key and delete the keys
1297 Context
->Status
= STATUS_NOT_IMPLEMENTED
;
1300 /* signal completion */
1301 KeSetEvent(&Context
->Event
, IO_NO_INCREMENT
, FALSE
);
1305 KspQueryBusRelations(
1306 IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
,
1309 PDEVICE_RELATIONS DeviceRelations
;
1311 PBUS_DEVICE_ENTRY DeviceEntry
;
1312 ULONG Count
= 0, Length
;
1316 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1318 /* first scan all device entries */
1319 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1321 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1323 /* get offset to device entry */
1324 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1326 /* is there a pdo yet */
1327 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1329 /* increment count */
1333 /* move to next entry */
1334 Entry
= Entry
->Flink
;
1337 /* calculate length */
1338 Length
= sizeof(DEVICE_RELATIONS
) + (Count
> 1 ? sizeof(PDEVICE_OBJECT
) * (Count
-1) : 0);
1340 /* allocate device relations */
1341 DeviceRelations
= (PDEVICE_RELATIONS
)AllocateItem(NonPagedPool
, Length
);
1343 if (!DeviceRelations
)
1345 /* not enough memory */
1346 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1347 return STATUS_INSUFFICIENT_RESOURCES
;
1350 /* rescan device entries */
1351 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1353 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1355 /* get offset to device entry */
1356 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1358 /* is there a pdo yet */
1359 if (DeviceEntry
->PDO
&& (DeviceEntry
->DeviceState
== NotStarted
|| DeviceEntry
->DeviceState
== Started
))
1362 DeviceRelations
->Objects
[DeviceRelations
->Count
] = DeviceEntry
->PDO
;
1364 /* reference device object */
1365 ObReferenceObject(DeviceEntry
->PDO
);
1367 /* increment pdo count */
1368 DeviceRelations
->Count
++;
1371 /* move to next entry */
1372 Entry
= Entry
->Flink
;
1376 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1378 /* FIXME handle existing device relations */
1379 ASSERT(Irp
->IoStatus
.Information
== 0);
1381 /* store device relations */
1382 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
1385 return STATUS_SUCCESS
;
1388 //------------------------------------------------------------------------------------
1397 KsGetBusEnumIdentifier(
1400 PDEV_EXTENSION DeviceExtension
;
1401 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1402 PIO_STACK_LOCATION IoStack
;
1407 DPRINT("KsGetBusEnumIdentifier\n");
1409 /* get stack location */
1410 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1413 ASSERT(IoStack
->DeviceObject
);
1414 ASSERT(IoStack
->DeviceObject
->DeviceExtension
);
1416 /* get device extension */
1417 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1419 /* get bus device extension */
1420 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1423 ASSERT(BusDeviceExtension
);
1424 ASSERT(BusDeviceExtension
->Common
.IsBus
);
1426 if (!BusDeviceExtension
)
1428 /* invalid parameter */
1429 return STATUS_INVALID_PARAMETER
;
1433 Length
= (wcslen(BusDeviceExtension
->BusIdentifier
)+1) * sizeof(WCHAR
);
1435 /* is there an output buffer provided */
1436 if (IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1438 if (Length
> IoStack
->Parameters
.DeviceIoControl
.InputBufferLength
)
1440 /* buffer is too small */
1441 return STATUS_BUFFER_TOO_SMALL
;
1444 /* now allocate buffer */
1445 Buffer
= AllocateItem(NonPagedPool
, Length
);
1449 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1453 /* copy bus identifier */
1454 wcscpy(Buffer
, BusDeviceExtension
->BusIdentifier
);
1457 Irp
->AssociatedIrp
.SystemBuffer
= Buffer
;
1459 /* set flag that buffer gets copied back */
1460 Irp
->Flags
|= IRP_BUFFERED_IO
| IRP_DEALLOCATE_BUFFER
| IRP_INPUT_OPERATION
;
1463 Status
= STATUS_SUCCESS
;
1468 /* no buffer provided */
1469 Status
= STATUS_BUFFER_OVERFLOW
;
1473 Irp
->IoStatus
.Status
= Status
;
1483 KsGetBusEnumParentFDOFromChildPDO(
1484 IN PDEVICE_OBJECT DeviceObject
,
1485 OUT PDEVICE_OBJECT
*FunctionalDeviceObject
)
1487 PDEV_EXTENSION DeviceExtension
;
1489 DPRINT("KsGetBusEnumParentFDOFromChildPDO\n");
1491 /* get device extension */
1492 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1494 /* check if this is child pdo */
1495 if (DeviceExtension
->Ext
->IsBus
== FALSE
)
1497 /* return bus device object */
1498 *FunctionalDeviceObject
= DeviceExtension
->Ext
->BusDeviceExtension
->BusDeviceObject
;
1501 return STATUS_SUCCESS
;
1504 /* invalid parameter */
1505 return STATUS_INVALID_PARAMETER
;
1515 KsCreateBusEnumObject(
1516 IN PWCHAR BusIdentifier
,
1517 IN PDEVICE_OBJECT BusDeviceObject
,
1518 IN PDEVICE_OBJECT PhysicalDeviceObject
,
1519 IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL
,
1520 IN REFGUID InterfaceGuid OPTIONAL
,
1521 IN PWCHAR ServiceRelativePath OPTIONAL
)
1524 NTSTATUS Status
= STATUS_SUCCESS
;
1525 UNICODE_STRING ServiceKeyPath
= RTL_CONSTANT_STRING(L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
1526 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1527 PDEV_EXTENSION DeviceExtension
;
1528 PBUS_DEVICE_ENTRY DeviceEntry
;
1532 DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath
, BusDeviceObject
);
1534 /* calculate sizeof bus enum device extension */
1535 Length
= wcslen(BusIdentifier
) * sizeof(WCHAR
);
1536 Length
+= sizeof(BUS_ENUM_DEVICE_EXTENSION
);
1538 BusDeviceExtension
= AllocateItem(NonPagedPool
, Length
);
1539 if (!BusDeviceExtension
)
1541 /* not enough memory */
1543 return STATUS_INSUFFICIENT_RESOURCES
;
1546 /* get device extension */
1547 DeviceExtension
= (PDEV_EXTENSION
)BusDeviceObject
->DeviceExtension
;
1549 /* store bus device extension */
1550 DeviceExtension
->Ext
= (PCOMMON_DEVICE_EXTENSION
)BusDeviceExtension
;
1552 DPRINT("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension
, DeviceExtension
->Ext
);
1555 /* zero device extension */
1556 RtlZeroMemory(BusDeviceExtension
, sizeof(BUS_ENUM_DEVICE_EXTENSION
));
1558 /* initialize bus device extension */
1559 wcscpy(BusDeviceExtension
->BusIdentifier
, BusIdentifier
);
1561 /* allocate service path string */
1562 Length
= ServiceKeyPath
.MaximumLength
;
1563 Length
+= BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
.MaximumLength
;
1565 if (ServiceRelativePath
)
1567 /* relative path for devices */
1568 Length
+= (wcslen(ServiceRelativePath
) + 2) * sizeof(WCHAR
);
1571 BusDeviceExtension
->ServicePath
.Length
= 0;
1572 BusDeviceExtension
->ServicePath
.MaximumLength
= (USHORT
)Length
;
1573 BusDeviceExtension
->ServicePath
.Buffer
= AllocateItem(NonPagedPool
, Length
);
1575 if (!BusDeviceExtension
->ServicePath
.Buffer
)
1577 /* not enough memory */
1578 FreeItem(BusDeviceExtension
);
1580 return STATUS_INSUFFICIENT_RESOURCES
;
1583 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &ServiceKeyPath
);
1584 RtlAppendUnicodeStringToString(&BusDeviceExtension
->ServicePath
, &BusDeviceObject
->DriverObject
->DriverExtension
->ServiceKeyName
);
1586 if (ServiceRelativePath
)
1588 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, L
"\\");
1589 RtlAppendUnicodeToString(&BusDeviceExtension
->ServicePath
, ServiceRelativePath
);
1594 /* register an device interface */
1595 Status
= IoRegisterDeviceInterface(PhysicalDeviceObject
, InterfaceGuid
, NULL
, &BusDeviceExtension
->DeviceInterfaceLink
);
1597 /* check for success */
1598 if (!NT_SUCCESS(Status
))
1600 DPRINT1("IoRegisterDeviceInterface failed Status %lx\n", Status
);
1601 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1602 FreeItem(BusDeviceExtension
);
1606 /* now enable device interface */
1607 Status
= IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, TRUE
);
1609 if (!NT_SUCCESS(Status
))
1611 DPRINT1("IoSetDeviceInterfaceState failed Status %lx\n", Status
);
1612 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1613 FreeItem(BusDeviceExtension
);
1618 /* initialize common device extension */
1619 BusDeviceExtension
->Common
.BusDeviceExtension
= NULL
;
1620 BusDeviceExtension
->Common
.DeviceObjectReferenceCount
= 1;
1621 BusDeviceExtension
->Common
.DeviceReferenceCount
= 1;
1622 BusDeviceExtension
->Common
.IsBus
= TRUE
;
1623 InitializeListHead(&BusDeviceExtension
->Common
.Entry
);
1625 /* store device objects */
1626 BusDeviceExtension
->BusDeviceObject
= BusDeviceObject
;
1627 BusDeviceExtension
->PhysicalDeviceObject
= PhysicalDeviceObject
;
1629 /* initialize lock */
1630 KeInitializeSpinLock(&BusDeviceExtension
->Lock
);
1632 /* initialize timer */
1633 KeInitializeTimer(&BusDeviceExtension
->Timer
);
1635 /* initialize dpc */
1636 KeInitializeDpc(&BusDeviceExtension
->Dpc
, KspBusDpcRoutine
, (PVOID
)BusDeviceExtension
);
1638 /* initialize event */
1639 KeInitializeEvent(&BusDeviceExtension
->Event
, SynchronizationEvent
, FALSE
);
1641 /* initialize work item */
1642 ExInitializeWorkItem(&BusDeviceExtension
->WorkItem
, KspBusWorkerRoutine
, (PVOID
)BusDeviceExtension
);
1644 if (!PnpDeviceObject
)
1647 BusDeviceExtension
->PnpDeviceObject
= IoAttachDeviceToDeviceStack(BusDeviceObject
, PhysicalDeviceObject
);
1649 if (!BusDeviceExtension
->PnpDeviceObject
)
1651 /* failed to attach device */
1652 DPRINT1("IoAttachDeviceToDeviceStack failed with %x\n", Status
);
1653 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1655 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1656 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1659 /* free device extension */
1660 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1661 FreeItem(BusDeviceExtension
);
1663 return STATUS_DEVICE_REMOVED
;
1666 /* mark device as attached */
1667 BusDeviceExtension
->DeviceAttached
= TRUE
;
1671 /* directly attach */
1672 BusDeviceExtension
->PnpDeviceObject
= PnpDeviceObject
;
1675 /* now scan the bus */
1676 Status
= KspScanBus(BusDeviceExtension
);
1678 /* check for success */
1679 if (!NT_SUCCESS(Status
))
1681 /* failed to scan bus */
1682 if (BusDeviceExtension
->DeviceInterfaceLink
.Buffer
)
1684 IoSetDeviceInterfaceState(&BusDeviceExtension
->DeviceInterfaceLink
, FALSE
);
1685 RtlFreeUnicodeString(&BusDeviceExtension
->DeviceInterfaceLink
);
1688 if (BusDeviceExtension
->DeviceAttached
)
1691 IoDetachDevice(BusDeviceExtension
->PnpDeviceObject
);
1694 /* free device extension */
1695 FreeItem(BusDeviceExtension
->ServicePath
.Buffer
);
1696 FreeItem(BusDeviceExtension
);
1701 /* acquire device entry lock */
1702 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1704 /* now iterate all device entries */
1705 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1706 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1708 /* get device entry */
1709 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1710 if (!DeviceEntry
->PDO
)
1712 /* release device entry lock */
1713 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1716 Status
= KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1718 /* acquire device entry lock */
1719 KeAcquireSpinLock(&BusDeviceExtension
->Lock
, &OldLevel
);
1724 /* move to next entry */
1725 Entry
= Entry
->Flink
;
1728 /* release device entry lock */
1729 KeReleaseSpinLock(&BusDeviceExtension
->Lock
, OldLevel
);
1732 /* invalidate device relations */
1733 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
1734 DPRINT("KsCreateBusEnumObject Status %x\n", Status
);
1745 KsGetBusEnumPnpDeviceObject(
1746 IN PDEVICE_OBJECT DeviceObject
,
1747 IN PDEVICE_OBJECT
*PnpDeviceObject
)
1749 PDEV_EXTENSION DeviceExtension
;
1750 PCOMMON_DEVICE_EXTENSION CommonDeviceExtension
;
1751 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1753 DPRINT("KsGetBusEnumPnpDeviceObject\n");
1755 if (!DeviceObject
->DeviceExtension
)
1757 /* invalid parameter */
1758 return STATUS_INVALID_PARAMETER
;
1761 /* get device extension */
1762 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1764 /* get common device extension */
1765 CommonDeviceExtension
= DeviceExtension
->Ext
;
1767 if (!CommonDeviceExtension
)
1769 /* invalid parameter */
1770 return STATUS_INVALID_PARAMETER
;
1773 if (!CommonDeviceExtension
->IsBus
)
1775 /* getting pnp device object is only supported for software bus device object */
1776 return STATUS_INVALID_PARAMETER
;
1780 ASSERT(CommonDeviceExtension
);
1781 ASSERT(CommonDeviceExtension
->IsBus
);
1783 /* cast to bus device extension */
1784 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)CommonDeviceExtension
;
1787 *PnpDeviceObject
= BusDeviceExtension
->PnpDeviceObject
;
1790 return STATUS_SUCCESS
;
1799 KsInstallBusEnumInterface(
1802 BUS_INSTALL_ENUM_CONTEXT Context
;
1803 KPROCESSOR_MODE Mode
;
1805 PIO_STACK_LOCATION IoStack
;
1806 PDEV_EXTENSION DeviceExtension
;
1807 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1809 DPRINT("KsInstallBusEnumInterface\n");
1811 /* get current irp stack location */
1812 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1814 /* get previous mode */
1815 Mode
= ExGetPreviousMode();
1817 /* convert to luid */
1818 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
1820 /* perform access check */
1821 if (!SeSinglePrivilegeCheck(luid
, Mode
))
1823 /* FIXME insufficient privileges */
1824 //return STATUS_PRIVILEGE_NOT_HELD;
1827 /* get device extension */
1828 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
1830 /* get bus device extension */
1831 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1834 /* initialize context */
1836 KeInitializeEvent(&Context
.Event
, NotificationEvent
, FALSE
);
1837 Context
.BusDeviceExtension
= BusDeviceExtension
;
1838 ExInitializeWorkItem(&Context
.WorkItem
, KspInstallBusEnumInterface
, (PVOID
)&Context
);
1840 /* queue the work item */
1841 ExQueueWorkItem(&Context
.WorkItem
, DelayedWorkQueue
);
1842 /* wait for completion */
1843 KeWaitForSingleObject(&Context
.Event
, Executive
, KernelMode
, FALSE
, NULL
);
1846 Irp
->IoStatus
.Status
= Context
.Status
;
1849 return Context
.Status
;
1858 KsIsBusEnumChildDevice(
1859 IN PDEVICE_OBJECT DeviceObject
,
1860 OUT PBOOLEAN ChildDevice
)
1862 PDEV_EXTENSION DeviceExtension
;
1863 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1865 DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject
);
1867 /* get device extension */
1868 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1870 /* get bus device extension */
1871 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1873 if (!BusDeviceExtension
)
1875 /* not a bus device */
1876 return STATUS_INVALID_PARAMETER
;
1880 *ChildDevice
= (BusDeviceExtension
->Common
.IsBus
== FALSE
);
1882 return STATUS_SUCCESS
;
1891 KsServiceBusEnumCreateRequest(
1892 IN PDEVICE_OBJECT DeviceObject
,
1896 PBUS_DEVICE_ENTRY DeviceEntry
= NULL
; /* fix gcc */
1897 PIO_STACK_LOCATION IoStack
;
1898 BOOLEAN ItemExists
= FALSE
;
1899 PDEV_EXTENSION DeviceExtension
;
1900 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
1901 //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension;
1907 /* get device extension */
1908 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
1910 /* get bus device extension */
1911 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
1913 /* get current irp stack location */
1914 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
1917 ASSERT(IoStack
->FileObject
);
1918 if (IoStack
->FileObject
->FileName
.Buffer
== NULL
)
1920 DPRINT("KsServiceBusEnumCreateRequest PNP Hack\n");
1921 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1922 return STATUS_SUCCESS
;
1925 ASSERT(IoStack
->FileObject
->FileName
.Buffer
);
1927 DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
1929 /* scan list and check if it is already present */
1930 Entry
= BusDeviceExtension
->Common
.Entry
.Flink
;
1932 while(Entry
!= &BusDeviceExtension
->Common
.Entry
)
1934 /* get real offset */
1935 DeviceEntry
= (PBUS_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, BUS_DEVICE_ENTRY
, Entry
);
1937 /* check if name matches */
1938 if (!wcsicmp(DeviceEntry
->DeviceName
, IoStack
->FileObject
->FileName
.Buffer
+ 1))
1940 /* item already exists */
1945 /* move to next entry */
1946 Entry
= Entry
->Flink
;
1951 /* interface not registered */
1952 DPRINT1("Interface %wZ not registered\n", &IoStack
->FileObject
->FileName
);
1953 return STATUS_OBJECT_NAME_NOT_FOUND
;
1956 /* is there a pdo yet */
1957 if (DeviceEntry
->PDO
)
1959 if (DeviceEntry
->DeviceState
== Started
)
1962 Status
= KspDoReparseForIrp(Irp
, DeviceEntry
);
1963 DPRINT("REPARSE Irp %p '%wZ'\n", Irp
, &IoStack
->FileObject
->FileName
);
1965 Irp
->IoStatus
.Status
= Status
;
1966 Irp
->IoStatus
.Information
= IO_REPARSE
;
1970 /* delay processing until pnp is finished with enumeration */
1971 IoMarkIrpPending(Irp
);
1973 /* insert into irp pending list */
1974 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
1976 Time
.QuadPart
= Int32x32To64(1500, -10000);
1977 DbgPrint("PENDING Irp %p %wZ DeviceState %d\n", Irp
, &IoStack
->FileObject
->FileName
, DeviceEntry
->DeviceState
);
1981 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
1984 return STATUS_PENDING
;
1989 /* time to create PDO */
1990 Status
= KspCreatePDO(BusDeviceExtension
, DeviceEntry
, &DeviceEntry
->PDO
);
1992 if (!NT_SUCCESS(Status
))
1994 /* failed to create PDO */
1995 DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status
);
1998 DPRINT("PENDING CREATE Irp %p %wZ\n", Irp
, &IoStack
->FileObject
->FileName
);
2000 /* delay processing until pnp is finished with enumeration */
2001 IoMarkIrpPending(Irp
);
2003 /* insert into irp pending list */
2004 InsertTailList(&DeviceEntry
->IrpPendingList
, &Irp
->Tail
.Overlay
.ListEntry
);
2006 /* invalidate device relations */
2007 IoInvalidateDeviceRelations(BusDeviceExtension
->PhysicalDeviceObject
, BusRelations
);
2010 return STATUS_PENDING
;
2020 KsServiceBusEnumPnpRequest(
2021 IN PDEVICE_OBJECT DeviceObject
,
2024 PDEV_EXTENSION DeviceExtension
;
2025 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
2026 PCOMMON_DEVICE_EXTENSION ChildDeviceExtension
;
2027 PIO_STACK_LOCATION IoStack
;
2030 PDEVICE_RELATIONS DeviceRelation
;
2031 PBUS_DEVICE_ENTRY DeviceEntry
;
2033 /* get device extension */
2034 DeviceExtension
= (PDEV_EXTENSION
)DeviceObject
->DeviceExtension
;
2036 /* get bus device extension */
2037 BusDeviceExtension
= (PBUS_ENUM_DEVICE_EXTENSION
)DeviceExtension
->Ext
;
2039 /* get current irp stack location */
2040 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2042 if (BusDeviceExtension
->Common
.IsBus
)
2044 if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
2046 /* no op for bus driver */
2047 Status
= STATUS_SUCCESS
;
2049 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
)
2051 /* handle bus device relations */
2052 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== BusRelations
);
2054 Status
= KspQueryBusRelations(BusDeviceExtension
, Irp
);
2058 /* get default status */
2059 Status
= Irp
->IoStatus
.Status
;
2064 /* get child device extension */
2065 ChildDeviceExtension
= DeviceExtension
->Ext
;
2067 /* get bus device extension */
2068 BusDeviceExtension
= ChildDeviceExtension
->BusDeviceExtension
;
2070 if (IoStack
->MinorFunction
== IRP_MN_QUERY_ID
)
2073 Status
= KspQueryId(ChildDeviceExtension
, Irp
);
2075 else if (IoStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
2077 ASSERT(ChildDeviceExtension
->DeviceEntry
->DeviceState
!= Started
|| ChildDeviceExtension
->DeviceEntry
->DeviceState
== NotStarted
);
2078 ASSERT(ChildDeviceExtension
->DeviceEntry
->PDO
== DeviceObject
);
2080 /* backup device entry */
2081 DeviceEntry
= ChildDeviceExtension
->DeviceEntry
;
2083 /* free device extension */
2084 FreeItem(ChildDeviceExtension
);
2086 /* clear PDO reference */
2087 DeviceEntry
->PDO
= NULL
;
2089 /* delete the device */
2090 IoDeleteDevice(DeviceObject
);
2092 if (DeviceEntry
->PDODeviceName
)
2094 /* delete pdo device name */
2095 FreeItem(DeviceEntry
->PDODeviceName
);
2098 DeviceEntry
->PDODeviceName
= NULL
;
2101 /* set state no notstarted */
2102 DeviceEntry
->DeviceState
= NotStarted
;
2104 /* complete pending irps */
2105 KspCompletePendingIrps(DeviceEntry
, STATUS_DEVICE_REMOVED
);
2108 Status
= STATUS_SUCCESS
;
2110 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_BUS_INFORMATION
)
2112 /* query bus information */
2113 Status
= KspQueryBusInformation(ChildDeviceExtension
, Irp
);
2115 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCES
)
2118 Status
= STATUS_SUCCESS
;
2120 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_RESOURCE_REQUIREMENTS
)
2123 Status
= STATUS_SUCCESS
;
2125 else if (IoStack
->MinorFunction
== IRP_MN_START_DEVICE
)
2128 Status
= KspStartBusDevice(DeviceObject
, ChildDeviceExtension
, Irp
);
2129 if (NT_SUCCESS(Status
))
2131 /* complete pending irps*/
2132 KspCompletePendingIrps(ChildDeviceExtension
->DeviceEntry
, STATUS_REPARSE
);
2136 Time
.QuadPart
= Int32x32To64(1500, -10000);
2139 ASSERT(BusDeviceExtension
);
2142 KeSetTimer(&BusDeviceExtension
->Timer
, Time
, &BusDeviceExtension
->Dpc
);
2144 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_CAPABILITIES
)
2146 /* query capabilities */
2147 Status
= KspQueryBusDeviceCapabilities(ChildDeviceExtension
, Irp
);
2149 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
2151 /* query pnp state */
2152 Status
= KspQueryBusDevicePnpState(ChildDeviceExtension
, Irp
);
2154 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_INTERFACE
)
2156 /* query interface */
2157 Status
= KspQueryBusDeviceInterface(ChildDeviceExtension
, Irp
);
2159 else if (IoStack
->MinorFunction
== IRP_MN_QUERY_DEVICE_RELATIONS
&& IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
)
2161 /* handle target device relations */
2162 ASSERT(IoStack
->Parameters
.QueryDeviceRelations
.Type
== TargetDeviceRelation
);
2163 ASSERT(Irp
->IoStatus
.Information
== 0);
2165 /* allocate device relation */
2166 DeviceRelation
= AllocateItem(PagedPool
, sizeof(DEVICE_RELATIONS
));
2169 DeviceRelation
->Count
= 1;
2170 DeviceRelation
->Objects
[0] = DeviceObject
;
2172 /* reference self */
2173 ObReferenceObject(DeviceObject
);
2176 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelation
;
2179 Status
= STATUS_SUCCESS
;
2184 Status
= STATUS_INSUFFICIENT_RESOURCES
;
2189 /* get default status */
2190 Status
= Irp
->IoStatus
.Status
;
2194 DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject
, BusDeviceExtension
->Common
.IsBus
, IoStack
->MinorFunction
, Status
);
2195 Irp
->IoStatus
.Status
= Status
;
2205 KsRemoveBusEnumInterface(
2208 KPROCESSOR_MODE Mode
;
2210 BUS_INSTALL_ENUM_CONTEXT Ctx
;
2211 PDEV_EXTENSION DeviceExtension
;
2212 PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension
;
2213 PIO_STACK_LOCATION IoStack
;
2215 DPRINT("KsRemoveBusEnumInterface\n");
2217 /* get io stack location */
2218 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
2220 /* get device extension */
2221 DeviceExtension
= (PDEV_EXTENSION
)IoStack
->DeviceObject
->DeviceExtension
;
2223 /* get bus device extension */
2224 BusDeviceExtension
= DeviceExtension
->Ext
->BusDeviceExtension
;
2226 /* get previous mode */
2227 Mode
= ExGetPreviousMode();
2229 /* convert to luid */
2230 luid
= RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE
);
2232 /* perform access check */
2233 if (!SeSinglePrivilegeCheck(luid
, Mode
))
2235 /* insufficient privileges */
2236 return STATUS_PRIVILEGE_NOT_HELD
;
2239 /* initialize context */
2240 KeInitializeEvent(&Ctx
.Event
, NotificationEvent
, FALSE
);
2242 Ctx
.BusDeviceExtension
= BusDeviceExtension
;
2243 ExInitializeWorkItem(&Ctx
.WorkItem
, KspRemoveBusInterface
, (PVOID
)&Ctx
);
2245 /* now queue the work item */
2246 ExQueueWorkItem(&Ctx
.WorkItem
, DelayedWorkQueue
);
2248 /* wait for completion */
2249 KeWaitForSingleObject(&Ctx
.Event
, Executive
, KernelMode
, FALSE
, NULL
);