[NTOS:IO] In IopSynchronousCall first check IrpStack->MajorFunction before checking...
[reactos.git] / ntoskrnl / io / pnpmgr / pnpmgr.c
index e0e040a..f204878 100644 (file)
@@ -23,7 +23,6 @@ RTL_AVL_TABLE PpDeviceReferenceTable;
 
 extern ERESOURCE IopDriverLoadResource;
 extern ULONG ExpInitializationPhase;
-extern BOOLEAN ExpInTextModeSetup;
 extern BOOLEAN PnpSystemInit;
 
 #define MAX_DEVICE_ID_LEN          200
@@ -647,6 +646,147 @@ IopSendStopDevice(IN PDEVICE_OBJECT DeviceObject)
     IopSynchronousCall(DeviceObject, &Stack, &Dummy);
 }
 
+static
+NTSTATUS
+IopSetServiceEnumData(PDEVICE_NODE DeviceNode)
+{
+    UNICODE_STRING ServicesKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+    UNICODE_STRING ServiceKeyName;
+    UNICODE_STRING EnumKeyName;
+    UNICODE_STRING ValueName;
+    PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
+    HANDLE ServiceKey = NULL, ServiceEnumKey = NULL;
+    ULONG Disposition;
+    ULONG Count = 0, NextInstance = 0;
+    WCHAR ValueBuffer[6];
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("IopSetServiceEnumData(%p)\n", DeviceNode);
+    DPRINT("Instance: %wZ\n", &DeviceNode->InstancePath);
+    DPRINT("Service: %wZ\n", &DeviceNode->ServiceName);
+
+    if (DeviceNode->ServiceName.Buffer == NULL)
+    {
+        DPRINT1("No service!\n");
+        return STATUS_SUCCESS;
+    }
+
+    ServiceKeyName.MaximumLength = ServicesKeyPath.Length + DeviceNode->ServiceName.Length + sizeof(UNICODE_NULL);
+    ServiceKeyName.Length = 0;
+    ServiceKeyName.Buffer = ExAllocatePool(PagedPool, ServiceKeyName.MaximumLength);
+    if (ServiceKeyName.Buffer == NULL)
+    {
+        DPRINT1("No ServiceKeyName.Buffer!\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    RtlAppendUnicodeStringToString(&ServiceKeyName, &ServicesKeyPath);
+    RtlAppendUnicodeStringToString(&ServiceKeyName, &DeviceNode->ServiceName);
+
+    DPRINT("ServiceKeyName: %wZ\n", &ServiceKeyName);
+
+    Status = IopOpenRegistryKeyEx(&ServiceKey, NULL, &ServiceKeyName, KEY_CREATE_SUB_KEY);
+    if (!NT_SUCCESS(Status))
+    {
+        goto done;
+    }
+
+    RtlInitUnicodeString(&EnumKeyName, L"Enum");
+    Status = IopCreateRegistryKeyEx(&ServiceEnumKey,
+                                    ServiceKey,
+                                    &EnumKeyName,
+                                    KEY_SET_VALUE,
+                                    REG_OPTION_VOLATILE,
+                                    &Disposition);
+    if (NT_SUCCESS(Status))
+    {
+        if (Disposition == REG_OPENED_EXISTING_KEY)
+        {
+            /* Read the NextInstance value */
+            Status = IopGetRegistryValue(ServiceEnumKey,
+                                         L"Count",
+                                         &KeyValueInformation);
+            if (!NT_SUCCESS(Status))
+                goto done;
+
+            if ((KeyValueInformation->Type == REG_DWORD) &&
+                (KeyValueInformation->DataLength))
+            {
+                /* Read it */
+                Count = *(PULONG)((ULONG_PTR)KeyValueInformation +
+                                  KeyValueInformation->DataOffset);
+            }
+
+            ExFreePool(KeyValueInformation);
+            KeyValueInformation = NULL;
+
+            /* Read the NextInstance value */
+            Status = IopGetRegistryValue(ServiceEnumKey,
+                                         L"NextInstance",
+                                         &KeyValueInformation);
+            if (!NT_SUCCESS(Status))
+                goto done;
+
+            if ((KeyValueInformation->Type == REG_DWORD) &&
+                (KeyValueInformation->DataLength))
+            {
+                NextInstance = *(PULONG)((ULONG_PTR)KeyValueInformation +
+                                         KeyValueInformation->DataOffset);
+            }
+
+            ExFreePool(KeyValueInformation);
+            KeyValueInformation = NULL;
+        }
+
+        /* Set the instance path */
+        swprintf(ValueBuffer, L"%lu", NextInstance);
+        RtlInitUnicodeString(&ValueName, ValueBuffer);
+        Status = ZwSetValueKey(ServiceEnumKey,
+                               &ValueName,
+                               0,
+                               REG_SZ,
+                               DeviceNode->InstancePath.Buffer,
+                               DeviceNode->InstancePath.MaximumLength);
+        if (!NT_SUCCESS(Status))
+            goto done;
+
+        /* Increment Count and NextInstance */
+        Count++;
+        NextInstance++;
+
+        /* Set the new Count value */
+        RtlInitUnicodeString(&ValueName, L"Count");
+        Status = ZwSetValueKey(ServiceEnumKey,
+                               &ValueName,
+                               0,
+                               REG_DWORD,
+                               &Count,
+                               sizeof(Count));
+        if (!NT_SUCCESS(Status))
+            goto done;
+
+        /* Set the new NextInstance value */
+        RtlInitUnicodeString(&ValueName, L"NextInstance");
+        Status = ZwSetValueKey(ServiceEnumKey,
+                               &ValueName,
+                               0,
+                               REG_DWORD,
+                               &NextInstance,
+                               sizeof(NextInstance));
+    }
+
+done:
+    if (ServiceEnumKey != NULL)
+        ZwClose(ServiceEnumKey);
+
+    if (ServiceKey != NULL)
+        ZwClose(ServiceKey);
+
+    ExFreePool(ServiceKeyName.Buffer);
+
+    return Status;
+}
+
 VOID
 NTAPI
 IopStartDevice2(IN PDEVICE_OBJECT DeviceObject)
@@ -740,6 +880,8 @@ IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode)
     }
 #endif
 
