Author: cgutman
Date: Thu Apr 1 08:58:32 2010
New Revision: 46639
URL:
http://svn.reactos.org/svn/reactos?rev=46639&view=rev
Log:
[NTOSKRNL]
- Change PnpRootCreateDevice's ServiceName parameter to be a full service name so it
can be used by IoReportDetectedDevice (for reporting devices without the
"LEGACY_" prefix) and change all of its callers accordingly
- Remove the broken implementation of IoReportDetectedDevice and replace it with a fully
working implementation
- There is still a bug that it creates a new device instance every boot, but unlike the
previous code, at least it creates one ;-)
Modified:
trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c
trunk/reactos/ntoskrnl/io/pnpmgr/pnpreport.c
trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.…
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c [iso-8859-1] Thu Apr 1 08:58:32 2010
@@ -46,11 +46,12 @@
/* FUNCTIONS *****************************************************************/
-static NTSTATUS
+NTSTATUS
IopAssignDeviceResources(
IN PDEVICE_NODE DeviceNode,
OUT ULONG *pRequiredSize);
-static NTSTATUS
+
+NTSTATUS
IopTranslateDeviceResources(
IN PDEVICE_NODE DeviceNode,
IN ULONG RequiredSize);
@@ -361,6 +362,8 @@
PDEVICE_NODE Node;
NTSTATUS Status;
KIRQL OldIrql;
+ UNICODE_STRING FullServiceName;
+ UNICODE_STRING LegacyPrefix = RTL_CONSTANT_STRING(L"LEGACY_");
DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
ParentNode, PhysicalDeviceObject, ServiceName);
@@ -375,7 +378,22 @@
if (!PhysicalDeviceObject)
{
- Status = PnpRootCreateDevice(ServiceName, &PhysicalDeviceObject);
+ if (ServiceName)
+ {
+ FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName->Length;
+ FullServiceName.Length = 0;
+ FullServiceName.Buffer = ExAllocatePool(PagedPool,
FullServiceName.MaximumLength);
+ if (!FullServiceName.Buffer)
+ {
+ ExFreePool(Node);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix);
+ RtlAppendUnicodeStringToString(&FullServiceName, ServiceName);
+ }
+
+ Status = PnpRootCreateDevice(ServiceName ? &FullServiceName : NULL,
&PhysicalDeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status);
@@ -709,7 +727,6 @@
}
-static
NTSTATUS
IopSetDeviceInstanceData(HANDLE InstanceKey,
PDEVICE_NODE DeviceNode)
@@ -799,7 +816,7 @@
}
-static NTSTATUS
+NTSTATUS
IopAssignDeviceResources(
IN PDEVICE_NODE DeviceNode,
OUT ULONG *pRequiredSize)
@@ -1014,7 +1031,7 @@
}
-static NTSTATUS
+NTSTATUS
IopTranslateDeviceResources(
IN PDEVICE_NODE DeviceNode,
IN ULONG RequiredSize)
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnpreport.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnprepo…
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnpreport.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnpreport.c [iso-8859-1] Thu Apr 1 08:58:32 2010
@@ -3,7 +3,7 @@
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/io/pnpmgr/pnpreport.c
* PURPOSE: Device Changes Reporting Functions
- * PROGRAMMERS: Filip Navara (xnavara(a)volny.cz)
+ * PROGRAMMERS: Cameron Gutman (cameron.gutman(a)reactos.org)
*/
/* INCLUDES ******************************************************************/
@@ -11,6 +11,90 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
+
+NTSTATUS
+NTAPI
+IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath,
+ OUT PHANDLE Handle);
+
+NTSTATUS
+IopAssignDeviceResources(
+ IN PDEVICE_NODE DeviceNode,
+ OUT ULONG *pRequiredSize);
+
+NTSTATUS
+IopSetDeviceInstanceData(HANDLE InstanceKey,
+ PDEVICE_NODE DeviceNode);
+
+NTSTATUS
+IopTranslateDeviceResources(
+ IN PDEVICE_NODE DeviceNode,
+ IN ULONG RequiredSize);
+
+NTSTATUS
+IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
+ PVOID Context);
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+PWCHAR
+IopGetInterfaceTypeString(INTERFACE_TYPE IfType)
+{
+ switch (IfType)
+ {
+ case Internal:
+ return L"Internal";
+
+ case Isa:
+ return L"Isa";
+
+ case Eisa:
+ return L"Eisa";
+
+ case MicroChannel:
+ return L"MicroChannel";
+
+ case TurboChannel:
+ return L"TurboChannel";
+
+ case PCIBus:
+ return L"PCIBus";
+
+ case VMEBus:
+ return L"VMEBus";
+
+ case NuBus:
+ return L"NuBus";
+
+ case PCMCIABus:
+ return L"PCMCIABus";
+
+ case CBus:
+ return L"CBus";
+
+ case MPIBus:
+ return L"MPIBus";
+
+ case MPSABus:
+ return L"MPSABus";
+
+ case ProcessorInternal:
+ return L"ProcessorInternal";
+
+ case PNPISABus:
+ return L"PNPISABus";
+
+ case PNPBus:
+ return L"PNPBus";
+
+ case Vmcs:
+ return L"Vmcs";
+
+ default:
+ DPRINT1("Invalid bus type: %d\n", IfType);
+ return NULL;
+ }
+}
/* PUBLIC FUNCTIONS **********************************************************/
@@ -30,29 +114,56 @@
{
PDEVICE_NODE DeviceNode;
PDEVICE_OBJECT Pdo;
- NTSTATUS Status = STATUS_SUCCESS;
-
- DPRINT("__FUNCTION__ (DeviceObject %p, *DeviceObject %p)\n",
+ NTSTATUS Status;
+ HANDLE InstanceKey;
+ ULONG RequiredLength;
+ UNICODE_STRING ValueName, ServiceName;
+ WCHAR HardwareId[256];
+ PWCHAR IfString;
+ ULONG IdLength;
+
+ DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
DeviceObject, DeviceObject ? *DeviceObject : NULL);
- /* if *DeviceObject is not NULL, we must use it as a PDO, and don't create a new
one */
+ /* 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;
+
+ /* If the interface type is unknown, treat it as internal */
+ if (LegacyBusType == InterfaceTypeUndefined)
+ LegacyBusType = Internal;
+
+ /* Get the string equivalent of the interface type */
+ IfString = IopGetInterfaceTypeString(LegacyBusType);
+
+ /* If NULL is returned then it's a bad type */
+ if (!IfString)
+ return STATUS_INVALID_PARAMETER;
+
+ /* We use the caller's PDO if they supplied one */
if (DeviceObject && *DeviceObject)
{
Pdo = *DeviceObject;
+ DeviceNode = IopGetDeviceNode(*DeviceObject);
}
else
{
- UNICODE_STRING ServiceName;
- 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;
-
- /* create a new PDO and return it in *DeviceObject */
+ /* Create the PDO */
+ Status = PnpRootCreateDevice(&ServiceName,
+ &Pdo);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ /* Create the device node for the new PDO */
Status = IopCreateDeviceNode(IopRootDeviceNode,
+ Pdo,
NULL,
- &ServiceName,
&DeviceNode);
if (!NT_SUCCESS(Status))
@@ -60,13 +171,129 @@
DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status);
return Status;
}
-
- Pdo = DeviceNode->PhysicalDeviceObject;
- if (DeviceObject) *DeviceObject = Pdo;
- }
-
- /* we don't need to call AddDevice and send IRP_MN_START_DEVICE */
- return Status;
+ }
+
+ /* We don't call AddDevice for devices reported this way */
+ IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
+
+ /* We don't send IRP_MN_START_DEVICE */
+ IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
+
+ /* This is a legacy driver for this device */
+ IopDeviceNodeSetFlag(DeviceNode, DNF_LEGACY_DRIVER);
+
+ /* Perform a manual configuration of our device */
+ IopActionInterrogateDeviceStack(DeviceNode, DeviceNode->Parent);
+ IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
+
+ /* Open a handle to the instance path key */
+ Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, &InstanceKey);
+ if (!NT_SUCCESS(Status))
+ return Status;
+
+ /* Add DETECTEDInterfaceType\DriverName */
+ IdLength = 0;
+ IdLength += swprintf(&HardwareId[IdLength],
+ L"DETECTED%ls\\%wZ",
+ IfString,
+ &ServiceName);
+ HardwareId[IdLength++] = UNICODE_NULL;
+
+ /* Add DETECTED\DriverName */
+ IdLength += swprintf(&HardwareId[IdLength],
+ L"DETECTED\\%wZ",
+ &ServiceName);
+ HardwareId[IdLength++] = UNICODE_NULL;
+
+ /* Terminate the string with another null */
+ HardwareId[IdLength] = UNICODE_NULL;
+
+ /* Store the value for CompatibleIDs */
+ RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
+ 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;
+ }
+
+ /* 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);
+ HardwareId[++IdLength] = UNICODE_NULL;
+
+ /* Write the value to the registry */
+ Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_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 */
+ DeviceNode->BootResources = ResourceList;
+ DeviceNode->ResourceRequirements = ResourceRequirements;
+
+ /* Set appropriate flags */
+ if (DeviceNode->BootResources)
+ IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
+
+ if (DeviceNode->ResourceRequirements)
+ IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_REPORTED);
+ else
+ IopDeviceNodeSetFlag(DeviceNode, DNF_NO_RESOURCE_REQUIRED);
+
+ /* Write the resource information to the registry */
+ IopSetDeviceInstanceData(InstanceKey, DeviceNode);
+
+ /* Close the instance key handle */
+ ZwClose(InstanceKey);
+
+ /* If the caller didn't get the resources assigned for us, do it now */
+ if (!ResourceAssigned)
+ {
+ IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
+ Status = IopAssignDeviceResources(DeviceNode, &RequiredLength);
+ if (NT_SUCCESS(Status))
+ {
+ Status = IopTranslateDeviceResources(DeviceNode, RequiredLength);
+ if (NT_SUCCESS(Status))
+ IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED);
+ }
+ IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
+
+ /* See if we failed */
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("Assigning resources failed: 0x%x\n", Status);
+ return Status;
+ }
+ }
+
+ /* Report the device's enumeration to umpnpmgr */
+ IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED,
+ &DeviceNode->InstancePath);
+
+ /* Report the device's arrival to umpnpmgr */
+ IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
+ &DeviceNode->InstancePath);
+
+ DPRINT1("Reported device: %S (%wZ)\n", HardwareId,
&DeviceNode->InstancePath);
+
+ /* Return the PDO */
+ if (DeviceObject) *DeviceObject = Pdo;
+
+ return STATUS_SUCCESS;
}
/*
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnproot…
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c [iso-8859-1] Thu Apr 1 08:58:32 2010
@@ -134,7 +134,7 @@
IN PDEVICE_OBJECT *PhysicalDeviceObject)
{
PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
- UNICODE_STRING UnknownServiceName = RTL_CONSTANT_STRING(L"UNKNOWN");
+ UNICODE_STRING UnknownServiceName =
RTL_CONSTANT_STRING(L"LEGACY_UNKNOWN");
PUNICODE_STRING LocalServiceName;
PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
WCHAR DevicePath[MAX_PATH + 1];
@@ -154,7 +154,7 @@
DPRINT("Creating a PnP root device for service '%wZ'\n",
LocalServiceName);
/* Search for a free instance ID */
- _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR),
L"%s\\LEGACY_%wZ", REGSTR_KEY_ROOTENUM, LocalServiceName);
+ _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\%wZ",
REGSTR_KEY_ROOTENUM, LocalServiceName);
for (i = 0; i < 9999; i++)
{
_snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR),
L"%04lu", i);