[NEWDEV][SHELL32][SYSSETUP] Improve browse driver folder dialog (#4293)

[NEWDEV] Enable OK button in "Browse For Folder" only when driver is found

Implement BrowseCallbackProc() function which sends BFFM_ENABLEOK message
to the browse dialog whether the driver is found in the selected folder.

Pass the search path to the browse dialog depending on the current index
of the drop down combobox. If the index is not set, just get window text.
Then, automatically expand the tree view to the specified path by sending
BFFM_SETSELECTION message.

Also fix a bug in SearchDriverRecursive() where a duplicate backslash
was added to the PathWithPattern string variable.

[SHELL32] Do not add Recycle Bin to the tree view items in FillTreeView()

[SYSSETUP] Add source path to the "Installation Sources" multi-string key

Each time the ProcessSetupInf() is being called, add the source path
to the "Installation Sources" registry key, if it's not added there yet.
The driver search path combobox will be then populated using its value.
This commit is contained in:
Jose Carlos Jesus 2022-11-27 15:00:46 +00:00 committed by GitHub
parent 015cd2596c
commit 45c8e4dcd0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 194 additions and 3 deletions

View file

@ -359,7 +359,7 @@ SearchDriverRecursive(
wcscat(DirPath, L"\\");
wcscpy(PathWithPattern, DirPath);
wcscat(PathWithPattern, L"\\*");
wcscat(PathWithPattern, L"*");
for (hFindFile = FindFirstFileW(PathWithPattern, &wfd);
ok && hFindFile != INVALID_HANDLE_VALUE;
@ -408,6 +408,14 @@ SearchDriverRecursive(
return retval;
}
BOOL
CheckBestDriver(
_In_ PDEVINSTDATA DevInstData,
_In_ PCWSTR pszDir)
{
return SearchDriverRecursive(DevInstData, pszDir);
}
BOOL
ScanFoldersForDriver(
IN PDEVINSTDATA DevInstData)

View file

@ -61,6 +61,11 @@ BOOL
InstallCurrentDriver(
IN PDEVINSTDATA DevInstData);
BOOL
CheckBestDriver(
_In_ PDEVINSTDATA DevInstData,
_In_ PCWSTR pszDir);
/* wizard.c */
BOOL
DisplayWizard(

View file

@ -579,6 +579,38 @@ AutoDriver(HWND Dlg, BOOL Enabled)
IncludePath(Dlg, Enabled & IsDlgButtonChecked(Dlg, IDC_CHECK_PATH));
}
static INT CALLBACK
BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
BOOL bValid = FALSE;
switch (uMsg)
{
case BFFM_INITIALIZED:
{
PCWSTR pszPath = ((PDEVINSTDATA)lpData)->CustomSearchPath;
bValid = CheckBestDriver((PDEVINSTDATA)lpData, pszPath);
SendMessageW(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)pszPath);
SendMessageW(hwnd, BFFM_ENABLEOK, 0, bValid);
break;
}
case BFFM_SELCHANGED:
{
WCHAR szDir[MAX_PATH];
if (SHGetPathFromIDListW((LPITEMIDLIST)lParam, szDir))
{
bValid = CheckBestDriver((PDEVINSTDATA)lpData, szDir);
}
PostMessageW(hwnd, BFFM_ENABLEOK, 0, bValid);
break;
}
}
return 0;
}
static INT_PTR CALLBACK
CHSourceDlgProc(
IN HWND hwndDlg,
@ -651,15 +683,33 @@ CHSourceDlgProc(
case IDC_BROWSE:
{
BROWSEINFO bi = { 0 };
BROWSEINFOW bi = { 0 };
LPITEMIDLIST pidl;
WCHAR Title[MAX_PATH];
WCHAR CustomSearchPath[MAX_PATH] = { 0 };
INT len, idx = (INT)SendDlgItemMessageW(hwndDlg, IDC_COMBO_PATH, CB_GETCURSEL, 0, 0);
LoadStringW(hDllInstance, IDS_BROWSE_FOR_FOLDER_TITLE, Title, _countof(Title));
if (idx == CB_ERR)
len = GetWindowTextLengthW(GetDlgItem(hwndDlg, IDC_COMBO_PATH));
else
len = (INT)SendDlgItemMessageW(hwndDlg, IDC_COMBO_PATH, CB_GETLBTEXTLEN, idx, 0);
if (len < _countof(CustomSearchPath))
{
if (idx == CB_ERR)
GetWindowTextW(GetDlgItem(hwndDlg, IDC_COMBO_PATH), CustomSearchPath, _countof(CustomSearchPath));
else
SendDlgItemMessageW(hwndDlg, IDC_COMBO_PATH, CB_GETLBTEXT, idx, (LPARAM)CustomSearchPath);
}
DevInstData->CustomSearchPath = CustomSearchPath;
bi.hwndOwner = hwndDlg;
bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NONEWFOLDERBUTTON;
bi.lpszTitle = Title;
pidl = SHBrowseForFolder(&bi);
bi.lpfn = BrowseCallbackProc;
bi.lParam = (LPARAM)DevInstData;
pidl = SHBrowseForFolderW(&bi);
if (pidl)
{
WCHAR Directory[MAX_PATH];

View file

@ -464,9 +464,17 @@ static void FillTreeView( browse_info *info, IShellFolder * lpsf,
IShellFolder_Release(pSFChild);
}
}
#ifdef __REACTOS__
if (ulAttrs != (ulAttrs & SFGAO_FOLDER))
{
if (!InsertTreeViewItem(info, lpsf, pidlTemp, pidl, pEnumIL, hParent))
goto done;
}
#else
if (!InsertTreeViewItem(info, lpsf, pidlTemp, pidl, pEnumIL, hParent))
goto done;
#endif
SHFree(pidlTemp); /* Finally, free the pidl that the shell gave us... */
pidlTemp=NULL;
}

View file

@ -20,6 +20,7 @@
#include <windowsx.h>
#include <wincon.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <tzlib.h>
#include <strsafe.h>
@ -2880,6 +2881,123 @@ ProcessUnattendSection(
}
}
static BOOL
PathIsEqual(
IN LPCWSTR lpPath1,
IN LPCWSTR lpPath2)
{
WCHAR szPath1[MAX_PATH];
WCHAR szPath2[MAX_PATH];
/* If something goes wrong, better return TRUE,
* so the calling function returns early.
*/
if (!PathCanonicalizeW(szPath1, lpPath1))
return TRUE;
if (!PathAddBackslashW(szPath1))
return TRUE;
if (!PathCanonicalizeW(szPath2, lpPath2))
return TRUE;
if (!PathAddBackslashW(szPath2))
return TRUE;
return (_wcsicmp(szPath1, szPath2) == 0);
}
static VOID
AddInstallationSource(
IN HKEY hKey,
IN LPWSTR lpPath)
{
LONG res;
DWORD dwRegType;
DWORD dwPathLength = 0;
DWORD dwNewLength = 0;
LPWSTR Buffer = NULL;
LPWSTR Path;
res = RegQueryValueExW(
hKey,
L"Installation Sources",
NULL,
&dwRegType,
NULL,
&dwPathLength);
if (res != ERROR_SUCCESS ||
dwRegType != REG_MULTI_SZ ||
dwPathLength == 0 ||
dwPathLength % sizeof(WCHAR) != 0)
{
dwPathLength = 0;
goto set;
}
/* Reserve space for existing data + new string */
dwNewLength = dwPathLength + (wcslen(lpPath) + 1) * sizeof(WCHAR);
Buffer = HeapAlloc(GetProcessHeap(), 0, dwNewLength);
if (!Buffer)
return;
ZeroMemory(Buffer, dwNewLength);
res = RegQueryValueExW(
hKey,
L"Installation Sources",
NULL,
NULL,
(LPBYTE)Buffer,
&dwPathLength);
if (res != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, Buffer);
dwPathLength = 0;
goto set;
}
/* Sanity check, these should already be zeros */
Buffer[dwPathLength / sizeof(WCHAR) - 2] = UNICODE_NULL;
Buffer[dwPathLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
for (Path = Buffer; *Path; Path += wcslen(Path) + 1)
{
/* Check if path is already added */
if (PathIsEqual(Path, lpPath))
goto cleanup;
}
Path = Buffer + dwPathLength / sizeof(WCHAR) - 1;
set:
if (dwPathLength == 0)
{
dwNewLength = (wcslen(lpPath) + 1 + 1) * sizeof(WCHAR);
Buffer = HeapAlloc(GetProcessHeap(), 0, dwNewLength);
if (!Buffer)
return;
Path = Buffer;
}
StringCbCopyW(Path, dwNewLength - (Path - Buffer) * sizeof(WCHAR), lpPath);
Buffer[dwNewLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
RegSetValueExW(
hKey,
L"Installation Sources",
0,
REG_MULTI_SZ,
(LPBYTE)Buffer,
dwNewLength);
cleanup:
HeapFree(GetProcessHeap(), 0, Buffer);
}
VOID
ProcessSetupInf(
IN OUT PSETUPDATA pSetupData)
@ -2978,6 +3096,8 @@ ProcessSetupInf(
NULL);
if (res == ERROR_SUCCESS)
{
AddInstallationSource(hKey, pSetupData->SourcePath);
res = RegSetValueExW(hKey,
L"SourcePath",
0,