}
VOID
+NTAPI
IopReportTargetDeviceChangeAsyncWorker(PVOID Context)
{
PINTERNAL_WORK_QUEUE_ITEM Item;
NTSTATUS Status;
HANDLE InstanceKey;
ULONG RequiredLength;
- UNICODE_STRING ValueName, ServiceName;
+ UNICODE_STRING ValueName, ServiceLongName, ServiceName;
WCHAR HardwareId[256];
PWCHAR IfString;
ULONG IdLength;
+ ULONG LegacyValue;
DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
- DeviceObject, DeviceObject ? *DeviceObject : NULL);
+ DeviceObject, DeviceObject ? *DeviceObject : NULL);
- /* Create the service name (eg. ACPI_HAL) */
- ServiceName.Buffer = DriverObject->DriverName.Buffer +
- sizeof(DRIVER_ROOT_NAME) / sizeof(WCHAR) - 1;
- ServiceName.Length = DriverObject->DriverName.Length -
- sizeof(DRIVER_ROOT_NAME) + sizeof(WCHAR);
- ServiceName.MaximumLength = ServiceName.Length;
+ ServiceLongName = DriverObject->DriverExtension->ServiceKeyName;
+ ServiceName = ServiceLongName;
/* If the interface type is unknown, treat it as internal */
if (LegacyBusType == InterfaceTypeUndefined)
if (!IfString)
return STATUS_INVALID_PARAMETER;
+ /*
+ * Drivers that have been created via a direct IoCreateDriver() call
+ * have their ServiceKeyName set to \Driver\DriverName. We need to
+ * strip everything up to the last path separator and keep what remains.
+ */
+ if (DriverObject->Flags & DRVO_BUILTIN_DRIVER)
+ {
+ /*
+ * Find the last path separator.
+ * NOTE: Since ServiceName is not necessarily NULL-terminated,
+ * we cannot use wcsrchr().
+ */
+ if (ServiceName.Buffer && ServiceName.Length >= sizeof(WCHAR))
+ {
+ ValueName.Length = 1;
+ ValueName.Buffer = ServiceName.Buffer + (ServiceName.Length / sizeof(WCHAR)) - 1;
+
+ while ((ValueName.Buffer > ServiceName.Buffer) && (*ValueName.Buffer != L'\\'))
+ {
+ --ValueName.Buffer;
+ ++ValueName.Length;
+ }
+ if (*ValueName.Buffer == L'\\')
+ {
+ ++ValueName.Buffer;
+ --ValueName.Length;
+ }
+ ValueName.Length *= sizeof(WCHAR);
+
+ /* Shorten the string */
+ ServiceName.MaximumLength -= (ServiceName.Length - ValueName.Length);
+ ServiceName.Length = ValueName.Length;
+ ServiceName.Buffer = ValueName.Buffer;
+ }
+ }
+
/* We use the caller's PDO if they supplied one */
if (DeviceObject && *DeviceObject)
{
Pdo,
NULL,
&DeviceNode);
-
if (!NT_SUCCESS(Status))
{
DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status);
/* We're enumerated already */
IopDeviceNodeSetFlag(DeviceNode, DNF_ENUMERATED);
-
+
/* We don't call AddDevice for devices reported this way */
IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
/* Open a handle to the instance path key */
- /* REG_OPTION_VOLATILE is a HACK!!! */
- Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_VOLATILE, &InstanceKey);
+ Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
if (!NT_SUCCESS(Status))
return Status;
+ /* Save the driver name */
+ RtlInitUnicodeString(&ValueName, L"Service");
+ Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_SZ, ServiceLongName.Buffer, ServiceLongName.Length + sizeof(UNICODE_NULL));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Failed to write the Service name value: 0x%x\n", Status);
+ }
+
+ /* Report as non-legacy driver */
+ RtlInitUnicodeString(&ValueName, L"Legacy");
+ LegacyValue = 0;
+ Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Failed to write the Legacy value: 0x%x\n", Status);
+ }
+
/* Add DETECTEDInterfaceType\DriverName */
IdLength = 0;
IdLength += swprintf(&HardwareId[IdLength],
Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, HardwareId, IdLength * sizeof(WCHAR));
if (!NT_SUCCESS(Status))
{
- DPRINT("Failed to write the compatible IDs: 0x%x\n", Status);
- ZwClose(InstanceKey);
- return Status;
+ DPRINT("Failed to write the compatible IDs: 0x%x\n", Status);
+ ZwClose(InstanceKey);
+ return Status;
}
/* Add a hardware ID if the driver didn't report one */
RtlInitUnicodeString(&ValueName, L"HardwareID");
if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND)
{
- /* Just use our most specific compatible ID */
- IdLength = 0;
- IdLength += swprintf(&HardwareId[IdLength],
- L"DETECTED%ls\\%wZ",
- IfString,
- &ServiceName);
- IdLength++;
-
- HardwareId[IdLength++] = UNICODE_NULL;
-
- /* Write the value to the registry */
- Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, HardwareId, IdLength * sizeof(WCHAR));
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Failed to write the hardware ID: 0x%x\n", Status);
- ZwClose(InstanceKey);
- return Status;
- }
+ /* Just use our most specific compatible ID */
+ IdLength = 0;
+ IdLength += swprintf(&HardwareId[IdLength],
+ L"DETECTED%ls\\%wZ",
+ IfString,
+ &ServiceName);
+ IdLength++;
+
+ HardwareId[IdLength++] = UNICODE_NULL;
+
+ /* Write the value to the registry */
+ Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, HardwareId, IdLength * sizeof(WCHAR));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Failed to write the hardware ID: 0x%x\n", Status);
+ ZwClose(InstanceKey);
+ return Status;
+ }
}
/* Assign the resources to the device node */
/* Set appropriate flags */
if (DeviceNode->BootResources)
- IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
+ IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
if (!DeviceNode->ResourceRequirements && !DeviceNode->BootResources)
- IopDeviceNodeSetFlag(DeviceNode, DNF_NO_RESOURCE_REQUIRED);
+ IopDeviceNodeSetFlag(DeviceNode, DNF_NO_RESOURCE_REQUIRED);
/* Write the resource information to the registry */
IopSetDeviceInstanceData(InstanceKey, DeviceNode);
/* If the caller didn't get the resources assigned for us, do it now */
if (!ResourceAssigned)
{
- Status = IopAssignDeviceResources(DeviceNode);
-
- /* See if we failed */
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Assigning resources failed: 0x%x\n", Status);
- ZwClose(InstanceKey);
- return Status;
- }
+ Status = IopAssignDeviceResources(DeviceNode);
+
+ /* See if we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Assigning resources failed: 0x%x\n", Status);
+ ZwClose(InstanceKey);
+ return Status;
+ }
}
/* Close the instance key handle */
IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
&DeviceNode->InstancePath);
- DPRINT1("Reported device: %S (%wZ)\n", HardwareId, &DeviceNode->InstancePath);
+ DPRINT("Reported device: %S (%wZ)\n", HardwareId, &DeviceNode->InstancePath);
/* Return the PDO */
if (DeviceObject) *DeviceObject = Pdo;
/* Check for valid PDO */
if (!IopIsValidPhysicalDeviceObject(PhysicalDeviceObject))
{
- KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG)PhysicalDeviceObject, 0, 0);
+ KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG_PTR)PhysicalDeviceObject, 0, 0);
}
/* FileObject must be null. PnP will fill in it */
/* Check for valid PDO */
if (!IopIsValidPhysicalDeviceObject(PhysicalDeviceObject))
{
- KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG)PhysicalDeviceObject, 0, 0);
+ KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG_PTR)PhysicalDeviceObject, 0, 0);
}
/* FileObject must be null. PnP will fill in it */
Item->PhysicalDeviceObject = PhysicalDeviceObject;
Item->Callback = Callback;
Item->Context = Context;
- ExInitializeWorkItem(&(Item->WorkItem), (PWORKER_THREAD_ROUTINE)IopReportTargetDeviceChangeAsyncWorker, Item);
+ ExInitializeWorkItem(&(Item->WorkItem), IopReportTargetDeviceChangeAsyncWorker, Item);
/* Finally, queue the item, our work here is done */
ExQueueWorkItem(&(Item->WorkItem), DelayedWorkQueue);