Implement DICS_FLAG_CONFIGSPECIFIC case in SetupDiOpenDevRegKey, by factorizing some code from SetupDiCreateDevRegKeyW to OpenHardwareProfileKey
Don't ask for KEY_ENUMERATE_SUB_KEYS access right when not needed
Implemenent internal function ResetDevice()
Modified: trunk/reactos/lib/setupapi/devinst.c

Modified: trunk/reactos/lib/setupapi/devinst.c
--- trunk/reactos/lib/setupapi/devinst.c	2005-12-15 22:13:01 UTC (rev 20202)
+++ trunk/reactos/lib/setupapi/devinst.c	2005-12-15 23:24:43 UTC (rev 20203)
@@ -1619,10 +1619,10 @@
 
         /* Find class GUID associated to the device instance */
         rc = RegOpenKeyExW(
-            HKEY_LOCAL_MACHINE,
+            list->HKLM,
             REGSTR_PATH_SYSTEMENUM,
             0, /* Options */
-            KEY_ENUMERATE_SUB_KEYS,
+            0,
             &hEnumKey);
         if (rc != ERROR_SUCCESS)
         {
@@ -2670,7 +2670,7 @@
                     list->HKLM,
                     REGSTR_PATH_SYSTEMENUM,
                     0, /* Options */
-                    KEY_ENUMERATE_SUB_KEYS,
+                    0,
                     &hEnumKey);
                 if (rc != ERROR_SUCCESS)
                 {
@@ -3198,7 +3198,7 @@
     rc = RegOpenKeyExW(HKLM,
 		      lpKeyName,
 		      0,
-		      ClassGuid ? KEY_ENUMERATE_SUB_KEYS : samDesired,
+		      ClassGuid ? 0 : samDesired,
 		      &hClassesKey);
     if (MachineName != NULL) RegCloseKey(HKLM);
     if (rc != ERROR_SUCCESS)
@@ -4304,6 +4304,63 @@
     return ret;
 }
 
+static HKEY
+OpenHardwareProfileKey(
+        IN HKEY HKLM,
+        IN DWORD HwProfile,
+        IN DWORD samDesired)
+{
+    HKEY hHWProfilesKey = INVALID_HANDLE_VALUE;
+    HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
+    HKEY ret = INVALID_HANDLE_VALUE;
+    LONG rc;
+
+    rc = RegOpenKeyExW(HKLM,
+        REGSTR_PATH_HWPROFILES,
+        0,
+        0,
+        &hHWProfilesKey);
+    if (rc != ERROR_SUCCESS)
+    {
+        SetLastError(rc);
+        goto cleanup;
+    }
+    if (HwProfile == 0)
+    {
+        rc = RegOpenKeyExW(
+            hHWProfilesKey,
+            REGSTR_KEY_CURRENT,
+            0,
+            KEY_CREATE_SUB_KEY,
+            &hHWProfileKey);
+    }
+    else
+    {
+        WCHAR subKey[5];
+        snprintfW(subKey, 4, L"%04lu", HwProfile);
+        subKey[4] = '\0';
+        rc = RegOpenKeyExW(
+            hHWProfilesKey,
+            subKey,
+            0,
+            KEY_CREATE_SUB_KEY,
+            &hHWProfileKey);
+    }
+    if (rc != ERROR_SUCCESS)
+    {
+        SetLastError(rc);
+        goto cleanup;
+    }
+    ret = hHWProfileKey;
+
+cleanup:
+    if (hHWProfilesKey != INVALID_HANDLE_VALUE)
+        RegCloseKey(hHWProfilesKey);
+    if (hHWProfileKey != INVALID_HANDLE_VALUE && hHWProfileKey != ret)
+        RegCloseKey(hHWProfileKey);
+    return ret;
+}
+
 /***********************************************************************
  *		SetupDiCreateDevRegKeyW (SETUPAPI.@)
  */
@@ -4345,7 +4402,6 @@
         LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
         DWORD Index; /* Index used in the DriverKey name */
         DWORD rc;
-        HKEY hHWProfilesKey = INVALID_HANDLE_VALUE;
         HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
         HKEY hEnumKey = INVALID_HANDLE_VALUE;
         HKEY hClassKey = INVALID_HANDLE_VALUE;
@@ -4357,42 +4413,9 @@
             RootKey = list->HKLM;
         else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
         {
-            rc = RegOpenKeyExW(list->HKLM,
-                REGSTR_PATH_HWPROFILES,
-                0,
-                0,
-                &hHWProfilesKey);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
+            hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
+            if (hHWProfileKey == INVALID_HANDLE_VALUE)
                 goto cleanup;
-            }
-            if (HwProfile == 0)
-            {
-                rc = RegOpenKeyExW(
-                    hHWProfilesKey,
-                    REGSTR_KEY_CURRENT,
-                    0,
-                    KEY_CREATE_SUB_KEY,
-                    &hHWProfileKey);
-            }
-            else
-            {
-                WCHAR subKey[5];
-                snprintfW(subKey, 4, L"%04lu", HwProfile);
-                subKey[4] = '\0';
-                rc = RegOpenKeyExW(
-                    hHWProfilesKey,
-                    subKey,
-                    0,
-                    KEY_CREATE_SUB_KEY,
-                    &hHWProfileKey);
-            }
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
             RootKey = hHWProfileKey;
         }
 