+    IopSetServiceEnumData(DeviceNode);
+
     /* Make sure we're started, and check if we need enumeration */
     if ((DeviceNode->Flags & DNF_STARTED) &&
         (DeviceNode->Flags & DNF_NEED_ENUMERATION_ONLY))
@@ -812,7 +954,13 @@ IopStartDevice(
                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                InstanceHandle,
                                NULL);
-    Status = ZwCreateKey(&ControlHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
+    Status = ZwCreateKey(&ControlHandle,
+                         KEY_SET_VALUE,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         REG_OPTION_VOLATILE,
+                         NULL);
     if (!NT_SUCCESS(Status))
         goto ByeBye;
 
@@ -1293,7 +1441,8 @@ IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject,
     Irp->IoStatus.Information = IoStatusBlock.Information = 0;
 
     /* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
-    if (IoStackLocation->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS)
+    if ((IoStackLocation->MajorFunction == IRP_MJ_PNP) &&
+        (IoStackLocation->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS))
     {
         /* Copy the resource requirements list into the IOSB */
         Irp->IoStatus.Information =
@@ -1458,10 +1607,6 @@ IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath,
     /* Assume failure */
     *Handle = NULL;
 
-    /* Create a volatile device tree in 1st stage so we have a clean slate
-     * for enumeration using the correct HAL (chosen in 1st stage setup) */
-    if (ExpInTextModeSetup) CreateOptions |= REG_OPTION_VOLATILE;
-
     /* Open root key for device instances */
     Status = IopOpenRegistryKeyEx(&hParent, NULL, &EnumU, KEY_CREATE_SUB_KEY);
     if (!NT_SUCCESS(Status))
@@ -1536,11 +1681,10 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
 {
     OBJECT_ATTRIBUTES ObjectAttributes;
     UNICODE_STRING KeyName;
-    HANDLE LogConfKey;
+    HANDLE LogConfKey, ControlKey, DeviceParamsKey;
     ULONG ResCount;
     ULONG ResultLength;
     NTSTATUS Status;
-    HANDLE ControlHandle;
 
     DPRINT("IopSetDeviceInstanceData() called\n");
 
@@ -1556,6 +1700,8 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
                          &ObjectAttributes,
                          0,
                          NULL,
+                         // FIXME? In r53694 it was silently turned from non-volatile into this,
+                         // without any extra warning. Is this still needed??
                          REG_OPTION_VOLATILE,
                          NULL);
     if (NT_SUCCESS(Status))
@@ -1619,10 +1765,46 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                InstanceKey,
                                NULL);
