Allow the user to specify a custom path for the driver when installing a new device
authorHervé Poussineau <hpoussin@reactos.org>
Fri, 26 May 2006 10:16:27 +0000 (10:16 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Fri, 26 May 2006 10:16:27 +0000 (10:16 +0000)
svn path=/trunk/; revision=22051

reactos/dll/win32/newdev/newdev.c
reactos/dll/win32/newdev/newdev.h
reactos/dll/win32/newdev/wizard.c

index 3b80b45..7019c5d 100644 (file)
@@ -350,7 +350,6 @@ SearchDriverRecursive(
        BOOL retval = FALSE;
        HANDLE hFindFile = INVALID_HANDLE_VALUE;
 
-       TRACE("SearchDriverRecursive(%s)\n", Path);
        _tcscpy(DirPath, Path);
 
        if (DirPath[_tcsclen(DirPath) - 1] != '\\')
index 0f4e1e4..dcb8ceb 100644 (file)
@@ -1,4 +1,5 @@
 #include <windows.h>
+#include <windowsx.h>
 #include <commctrl.h>
 #include <regstr.h>
 #include <setupapi.h>
index fc617e1..6481a32 100644 (file)
@@ -182,8 +182,83 @@ PrepareFoldersToScan(
        IN PDEVINSTDATA DevInstData,
        IN HWND hwndDlg)
 {
-       FIXME("Include removable devices: %s\n", IsDlgButtonChecked(hwndDlg, IDC_CHECK_MEDIA) ? "yes" : "no");
-       FIXME("Include custom path      : %s\n", IsDlgButtonChecked(hwndDlg, IDC_CHECK_PATH) ? "yes" : "no");
+       TCHAR drive[] = {'?',':',0};
+       DWORD dwDrives = 0;
+       DWORD i;
+       UINT nType;
+       DWORD CustomTextLength = 0;
+       DWORD LengthNeeded = 0;
+       LPTSTR Buffer;
+
+       TRACE("Include removable devices: %s\n", IsDlgButtonChecked(hwndDlg, IDC_CHECK_MEDIA) ? "yes" : "no");
+       TRACE("Include custom path      : %s\n", IsDlgButtonChecked(hwndDlg, IDC_CHECK_PATH) ? "yes" : "no");
+
+       /* Calculate length needed to store the search paths */
+       if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_MEDIA))
+       {
+               dwDrives = GetLogicalDrives();
+               for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1)
+               {
+                       if (dwDrives & i)
+                       {
+                               nType = GetDriveType(drive);
+                               if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM)
+                               {
+                                       LengthNeeded += 3;
+                               }
+                       }
+               }
+       }
+       if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_PATH))
+       {
+               CustomTextLength = 1 + SendDlgItemMessage(
+                       hwndDlg,
+                       IDC_COMBO_PATH,
+                       WM_GETTEXTLENGTH,
+                       (WPARAM)0,
+                       (LPARAM)0);
+               LengthNeeded += CustomTextLength;
+       }
+
+       /* Allocate space for search paths */
+       HeapFree(GetProcessHeap(), 0, DevInstData->CustomSearchPath);
+       DevInstData->CustomSearchPath = Buffer = HeapAlloc(
+               GetProcessHeap(),
+               0,
+               (LengthNeeded + 1) * sizeof(TCHAR));
+       if (!Buffer)
+       {
+               TRACE("HeapAlloc() failed\n");
+               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+               return FALSE;
+       }
+
+       /* Fill search paths */
+       if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_MEDIA))
+       {
+               for (drive[0] = 'A', i = 1; drive[0] <= 'Z'; drive[0]++, i <<= 1)
+               {
+                       if (dwDrives & i)
+                       {
+                               nType = GetDriveType(drive);
+                               if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM)
+                               {
+                                       Buffer += 1 + _stprintf(Buffer, drive);
+                               }
+                       }
+               }
+       }
+       if (IsDlgButtonChecked(hwndDlg, IDC_CHECK_PATH))
+       {
+               Buffer += 1 + SendDlgItemMessage(
+                       hwndDlg,
+                       IDC_COMBO_PATH,
+                       WM_GETTEXT,
+                       (WPARAM)CustomTextLength,
+                       (LPARAM)Buffer);
+       }
+       *Buffer = _T('\0');
+
        return TRUE;
 }
 