@@ -4522,8 +4545,6 @@
         if (lpGuidString)
             RpcStringFreeW(&lpGuidString);
         HeapFree(GetProcessHeap(), 0, DriverKey);
-        if (hHWProfilesKey != INVALID_HANDLE_VALUE)
-            RegCloseKey(hHWProfilesKey);
         if (hHWProfileKey != INVALID_HANDLE_VALUE)
             RegCloseKey(hHWProfileKey);
         if (hEnumKey != INVALID_HANDLE_VALUE)
@@ -4571,104 +4592,113 @@
         SetLastError(ERROR_INVALID_PARAMETER);
     else
     {
-        HKEY hKey = INVALID_HANDLE_VALUE;
-        HKEY hRootKey = INVALID_HANDLE_VALUE;
         struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
         LPWSTR DriverKey = NULL;
         DWORD dwLength = 0;
         DWORD dwRegType;
         DWORD rc;
+        HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
+        HKEY hEnumKey = INVALID_HANDLE_VALUE;
+        HKEY hKey = INVALID_HANDLE_VALUE;
+        HKEY RootKey;
 
-        if (Scope == DICS_FLAG_CONFIGSPECIFIC)
+        if (Scope == DICS_FLAG_GLOBAL)
+            RootKey = list->HKLM;
+        else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
         {
-            FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
+            hHWProfileKey = OpenHardwareProfileKey(list->HKLM, HwProfile, 0);
+            if (hHWProfileKey == INVALID_HANDLE_VALUE)
+                goto cleanup;
+            RootKey = hHWProfileKey;
         }
-        else /* Scope == DICS_FLAG_GLOBAL */
+
+        rc = RegOpenKeyExW(
+            RootKey,
+            REGSTR_PATH_SYSTEMENUM,
+            0, /* Options */
+            0,
+            &hEnumKey);
+        if (rc != ERROR_SUCCESS)
         {
-            rc = RegOpenKeyExW(
-                list->HKLM,
-                REGSTR_PATH_SYSTEMENUM,
-                0, /* Options */
-                KEY_ENUMERATE_SUB_KEYS,
-                &hRootKey);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            rc = RegOpenKeyExW(
-                hRootKey,
-                deviceInfo->DeviceName,
-                0, /* Options */
-                KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
-                &hKey);
-            RegCloseKey(hRootKey);
-            hRootKey = INVALID_HANDLE_VALUE;
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            if (KeyType == DIREG_DEV)
-            {
-                /* We're done. Just return the hKey handle */
-                ret = hKey;
-                goto cleanup;
-            }
-            /* Read the 'Driver' key */
-            rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            if (dwRegType != REG_SZ)
-            {
-                SetLastError(ERROR_GEN_FAILURE);
-                goto cleanup;
-            }
-            DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
-            if (!DriverKey)
-            {
-                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-                goto cleanup;
-            }
-            rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            RegCloseKey(hKey);
-            hKey = INVALID_HANDLE_VALUE;
-            /* Need to open the driver key */
-            rc = RegOpenKeyExW(
-                list->HKLM,
-                REGSTR_PATH_CLASS_NT,
-                0, /* Options */
-                KEY_ENUMERATE_SUB_KEYS,
-                &hRootKey);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
-            rc = RegOpenKeyExW(
-                hRootKey,
-                DriverKey,
-                0, /* Options */
-                samDesired,
-                &hKey);
-            if (rc != ERROR_SUCCESS)
-            {
-                SetLastError(rc);
-                goto cleanup;
-            }
+            SetLastError(rc);
+            goto cleanup;
+        }
+        rc = RegOpenKeyExW(
+            hEnumKey,
+            deviceInfo->DeviceName,
+            0, /* Options */
+            KeyType == DIREG_DEV ? samDesired : KEY_QUERY_VALUE,
+            &hKey);
+        RegCloseKey(hEnumKey);
+        hEnumKey = INVALID_HANDLE_VALUE;
+        if (rc != ERROR_SUCCESS)
+        {
+            SetLastError(rc);
+            goto cleanup;
+        }
+        if (KeyType == DIREG_DEV)
+        {
+            /* We're done. Just return the hKey handle */
+            CHECKPOINT1;
             ret = hKey;
+            goto cleanup;
         }
+        /* Read the 'Driver' key */
+        rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength);
+        if (rc != ERROR_SUCCESS)
+        {
+            SetLastError(rc);
+            goto cleanup;
+        }
+        else if (dwRegType != REG_SZ)
+        {
+            SetLastError(ERROR_GEN_FAILURE);
+            goto cleanup;
+        }
+        DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
+        if (!DriverKey)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            goto cleanup;
+        }
+        rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
+        if (rc != ERROR_SUCCESS)
+        {
+            SetLastError(rc);
+            goto cleanup;
+        }
+        RegCloseKey(hKey);
+        hKey = INVALID_HANDLE_VALUE;
+        /* Need to open the driver key */
+        rc = RegOpenKeyExW(
+            RootKey,
+            REGSTR_PATH_CLASS_NT,
+            0, /* Options */
+            0,
+            &hEnumKey);
+        if (rc != ERROR_SUCCESS)
+        {
+            SetLastError(rc);
+            goto cleanup;
+        }
+        rc = RegOpenKeyExW(
+            hEnumKey,
+            DriverKey,
+            0, /* Options */
+            samDesired,
+            &hKey);
+        if (rc != ERROR_SUCCESS)
+        {
+            SetLastError(rc);
+            goto cleanup;
+        }
+        ret = hKey;
+
 cleanup:
