Allow the user to specify a custom path for the driver when installing a new device

svn path=/trunk/; revision=22051
This commit is contained in:
Hervé Poussineau 2006-05-26 10:16:27 +00:00
parent a10d9d8b2b
commit 57404cf7cf
3 changed files with 218 additions and 48 deletions

View 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] != '\\')

View file

@ -1,4 +1,5 @@
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <regstr.h>
#include <setupapi.h>

View 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)
{
LPCTSTR Path;
for (Path = DevInstData->CustomSearchPath; *Path != '\0'; Path += _tcslen(Path) + 1)
DPRINT1("Path %S\n", Path);
}
dwDrives = GetLogicalDrives();
for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++)
{
if (dwDrives & i)
{
nType = GetDriveType(drive);
if (nType == DRIVE_REMOVABLE || nType == DRIVE_CDROM)
{
/* search for valid inf file */
if (SearchDriverRecursive(DevInstData, drive))
{
InstallCurrentDriver(DevInstData);
PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 1, 0);
return 0;
}
}
}
i <<= 1;
}
/* update device configuration */
if (SetupDiGetDeviceRegistryProperty(
/* Yes, we can safely ignore the problem (if any) */
SetupDiDestroyDriverInfoList(
DevInstData->hDevInfo,
&DevInstData->devInfoData,
SPDRP_CONFIGFLAGS,
NULL,
(BYTE *)&config_flags,
sizeof(config_flags),
NULL))
SPDIT_COMPATDRIVER);
if (!DevInstData->CustomSearchPath)
{
config_flags |= CONFIGFLAG_FAILEDINSTALL;
SetupDiSetDeviceRegistryProperty(
/* Search in default location */
result = SearchDriver(DevInstData, NULL, NULL);
}
else
{
/* 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)
{
TRACE("Search driver in %S\n", Path);
if (_tcslen(Path) == 2 && Path[1] == ':')
{
if (SearchDriverRecursive(DevInstData, Path))
result = TRUE;
}
else
{
if (SearchDriver(DevInstData, Path, NULL))
result = TRUE;
}
}
}
if (result)
{
PostMessage(DevInstData->hDialog, WM_SEARCH_FINISHED, 1, 0);
}
else
{
/* 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;
}