@@ -191,64 +266,151 @@ static DWORD WINAPI
 FindDriverProc(
        IN LPVOID lpParam)
 {
-       TCHAR drive[] = {'?',':',0};
-       size_t nType;
-       DWORD dwDrives;
        PDEVINSTDATA DevInstData;
        DWORD config_flags;
-       UINT i = 1;
+       BOOL result = FALSE;
 
        DevInstData = (PDEVINSTDATA)lpParam;
-       DPRINT1("FindDriverProc(%p)\n", DevInstData->CustomSearchPath);
-       if (DevInstData->CustomSearchPath)
+
+       /* Yes, we can safely ignore the problem (if any) */
+       SetupDiDestroyDriverInfoList(
+               DevInstData->hDevInfo,
+               &DevInstData->devInfoData,
+               SPDIT_COMPATDRIVER);
+
+       if (!DevInstData->CustomSearchPath)
        {
-               LPCTSTR Path;
-               for (Path = DevInstData->CustomSearchPath; *Path != '\0'; Path += _tcslen(Path) + 1)
-                       DPRINT1("Path %S\n", Path);
+               /* Search in default location */
+               result = SearchDriver(DevInstData, NULL, NULL);
        }
-
-       dwDrives = GetLogicalDrives();
-       for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
+       else
        {
-               if (dwDrives & i)
+               /* Search only in specified paths */
+               /* We need to check all specified directories to be
+                * sure to find the best driver for the device.
+                */
+               LPCTSTR Path;
+               for (Path = DevInstData->CustomSearchPath; *Path != '\0'; Path += _tcslen(Path) + 1)
                {
-                       nType = GetDriveType(drive);
-                       if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM)
+                       TRACE("Search driver in %S\n", Path);
+                       if (_tcslen(Path) == 2 && Path[1] == ':')
                        {
-                               /* search for valid inf file */
-                               if (SearchDriverRecursive(DevInstData, drive))
-                               {
-                                       InstallCurrentDriver(DevInstData);
-                                       PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 1, 0);
-                                       return 0;
-                               }
+                               if (SearchDriverRecursive(DevInstData, Path))
+                                       result = TRUE;
+                       }
+                       else
+                       {
+                               if (SearchDriver(DevInstData, Path, NULL))
+                                       result = TRUE;
                        }
                }
-               i <<= 1;
        }
 
-       /* update device configuration */
-       if (SetupDiGetDeviceRegistryProperty(
-               DevInstData->hDevInfo,
-               &DevInstData->devInfoData,
-               SPDRP_CONFIGFLAGS,
-               NULL,
-               (BYTE *)&config_flags,
-               sizeof(config_flags),
-               NULL))
+       if (result)
+       {
+               PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 1, 0);
+       }
+       else
        {
-               config_flags |= CONFIGFLAG_FAILEDINSTALL;
-               SetupDiSetDeviceRegistryProperty(
+               /* Update device configuration */
+               if (SetupDiGetDeviceRegistryProperty(
                        DevInstData->hDevInfo,
                        &DevInstData->devInfoData,
                        SPDRP_CONFIGFLAGS,
-                       (BYTE *)&config_flags, sizeof(config_flags));
-       }
+                       NULL,
+                       (BYTE *)&config_flags,
+                       sizeof(config_flags),
+                       NULL))
+               {
+                       config_flags |= CONFIGFLAG_FAILEDINSTALL;
+                       SetupDiSetDeviceRegistryProperty(
+                               DevInstData->hDevInfo,
+                               &DevInstData->devInfoData,
+                               SPDRP_CONFIGFLAGS,
+                               (BYTE *)&config_flags, sizeof(config_flags));
+               }
 
-       PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 0, 0);
+               PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 0, 0);
+       }
        return 0;
 }
 