-        if (hRootKey != INVALID_HANDLE_VALUE)
-            RegCloseKey(hRootKey);
+        if (hHWProfileKey != INVALID_HANDLE_VALUE)
+            RegCloseKey(hHWProfileKey);
+        if (hEnumKey != INVALID_HANDLE_VALUE)
+            RegCloseKey(hEnumKey);
         if (hKey != INVALID_HANDLE_VALUE && hKey != ret)
             RegCloseKey(hKey);
     }
@@ -5717,7 +5747,7 @@
                 list->HKLM,
                 REGSTR_PATH_SYSTEMENUM,
                 0, /* Options */
-                KEY_ENUMERATE_SUB_KEYS,
+                0,
                 &hEnumKey);
             if (rc != ERROR_SUCCESS)
             {
@@ -6461,11 +6491,39 @@
     return hwProfile;
 }
 
+static BOOL
+ResetDevice(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData)
+{
+    PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
+    struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+    NTSTATUS Status;
+
+    if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
+    {
+        /* At the moment, I only know how to start local devices */
+        SetLastError(ERROR_INVALID_COMPUTERNAME);
+        return FALSE;
+    }
+
+    RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, deviceInfo->DeviceName);
+    Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
+    SetLastError(RtlNtStatusToDosError(Status));
+    return NT_SUCCESS(Status);
+}
+
+static BOOL StopDevice(
+    IN HDEVINFO DeviceInfoSet,
+    IN PSP_DEVINFO_DATA DeviceInfoData)
+{
+    FIXME("Stub %p %p\n", DeviceInfoSet, DeviceInfoData);
+    return TRUE;
+}
+
 /***********************************************************************
  *		SetupDiChangeState (SETUPAPI.@)
  */
-static BOOL StartDevice(VOID) { FIXME("Stub"); return TRUE; }
-static BOOL StopDevice(VOID) { FIXME("Stub"); return TRUE; }
 BOOL WINAPI
 SetupDiChangeState(
     IN HDEVINFO DeviceInfoSet,
@@ -6503,7 +6561,7 @@
             /* Enable/disable device in registry */
             hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
             if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
-                hKey = SetupDiCreateDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
+                hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
             if (hKey == INVALID_HANDLE_VALUE)
                 break;
             dwLength = sizeof(DWORD);
@@ -6547,9 +6605,9 @@
                 || PropChange->HwProfile == GetCurrentHwProfile(DeviceInfoSet))
             {
                 if (PropChange->StateChange == DICS_ENABLE)
-                    ret = StartDevice();
+                    ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
                 else
-                    ret = StopDevice();
+                    ret = StopDevice(DeviceInfoSet, DeviceInfoData);
             }
             else
                 ret = TRUE;
@@ -6557,7 +6615,7 @@
         }
         case DICS_PROPCHANGE:
         {
-            ret = StopDevice() && StartDevice();
+            ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
             break;
         }
         default:
@@ -6837,7 +6895,6 @@
     IN HDEVINFO DeviceInfoSet,
     IN PSP_DEVINFO_DATA DeviceInfoData)
 {
-    struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
     SP_DEVINSTALL_PARAMS_W InstallParams;
     struct DriverInfoElement *SelectedDriver;
     SYSTEMTIME DriverDate;
@@ -7166,13 +7223,7 @@
 
     /* Start the device */
     if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
-    {
-        PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
-        NTSTATUS Status;
-        RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DevInfo->DeviceName);
-        Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
-        ret = NT_SUCCESS(Status);
-    }
+        ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
     else
         ret = TRUE;