Reactos

[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.

authored by

Jose Carlos Jesus and committed by
GitHub
45c8e4dc 015cd259

+194 -3
+9 -1
dll/win32/newdev/newdev.c
··· 359 359 wcscat(DirPath, L"\\"); 360 360 361 361 wcscpy(PathWithPattern, DirPath); 362 - wcscat(PathWithPattern, L"\\*"); 362 + wcscat(PathWithPattern, L"*"); 363 363 364 364 for (hFindFile = FindFirstFileW(PathWithPattern, &wfd); 365 365 ok && hFindFile != INVALID_HANDLE_VALUE; ··· 406 406 if (hFindFile != INVALID_HANDLE_VALUE) 407 407 FindClose(hFindFile); 408 408 return retval; 409 + } 410 + 411 + BOOL 412 + CheckBestDriver( 413 + _In_ PDEVINSTDATA DevInstData, 414 + _In_ PCWSTR pszDir) 415 + { 416 + return SearchDriverRecursive(DevInstData, pszDir); 409 417 } 410 418 411 419 BOOL
+5
dll/win32/newdev/newdev_private.h
··· 61 61 InstallCurrentDriver( 62 62 IN PDEVINSTDATA DevInstData); 63 63 64 + BOOL 65 + CheckBestDriver( 66 + _In_ PDEVINSTDATA DevInstData, 67 + _In_ PCWSTR pszDir); 68 + 64 69 /* wizard.c */ 65 70 BOOL 66 71 DisplayWizard(
+52 -2
dll/win32/newdev/wizard.c
··· 579 579 IncludePath(Dlg, Enabled & IsDlgButtonChecked(Dlg, IDC_CHECK_PATH)); 580 580 } 581 581 582 + static INT CALLBACK 583 + BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) 584 + { 585 + BOOL bValid = FALSE; 586 + 587 + switch (uMsg) 588 + { 589 + case BFFM_INITIALIZED: 590 + { 591 + PCWSTR pszPath = ((PDEVINSTDATA)lpData)->CustomSearchPath; 592 + 593 + bValid = CheckBestDriver((PDEVINSTDATA)lpData, pszPath); 594 + SendMessageW(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)pszPath); 595 + SendMessageW(hwnd, BFFM_ENABLEOK, 0, bValid); 596 + break; 597 + } 598 + 599 + case BFFM_SELCHANGED: 600 + { 601 + WCHAR szDir[MAX_PATH]; 602 + 603 + if (SHGetPathFromIDListW((LPITEMIDLIST)lParam, szDir)) 604 + { 605 + bValid = CheckBestDriver((PDEVINSTDATA)lpData, szDir); 606 + } 607 + PostMessageW(hwnd, BFFM_ENABLEOK, 0, bValid); 608 + break; 609 + } 610 + } 611 + return 0; 612 + } 613 + 582 614 static INT_PTR CALLBACK 583 615 CHSourceDlgProc( 584 616 IN HWND hwndDlg, ··· 651 683 652 684 case IDC_BROWSE: 653 685 { 654 - BROWSEINFO bi = { 0 }; 686 + BROWSEINFOW bi = { 0 }; 655 687 LPITEMIDLIST pidl; 656 688 WCHAR Title[MAX_PATH]; 689 + WCHAR CustomSearchPath[MAX_PATH] = { 0 }; 690 + INT len, idx = (INT)SendDlgItemMessageW(hwndDlg, IDC_COMBO_PATH, CB_GETCURSEL, 0, 0); 657 691 LoadStringW(hDllInstance, IDS_BROWSE_FOR_FOLDER_TITLE, Title, _countof(Title)); 658 692 693 + if (idx == CB_ERR) 694 + len = GetWindowTextLengthW(GetDlgItem(hwndDlg, IDC_COMBO_PATH)); 695 + else 696 + len = (INT)SendDlgItemMessageW(hwndDlg, IDC_COMBO_PATH, CB_GETLBTEXTLEN, idx, 0); 697 + 698 + if (len < _countof(CustomSearchPath)) 699 + { 700 + if (idx == CB_ERR) 701 + GetWindowTextW(GetDlgItem(hwndDlg, IDC_COMBO_PATH), CustomSearchPath, _countof(CustomSearchPath)); 702 + else 703 + SendDlgItemMessageW(hwndDlg, IDC_COMBO_PATH, CB_GETLBTEXT, idx, (LPARAM)CustomSearchPath); 704 + } 705 + DevInstData->CustomSearchPath = CustomSearchPath; 706 + 659 707 bi.hwndOwner = hwndDlg; 660 708 bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NONEWFOLDERBUTTON; 661 709 bi.lpszTitle = Title; 662 - pidl = SHBrowseForFolder(&bi); 710 + bi.lpfn = BrowseCallbackProc; 711 + bi.lParam = (LPARAM)DevInstData; 712 + pidl = SHBrowseForFolderW(&bi); 663 713 if (pidl) 664 714 { 665 715 WCHAR Directory[MAX_PATH];
+8
dll/win32/shell32/wine/brsfolder.c
··· 464 464 IShellFolder_Release(pSFChild); 465 465 } 466 466 } 467 + #ifdef __REACTOS__ 468 + if (ulAttrs != (ulAttrs & SFGAO_FOLDER)) 469 + { 470 + if (!InsertTreeViewItem(info, lpsf, pidlTemp, pidl, pEnumIL, hParent)) 471 + goto done; 472 + } 473 + #else 467 474 468 475 if (!InsertTreeViewItem(info, lpsf, pidlTemp, pidl, pEnumIL, hParent)) 469 476 goto done; 477 + #endif 470 478 SHFree(pidlTemp); /* Finally, free the pidl that the shell gave us... */ 471 479 pidlTemp=NULL; 472 480 }
+120
dll/win32/syssetup/wizard.c
··· 20 20 #include <windowsx.h> 21 21 #include <wincon.h> 22 22 #include <shlobj.h> 23 + #include <shlwapi.h> 23 24 #include <tzlib.h> 24 25 #include <strsafe.h> 25 26 ··· 2880 2881 } 2881 2882 } 2882 2883 2884 + static BOOL 2885 + PathIsEqual( 2886 + IN LPCWSTR lpPath1, 2887 + IN LPCWSTR lpPath2) 2888 + { 2889 + WCHAR szPath1[MAX_PATH]; 2890 + WCHAR szPath2[MAX_PATH]; 2891 + 2892 + /* If something goes wrong, better return TRUE, 2893 + * so the calling function returns early. 2894 + */ 2895 + if (!PathCanonicalizeW(szPath1, lpPath1)) 2896 + return TRUE; 2897 + 2898 + if (!PathAddBackslashW(szPath1)) 2899 + return TRUE; 2900 + 2901 + if (!PathCanonicalizeW(szPath2, lpPath2)) 2902 + return TRUE; 2903 + 2904 + if (!PathAddBackslashW(szPath2)) 2905 + return TRUE; 2906 + 2907 + return (_wcsicmp(szPath1, szPath2) == 0); 2908 + } 2909 + 2910 + static VOID 2911 + AddInstallationSource( 2912 + IN HKEY hKey, 2913 + IN LPWSTR lpPath) 2914 + { 2915 + LONG res; 2916 + DWORD dwRegType; 2917 + DWORD dwPathLength = 0; 2918 + DWORD dwNewLength = 0; 2919 + LPWSTR Buffer = NULL; 2920 + LPWSTR Path; 2921 + 2922 + res = RegQueryValueExW( 2923 + hKey, 2924 + L"Installation Sources", 2925 + NULL, 2926 + &dwRegType, 2927 + NULL, 2928 + &dwPathLength); 2929 + 2930 + if (res != ERROR_SUCCESS || 2931 + dwRegType != REG_MULTI_SZ || 2932 + dwPathLength == 0 || 2933 + dwPathLength % sizeof(WCHAR) != 0) 2934 + { 2935 + dwPathLength = 0; 2936 + goto set; 2937 + } 2938 + 2939 + /* Reserve space for existing data + new string */ 2940 + dwNewLength = dwPathLength + (wcslen(lpPath) + 1) * sizeof(WCHAR); 2941 + Buffer = HeapAlloc(GetProcessHeap(), 0, dwNewLength); 2942 + if (!Buffer) 2943 + return; 2944 + 2945 + ZeroMemory(Buffer, dwNewLength); 2946 + 2947 + res = RegQueryValueExW( 2948 + hKey, 2949 + L"Installation Sources", 2950 + NULL, 2951 + NULL, 2952 + (LPBYTE)Buffer, 2953 + &dwPathLength); 2954 + 2955 + if (res != ERROR_SUCCESS) 2956 + { 2957 + HeapFree(GetProcessHeap(), 0, Buffer); 2958 + dwPathLength = 0; 2959 + goto set; 2960 + } 2961 + 2962 + /* Sanity check, these should already be zeros */ 2963 + Buffer[dwPathLength / sizeof(WCHAR) - 2] = UNICODE_NULL; 2964 + Buffer[dwPathLength / sizeof(WCHAR) - 1] = UNICODE_NULL; 2965 + 2966 + for (Path = Buffer; *Path; Path += wcslen(Path) + 1) 2967 + { 2968 + /* Check if path is already added */ 2969 + if (PathIsEqual(Path, lpPath)) 2970 + goto cleanup; 2971 + } 2972 + 2973 + Path = Buffer + dwPathLength / sizeof(WCHAR) - 1; 2974 + 2975 + set: 2976 + if (dwPathLength == 0) 2977 + { 2978 + dwNewLength = (wcslen(lpPath) + 1 + 1) * sizeof(WCHAR); 2979 + Buffer = HeapAlloc(GetProcessHeap(), 0, dwNewLength); 2980 + if (!Buffer) 2981 + return; 2982 + 2983 + Path = Buffer; 2984 + } 2985 + 2986 + StringCbCopyW(Path, dwNewLength - (Path - Buffer) * sizeof(WCHAR), lpPath); 2987 + Buffer[dwNewLength / sizeof(WCHAR) - 1] = UNICODE_NULL; 2988 + 2989 + RegSetValueExW( 2990 + hKey, 2991 + L"Installation Sources", 2992 + 0, 2993 + REG_MULTI_SZ, 2994 + (LPBYTE)Buffer, 2995 + dwNewLength); 2996 + 2997 + cleanup: 2998 + HeapFree(GetProcessHeap(), 0, Buffer); 2999 + } 3000 + 2883 3001 VOID 2884 3002 ProcessSetupInf( 2885 3003 IN OUT PSETUPDATA pSetupData) ··· 2978 3096 NULL); 2979 3097 if (res == ERROR_SUCCESS) 2980 3098 { 3099 + AddInstallationSource(hKey, pSetupData->SourcePath); 3100 + 2981 3101 res = RegSetValueExW(hKey, 2982 3102 L"SourcePath", 2983 3103 0,