+static VOID
+PopulateCustomPathCombo(
+       IN HWND hwndCombo)
+{
+       HKEY hKey = NULL;
+       DWORD dwRegType;
+       DWORD dwPathLength;
+       LPTSTR Buffer = NULL;
+       LPCTSTR Path;
+       LONG rc;
+
+       ComboBox_ResetContent(hwndCombo);
+
+       /* RegGetValue would have been better... */
+       rc = RegOpenKeyEx(
+               HKEY_LOCAL_MACHINE,
+               REGSTR_PATH_SETUP REGSTR_KEY_SETUP,
+               0,
+               KEY_QUERY_VALUE,
+               &hKey);
+       if (rc != ERROR_SUCCESS)
+       {
+               TRACE("RegOpenKeyEx() failed with error 0x%lx\n", rc);
+               goto cleanup;
+       }
+       rc = RegQueryValueEx(
+               hKey,
+               _T("Installation Sources"),
+               NULL,
+               &dwRegType,
+               NULL,
+               &dwPathLength);
+       if (rc != ERROR_SUCCESS || dwRegType != REG_MULTI_SZ)
+       {
+               TRACE("RegQueryValueEx() failed with error 0x%lx\n", rc);
+               goto cleanup;
+       }
+       /* Allocate enough space to add 2 NULL chars at the end of the string */
+       Buffer = HeapAlloc(GetProcessHeap(), 0, dwPathLength + 2 * sizeof(TCHAR));
+       if (!Buffer)
+       {
+               TRACE("HeapAlloc() failed\n");
+               goto cleanup;
+       }
+       rc = RegQueryValueEx(
+               hKey,
+               _T("Installation Sources"),
+               NULL,
+               NULL,
+               (LPBYTE)Buffer,
+               &dwPathLength);
+       if (rc != ERROR_SUCCESS)
+       {
+               TRACE("RegQueryValueEx() failed with error 0x%lx\n", rc);
+               goto cleanup;
+       }
+       Buffer[dwPathLength] = Buffer[dwPathLength + 1] = '\0';
+
+       /* Populate combo box */
+       for (Path = Buffer; *Path; Path += _tcslen(Path))
+               ComboBox_AddString(hwndCombo, Path);
+       ComboBox_SetCurSel(hwndCombo, 0);
+
+cleanup:
+       if (hKey != NULL)
+               RegCloseKey(hKey);
+       HeapFree(GetProcessHeap(), 0, Buffer);
+}
+
+static VOID
+SaveCustomPath(
+       IN HWND hwndCombo)
+{
+       FIXME("Stub.");
+}
+
 static INT_PTR CALLBACK
 WelcomeDlgProc(
        IN HWND hwndDlg,
@@ -382,6 +544,8 @@ CHSourceDlgProc(
                        dwStyle = GetWindowLong(hwndControl, GWL_STYLE);
                        SetWindowLong(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
 
+                       PopulateCustomPathCombo(GetDlgItem(hwndDlg, IDC_COMBO_PATH));
+
                        SendDlgItemMessage(
                                hwndDlg,
                                IDC_RADIO_SEARCHHERE,
@@ -393,8 +557,7 @@ CHSourceDlgProc(
 
                        /* Disable manual driver choice for now */
                        EnableWindow(GetDlgItem(hwndDlg, IDC_RADIO_CHOOSE), FALSE);
-                       /* Disable custom path for now */
-                       EnableWindow(GetDlgItem(hwndDlg, IDC_CHECK_PATH), FALSE);
+
                        break;
                }
 
@@ -437,10 +600,13 @@ CHSourceDlgProc(
                                        /* Handle a Next button click, if necessary */
                                        if (IsDlgButtonChecked(hwndDlg, IDC_RADIO_SEARCHHERE))
                                        {
+                                               SaveCustomPath(GetDlgItem(hwndDlg, IDC_COMBO_PATH));
                                                HeapFree(GetProcessHeap(), 0, DevInstData->CustomSearchPath);
                                                DevInstData->CustomSearchPath = NULL;
                                                if (PrepareFoldersToScan(DevInstData, hwndDlg))
                                                        PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_SEARCHDRV);
+                                               else
+                                                       /* FIXME: unknown error */;
                                        }
                                        else
                                                /* FIXME */;
@@ -509,7 +675,11 @@ SearchDrvDlgProc(
                        if (wParam == 0)
                                PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_NODRIVER);
                        else
+                       {
+                               /* FIXME: Shouldn't belong here... */
+                               InstallCurrentDriver(DevInstData);
                                PropSheet_SetCurSelByID(GetParent(hwndDlg), IDD_FINISHPAGE);
+                       }
                        break;
                }