[NTOSKRNL] Minor PnP enhancements.

- For non-PnP devices reported to the PnP manager through the
  IoReportDetectedDevice() function, store the corresponding
  service/driver name and (non-)legacy information inside their
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\ entries.
- Drivers flagged as "DRVO_BUILTIN_DRIVER" (basically, only those
  created via a IoCreateDriver() call) have their "Service" name that
  contain "\Driver\", which should be stripped before being used in
  building e.g. the corresponding "DETECTEDxxx" PnP compatible IDs.
  CORE-14247

- Use explicit REG_OPTION_NON_VOLATILE flag where needed in the
  IopCreateDeviceKeyPath() calls.
- Save NULL-terminated REG-SZ string properties in the enumeration tree
  for each device enumerated inside \Enum\Root\.
- Always use upcased key name for the "LEGACY_***" elements in \Enum\Root\.
- Add a default "ConfigFlags" value for the legacy elements.
- Simplify few parts of code.
This commit is contained in:
Hermès Bélusca-Maïto 2018-04-22 16:31:53 +02:00
parent 2183e65c17
commit e616a456c0
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 79 additions and 25 deletions

View file

@ -98,7 +98,7 @@ IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
PWCHAR IdBuffer, OriginalIdBuffer;
/* Open the device instance key */
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
if (Status != STATUS_SUCCESS)
return;
@ -800,7 +800,7 @@ IopStartDevice(
IopStartAndEnumerateDevice(DeviceNode);
/* FIX: Should be done in new device instance code */
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceHandle);
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceHandle);
if (!NT_SUCCESS(Status))
goto ByeBye;
@ -817,7 +817,7 @@ IopStartDevice(
goto ByeBye;
RtlInitUnicodeString(&KeyName, L"ActiveService");
Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, DeviceNode->ServiceName.Buffer, DeviceNode->ServiceName.Length);
Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, DeviceNode->ServiceName.Buffer, DeviceNode->ServiceName.Length + sizeof(UNICODE_NULL));
// }
ByeBye:
@ -873,7 +873,7 @@ IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode,
else
DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
if (NT_SUCCESS(Status))
{
/* Set 'Capabilities' value */
@ -1067,7 +1067,7 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
if (!PhysicalDeviceObject)
{
FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName1->Length;
FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName1->Length + sizeof(UNICODE_NULL);
FullServiceName.Length = 0;
FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength);
if (!FullServiceName.Buffer)
@ -1078,6 +1078,7 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix);
RtlAppendUnicodeStringToString(&FullServiceName, ServiceName1);
RtlUpcaseUnicodeString(&FullServiceName, &FullServiceName, FALSE);
Status = PnpRootCreateDevice(&FullServiceName, NULL, &PhysicalDeviceObject, &Node->InstancePath);
if (!NT_SUCCESS(Status))
@ -1097,7 +1098,9 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
return Status;
}
Node->ServiceName.Buffer = ExAllocatePool(PagedPool, ServiceName1->Length);
Node->ServiceName.MaximumLength = ServiceName1->Length + sizeof(UNICODE_NULL);
Node->ServiceName.Length = 0;
Node->ServiceName.Buffer = ExAllocatePool(PagedPool, Node->ServiceName.MaximumLength);
if (!Node->ServiceName.Buffer)
{
ZwClose(InstanceHandle);
@ -1106,39 +1109,39 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
return Status;
}
Node->ServiceName.MaximumLength = ServiceName1->Length;
Node->ServiceName.Length = 0;
RtlAppendUnicodeStringToString(&Node->ServiceName, ServiceName1);
RtlCopyUnicodeString(&Node->ServiceName, ServiceName1);
if (ServiceName)
{
RtlInitUnicodeString(&KeyName, L"Service");
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName->Buffer, ServiceName->Length);
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName->Buffer, ServiceName->Length + sizeof(UNICODE_NULL));
}
if (NT_SUCCESS(Status))
{
RtlInitUnicodeString(&KeyName, L"Legacy");
LegacyValue = 1;
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
RtlInitUnicodeString(&KeyName, L"ConfigFlags");
LegacyValue = 0;
ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
if (NT_SUCCESS(Status))
{
RtlInitUnicodeString(&KeyName, L"Class");
RtlInitUnicodeString(&ClassName, L"LegacyDriver\0");
RtlInitUnicodeString(&ClassName, L"LegacyDriver");
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassName.Buffer, ClassName.Length + sizeof(UNICODE_NULL));
if (NT_SUCCESS(Status))
{
RtlInitUnicodeString(&KeyName, L"ClassGUID");
RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}\0");
RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassGUID.Buffer, ClassGUID.Length + sizeof(UNICODE_NULL));
if (NT_SUCCESS(Status))
{
// FIXME: Retrieve the real "description" by looking at the "DisplayName" string
// of the corresponding CurrentControlSet\Services\xxx entry for this driver.
RtlInitUnicodeString(&KeyName, L"DeviceDesc");
Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName1->Buffer, ServiceName1->Length + sizeof(UNICODE_NULL));
}
}
@ -2244,7 +2247,7 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
/*
* Create registry key for the instance id, if it doesn't exist yet
*/
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
@ -2719,10 +2722,7 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
DeviceCaps.RawDeviceOK)
{
DPRINT("%wZ is using parent bus driver (%wZ)\n", &DeviceNode->InstancePath, &ParentDeviceNode->ServiceName);
DeviceNode->ServiceName.Length = 0;
DeviceNode->ServiceName.MaximumLength = 0;
DeviceNode->ServiceName.Buffer = NULL;
RtlInitEmptyUnicodeString(&DeviceNode->ServiceName, NULL, 0);
}
else if (ClassGUID.Length != 0)
{

View file

@ -173,15 +173,17 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
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);
ServiceName = DriverObject->DriverExtension->ServiceKeyName;
ServiceLongName = DriverObject->DriverExtension->ServiceKeyName;
ServiceName = ServiceLongName;
/* If the interface type is unknown, treat it as internal */
if (LegacyBusType == InterfaceTypeUndefined)
@ -194,6 +196,42 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
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)
{
@ -218,7 +256,6 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
Pdo,
NULL,
&DeviceNode);
if (!NT_SUCCESS(Status))
{
DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status);
@ -252,6 +289,23 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
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],