-    Status = ZwCreateKey(&ControlHandle, 0, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
-
+    Status = ZwCreateKey(&ControlKey,
+                         0,
+                         &ObjectAttributes,
+                         0,
+                         NULL,
+                         REG_OPTION_VOLATILE,
+                         NULL);
     if (NT_SUCCESS(Status))
-        ZwClose(ControlHandle);
+        ZwClose(ControlKey);
+
+    /* Create the 'Device Parameters' key and set the 'FirmwareIdentified' value for all ACPI-enumerated devices */
+    if (_wcsnicmp(DeviceNode->InstancePath.Buffer, L"ACPI\\", 5) == 0)
+    {
+        RtlInitUnicodeString(&KeyName, L"Device Parameters");
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &KeyName,
+                                   OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+                                   InstanceKey,
+                                   NULL);
+        Status = ZwCreateKey(&DeviceParamsKey,
+                             0,
+                             &ObjectAttributes,
+                             0,
+                             NULL,
+                             REG_OPTION_NON_VOLATILE,
+                             NULL);
+        if (NT_SUCCESS(Status))
+        {
+            ULONG FirmwareIdentified = 1;
+            RtlInitUnicodeString(&KeyName, L"FirmwareIdentified");
+            Status = ZwSetValueKey(DeviceParamsKey,
+                                   &KeyName,
+                                   0,
+                                   REG_DWORD,
+                                   &FirmwareIdentified,
+                                   sizeof(FirmwareIdentified));
+
+            ZwClose(DeviceParamsKey);
+        }
+    }
 
     DPRINT("IopSetDeviceInstanceData() done\n");
 
@@ -1672,7 +1854,7 @@ IopGetParentIdPrefix(PDEVICE_NODE DeviceNode,
     }
 
     /* 1. Try to retrieve ParentIdPrefix from registry */
-    KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR);
+    KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(L"12345678&12345678");
     ParentIdPrefixInformation = ExAllocatePoolWithTag(PagedPool,
                                                       KeyNameBufferLength + sizeof(UNICODE_NULL),
                                                       TAG_IO);
@@ -2673,16 +2855,11 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
 
    if (!(DeviceNode->Flags & (DNF_DISABLED | DNF_STARTED | DNF_ADDED)))
    {
-      WCHAR RegKeyBuffer[MAX_PATH];
       UNICODE_STRING RegKey;
 
       /* Install the service for this if it's in the CDDB */
       IopInstallCriticalDevice(DeviceNode);
 
-      RegKey.Length = 0;
-      RegKey.MaximumLength = sizeof(RegKeyBuffer);
-      RegKey.Buffer = RegKeyBuffer;
-
       /*
        * Retrieve configuration from Enum key
        */
@@ -2704,11 +2881,24 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
       QueryTable[1].DefaultData = L"";
       QueryTable[1].DefaultLength = 0;
 
-      RtlAppendUnicodeToString(&RegKey, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
+      RegKey.Length = 0;
+      RegKey.MaximumLength = sizeof(ENUM_ROOT) + sizeof(WCHAR) + DeviceNode->InstancePath.Length;
+      RegKey.Buffer = ExAllocatePoolWithTag(PagedPool,
+                                            RegKey.MaximumLength,
+                                            TAG_IO);
+      if (RegKey.Buffer == NULL)
+      {
+          IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+          return STATUS_INSUFFICIENT_RESOURCES;
+      }
+
+      RtlAppendUnicodeToString(&RegKey, ENUM_ROOT);
+      RtlAppendUnicodeToString(&RegKey, L"\\");
       RtlAppendUnicodeStringToString(&RegKey, &DeviceNode->InstancePath);
 
       Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
          RegKey.Buffer, QueryTable, NULL, NULL);
+      ExFreePoolWithTag(RegKey.Buffer, TAG_IO);
 
       if (!NT_SUCCESS(Status))
       {
@@ -2914,7 +3104,9 @@ IopInitializePnpServices(IN PDEVICE_NODE DeviceNode)
    return IopTraverseDeviceTree(&Context);
 }
 
-static NTSTATUS INIT_FUNCTION
+static
+INIT_FUNCTION
+NTSTATUS
 IopEnumerateDetectedDevices(
    IN HANDLE hBaseKey,
    IN PUNICODE_STRING RelativePath OPTIONAL,
@@ -3232,7 +3424,7 @@ IopEnumerateDetectedDevices(
          &ObjectAttributes,
          0,
          NULL,
-         ExpInTextModeSetup ? REG_OPTION_VOLATILE : 0,
+         REG_OPTION_NON_VOLATILE,
          NULL);
       if (!NT_SUCCESS(Status))
       {
@@ -3248,7 +3440,7 @@ IopEnumerateDetectedDevices(
          &ObjectAttributes,
          0,
          NULL,
-         ExpInTextModeSetup ? REG_OPTION_VOLATILE : 0,
+         REG_OPTION_NON_VOLATILE,
          NULL);
       ZwClose(hLevel1Key);
       if (!NT_SUCCESS(Status))
@@ -3345,7 +3537,9 @@ cleanup:
    return Status;
 }
 
-static BOOLEAN INIT_FUNCTION
+static
+INIT_FUNCTION
+BOOLEAN
 IopIsFirmwareMapperDisabled(VOID)
 {
    UNICODE_STRING KeyPathU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CURRENTCONTROLSET\\Control\\Pnp");
@@ -3413,9 +3607,9 @@ IopIsFirmwareMapperDisabled(VOID)
    return (KeyValue != 0) ? TRUE : FALSE;
 }
 
+INIT_FUNCTION
 NTSTATUS
 NTAPI
-INIT_FUNCTION
 IopUpdateRootKey(VOID)
 {
    UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
@@ -3426,7 +3620,7 @@ IopUpdateRootKey(VOID)
    NTSTATUS Status;
 
    InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
-   Status = ZwCreateKey(&hEnum, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, 0, NULL);
+   Status = ZwCreateKey(&hEnum, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
    if (!NT_SUCCESS(Status))
    {
       DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status);
@@ -3434,7 +3628,7 @@ IopUpdateRootKey(VOID)
    }
 
    InitializeObjectAttributes(&ObjectAttributes, &RootPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hEnum, NULL);
-   Status = ZwCreateKey(&hRoot, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, 0, NULL);
+   Status = ZwCreateKey(&hRoot, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
    ZwClose(hEnum);
    if (!NT_SUCCESS(Status))
    {
@@ -4145,6 +4339,9 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
             *ResultLength -= sizeof(OBJECT_NAME_INFORMATION);
             break;
 
+        case DevicePropertyRemovalPolicy:
+            PIP_RETURN_DATA(sizeof(UCHAR), &DeviceNode->RemovalPolicy);
+
         /* Handle the registry-based properties */
         case DevicePropertyUINumber:
             PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER, REG_DWORD);
@@ -4171,8 +4368,6 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
         case DevicePropertyContainerID:
             //PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
             PIP_UNIMPLEMENTED();
-        case DevicePropertyRemovalPolicy:
-            PIP_UNIMPLEMENTED();
             break;
         case DevicePropertyInstallState:
             PIP_REGISTRY_DATA(REGSTR_VAL_CONFIGFLAGS, REG_DWORD);
@@ -4502,8 +4697,13 @@ IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject,
                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                               *DevInstRegKey,
                               NULL);
-   Status = ZwCreateKey(DevInstRegKey, DesiredAccess, &ObjectAttributes,
-                        0, NULL, ExpInTextModeSetup ? REG_OPTION_VOLATILE : 0, NULL);
+   Status = ZwCreateKey(DevInstRegKey,
+                        DesiredAccess,
+                        &ObjectAttributes,
+                        0,
+                        NULL,
+                        REG_OPTION_NON_VOLATILE,
+                        NULL);
    ZwClose(ObjectAttributes.RootDirectory);
 
    return Status;