[BROWSEUI][SHELL32] Implement BrowseObject flags (#7086)

* [BROWSEUI][SHELL32] Implement BrowseObject flags

Respect CABINETSTATE::fNewWindowMode if no other flags are relevant
This commit is contained in:
Whindmar Saksit 2024-07-09 20:00:54 +02:00 committed by GitHub
parent a629258e4a
commit 5b78381a53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 172 additions and 26 deletions

View file

@ -366,10 +366,23 @@ static HRESULT ExplorerMessageLoop(IEThreadParamBlock * parameters)
}
CComPtr<IShellBrowser> psb;
#if 0
if (!(parameters->dwFlags & (SH_EXPLORER_CMDLINE_FLAG_E | SH_EXPLORER_CMDLINE_FLAG_NOREUSE)))
{
// TODO: IShellWindows::FindWindowSW(...) and reuse the existing IShellBrowser
}
#endif
hResult = CShellBrowser_CreateInstance(IID_PPV_ARG(IShellBrowser, &psb));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
if (parameters->dwFlags & SH_EXPLORER_CMDLINE_FLAG_EMBED)
{
CComPtr<IBrowserService> pbs;
if (SUCCEEDED(psb->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs))))
pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION);
}
hResult = psb->BrowseObject(parameters->directoryPIDL, wFlags);
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;

View file

@ -259,7 +259,7 @@ SHExplorerParseCmdLine(_Out_ PEXPLORER_CMDLINE_PARSE_RESULTS pInfo)
// Basic flags-only params first
if (!StrCmpIW(strField, L"/N"))
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_N | SH_EXPLORER_CMDLINE_FLAG_ONE;
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_NEWWND | SH_EXPLORER_CMDLINE_FLAG_NOREUSE;
TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
}
else if (!StrCmpIW(strField, L"/S"))

View file

@ -120,6 +120,7 @@ static const unsigned int folderOptionsPageCountMax = 20;
static const long BTP_DONT_UPDATE_HISTORY = 0;
static const long BTP_UPDATE_CUR_HISTORY = 1;
static const long BTP_UPDATE_NEXT_HISTORY = 2;
static const long BTP_ACTIVATE_NOFOCUS = 0x04;
BOOL createNewStuff = false;
@ -306,6 +307,7 @@ private:
HACCEL m_hAccel;
ShellSettings m_settings;
SBFOLDERSETTINGS m_deffoldersettings;
DWORD m_BrowserSvcFlags;
public:
#if 0
ULONG InternalAddRef()
@ -324,6 +326,9 @@ public:
~CShellBrowser();
HRESULT Initialize();
public:
UINT ApplyNewBrowserFlag(UINT Flags);
HRESULT OpenNewBrowserWindow(LPCITEMIDLIST pidl, UINT SbspFlags);
HRESULT CreateRelativeBrowsePIDL(LPCITEMIDLIST relative, UINT SbspFlags, LPITEMIDLIST *ppidl);
HRESULT BrowseToPIDL(LPCITEMIDLIST pidl, long flags);
HRESULT BrowseToPath(IShellFolder *newShellFolder, LPCITEMIDLIST absolutePIDL,
FOLDERSETTINGS *folderSettings, long flags);
@ -629,6 +634,7 @@ public:
LRESULT OnRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
LRESULT OnExplorerBar(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL &bHandled);
LRESULT RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnCabinetStateChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnSettingsChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnGetSettingsPtr(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnAppCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
@ -683,6 +689,7 @@ public:
COMMAND_RANGE_HANDLER(IDM_GOTO_TRAVEL_FIRSTTARGET, IDM_GOTO_TRAVEL_LASTTARGET, OnGoTravel)
COMMAND_RANGE_HANDLER(IDM_EXPLORERBAND_BEGINCUSTOM, IDM_EXPLORERBAND_ENDCUSTOM, OnExplorerBar)
MESSAGE_HANDLER(WM_COMMAND, RelayCommands)
MESSAGE_HANDLER(CWM_STATECHANGE, OnCabinetStateChange)
MESSAGE_HANDLER(BWM_SETTINGCHANGE, OnSettingsChange)
MESSAGE_HANDLER(BWM_GETSETTINGSPTR, OnGetSettingsPtr)
MESSAGE_HANDLER(WM_APPCOMMAND, OnAppCommand)
@ -719,6 +726,7 @@ extern HRESULT CreateProgressDialog(REFIID riid, void **ppv);
CShellBrowser::CShellBrowser()
{
m_BrowserSvcFlags = BSF_RESIZABLE | BSF_CANMAXIMIZE;
fCurrentShellViewWindow = NULL;
fCurrentDirectoryPIDL = NULL;
fStatusBar = NULL;
@ -729,6 +737,7 @@ CShellBrowser::CShellBrowser()
m_settings.Load();
m_deffoldersettings.Load();
gCabinetState.Load();
SetTopBrowser();
}
CShellBrowser::~CShellBrowser()
@ -821,6 +830,52 @@ HRESULT CShellBrowser::ApplyBrowserDefaultFolderSettings(IShellView *pvs)
return hr;
}
UINT CShellBrowser::ApplyNewBrowserFlag(UINT Flags)
{
if ((Flags & (SBSP_SAMEBROWSER | SBSP_NEWBROWSER)) == SBSP_DEFBROWSER)
{
if (!fCurrentDirectoryPIDL || IsControlWindowShown(FCW_TREE, NULL) == S_OK)
Flags |= SBSP_SAMEBROWSER; // Force if this is the first navigation or the folder tree is present
else
Flags |= (!!gCabinetState.fNewWindowMode) ^ (GetAsyncKeyState(VK_CONTROL) < 0) ? SBSP_NEWBROWSER : SBSP_SAMEBROWSER;
}
if (Flags & (SBSP_NAVIGATEBACK | SBSP_NAVIGATEFORWARD))
Flags = (Flags & ~SBSP_NEWBROWSER) | SBSP_SAMEBROWSER; // Force same browser for now
return Flags;
}
HRESULT CShellBrowser::OpenNewBrowserWindow(LPCITEMIDLIST pidl, UINT SbspFlags)
{
SaveITBarLayout(); // Do this now so the new window inherits the current layout
// TODO: www.geoffchappell.com/studies/windows/ie/shdocvw/interfaces/inotifyappstart.htm
DWORD flags = (SbspFlags & SBSP_EXPLOREMODE) ? SH_EXPLORER_CMDLINE_FLAG_E : 0;
if ((SbspFlags & (SBSP_OPENMODE | SBSP_EXPLOREMODE)) == SBSP_DEFMODE)
flags |= IsControlWindowShown(FCW_TREE, NULL) == S_OK ? SH_EXPLORER_CMDLINE_FLAG_E : 0;
LPITEMIDLIST pidlDir;
HRESULT hr = SHILClone(pidl, &pidlDir);
if (FAILED(hr))
return hr;
// TODO: !SBSP_NOTRANSFERHIST means we are supposed to pass the history here somehow?
return SHOpenNewFrame(pidlDir, NULL, 0, flags | SH_EXPLORER_CMDLINE_FLAG_NEWWND | SH_EXPLORER_CMDLINE_FLAG_NOREUSE);
}
HRESULT CShellBrowser::CreateRelativeBrowsePIDL(LPCITEMIDLIST relative, UINT SbspFlags, LPITEMIDLIST *ppidl)
{
if (SbspFlags & SBSP_RELATIVE)
return SHILCombine(fCurrentDirectoryPIDL, relative, ppidl);
if (SbspFlags & SBSP_PARENT)
{
HRESULT hr = GetPidl(ppidl);
if (FAILED(hr))
return hr;
ILRemoveLastID(*ppidl);
return S_OK;
}
// TODO: SBSP_NAVIGATEBACK and SBSP_NAVIGATEFORWARD?
return E_UNEXPECTED;
}
HRESULT CShellBrowser::BrowseToPIDL(LPCITEMIDLIST pidl, long flags)
{
CComPtr<IShellFolder> newFolder;
@ -955,6 +1010,7 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
wchar_t newTitle[MAX_PATH];
SHGDNF nameFlags;
HRESULT hResult;
//TODO: BOOL nohistory = m_BrowserSvcFlags & BSF_NAVNOHISTORY;
if (newShellFolder == NULL)
return E_INVALIDARG;
@ -1036,7 +1092,7 @@ HRESULT CShellBrowser::BrowseToPath(IShellFolder *newShellFolder,
saveCurrentShellView.Release();
saveCurrentShellFolder.Release();
hResult = newShellView->UIActivate(SVUIA_ACTIVATE_FOCUS);
hResult = newShellView->UIActivate((flags & BTP_ACTIVATE_NOFOCUS) ? SVUIA_ACTIVATE_NOFOCUS : SVUIA_ACTIVATE_FOCUS);
// leave updating section
if (windowUpdateIsLocked)
@ -2257,12 +2313,39 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::TranslateAcceleratorSB(MSG *pmsg, WORD
HRESULT STDMETHODCALLTYPE CShellBrowser::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
{
if ((wFlags & SBSP_EXPLOREMODE) != NULL)
wFlags = ApplyNewBrowserFlag(wFlags);
// FIXME: Should not automatically show the Explorer band
if ((wFlags & SBSP_EXPLOREMODE) && !(wFlags & SBSP_NEWBROWSER))
ShowBand(CLSID_ExplorerBand, true);
CComHeapPtr<ITEMIDLIST> pidlResolved;
if (wFlags & (SBSP_RELATIVE | SBSP_PARENT))
{
HRESULT hr = CreateRelativeBrowsePIDL(pidl, wFlags, &pidlResolved);
if (FAILED(hr))
return hr;
pidl = pidlResolved;
}
if (wFlags & SBSP_NEWBROWSER)
return OpenNewBrowserWindow(pidl, wFlags);
switch (wFlags & (SBSP_ABSOLUTE | SBSP_RELATIVE | SBSP_PARENT | SBSP_NAVIGATEBACK | SBSP_NAVIGATEFORWARD))
{
case SBSP_PARENT:
return NavigateToParent();
case SBSP_NAVIGATEBACK:
return GoBack();
case SBSP_NAVIGATEFORWARD:
return GoForward();
}
// TODO: SBSP_WRITENOHISTORY? SBSP_CREATENOHISTORY?
long flags = BTP_UPDATE_NEXT_HISTORY;
if (fTravelLog)
flags |= BTP_UPDATE_CUR_HISTORY;
if (wFlags & SBSP_ACTIVATE_NOFOCUS)
flags |= BTP_ACTIVATE_NOFOCUS;
return BrowseToPIDL(pidl, flags);
}
@ -2555,7 +2638,7 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::DisplayParseError(HRESULT hres, LPCWSTR
HRESULT STDMETHODCALLTYPE CShellBrowser::NavigateToPidl(LPCITEMIDLIST pidl, DWORD grfHLNF)
{
return E_NOTIMPL;
return _NavigateToPidl(pidl, grfHLNF, 0);
}
HRESULT STDMETHODCALLTYPE CShellBrowser::SetNavigateState(BNSTATE bnstate)
@ -2585,12 +2668,14 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::UpdateBackForwardState()
HRESULT STDMETHODCALLTYPE CShellBrowser::SetFlags(DWORD dwFlags, DWORD dwFlagMask)
{
return E_NOTIMPL;
m_BrowserSvcFlags = (m_BrowserSvcFlags & ~dwFlagMask) | (dwFlags & dwFlagMask);
return S_OK;
}
HRESULT STDMETHODCALLTYPE CShellBrowser::GetFlags(DWORD *pdwFlags)
{
return E_NOTIMPL;
*pdwFlags = m_BrowserSvcFlags;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CShellBrowser::CanNavigateNow()
@ -2771,7 +2856,8 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::InitializeTravelLog(ITravelLog *ptl, DW
HRESULT STDMETHODCALLTYPE CShellBrowser::SetTopBrowser()
{
return E_NOTIMPL;
m_BrowserSvcFlags |= BSF_TOPBROWSER;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CShellBrowser::Offline(int iCmd)
@ -2836,6 +2922,16 @@ HRESULT STDMETHODCALLTYPE CShellBrowser::_DisableModeless()
HRESULT STDMETHODCALLTYPE CShellBrowser::_NavigateToPidl(LPCITEMIDLIST pidl, DWORD grfHLNF, DWORD dwFlags)
{
const UINT navflags = HLNF_NAVIGATINGBACK | HLNF_NAVIGATINGFORWARD;
if ((grfHLNF & navflags) && grfHLNF != ~0ul)
{
UINT SbspFlags = (grfHLNF & HLNF_NAVIGATINGBACK) ? SBSP_NAVIGATEBACK : SBSP_NAVIGATEFORWARD;
if (grfHLNF & SHHLNF_WRITENOHISTORY)
SbspFlags |= SBSP_WRITENOHISTORY;
if (grfHLNF & SHHLNF_NOAUTOSELECT)
SbspFlags |= SBSP_NOAUTOSELECT;
return BrowseObject(pidl, SbspFlags);
}
return E_NOTIMPL;
}
@ -3931,6 +4027,12 @@ LRESULT CShellBrowser::RelayCommands(UINT uMsg, WPARAM wParam, LPARAM lParam, BO
return 0;
}
LRESULT CShellBrowser::OnCabinetStateChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
RefreshCabinetState();
return 0;
}
LRESULT CShellBrowser::OnSettingsChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
/* Refresh child windows */
@ -4001,7 +4103,7 @@ void CShellBrowser::UpdateWindowTitle()
void CShellBrowser::SaveITBarLayout()
{
if (!gCabinetState.fSaveLocalView)
if (!gCabinetState.fSaveLocalView || (m_BrowserSvcFlags & (BSF_THEATERMODE | BSF_UISETBYAUTOMATION)))
return;
#if 0 // If CDesktopBrowser aggregates us, skip saving
FOLDERSETTINGS fs;

View file

@ -167,10 +167,12 @@ HRESULT STDMETHODCALLTYPE CTravelEntry::Update(IUnknown *punk, BOOL fIsLocalAnch
TRACE("CTravelEntry::Update for IUnknown punk=%p, fIsLocalAnchor=%s\n", punk, fIsLocalAnchor ? "TRUE" : "FALSE");
WCHAR wch[MAX_PATH * 2];
GetToolTipText(punk, wch);
TRACE("Updating entry with display name: %S\n", wch);
if (TRACE_ON(browseui))
{
WCHAR wch[MAX_PATH * 2];
GetToolTipText(punk, wch);
TRACE("Updating entry with display name: %S\n", wch);
}
ZeroMemory(&windowData, sizeof(WINDOWDATA));
ILFree(fPIDL);
@ -198,8 +200,12 @@ HRESULT STDMETHODCALLTYPE CTravelEntry::Update(IUnknown *punk, BOOL fIsLocalAnch
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
GetToolTipText(punk, wch);
TRACE("Updated entry display name is now: %S\n", wch);
if (TRACE_ON(browseui))
{
WCHAR wch[MAX_PATH * 2];
GetToolTipText(punk, wch);
TRACE("Updated entry display name is now: %S\n", wch);
}
return S_OK;
}

View file

@ -126,14 +126,15 @@ static BOOL IntGetUnderlineState(VOID)
// SHELL32.dll RegSetValueExW ( 0x00000854, "Settings", 0, REG_BINARY, 0x0210f170, 12 ) ERROR_SUCCESS 0.0001472
// SHELL32.dll RegSetValueExW ( 0x00000854, "FullPath", 0, REG_DWORD, 0x00d2f2ac, 4 ) ERROR_SUCCESS 0.0000168
// SHELL32.dll RegCloseKey ( 0x00000854 ) ERROR_SUCCESS 0.0000000
static BOOL IntSetNewWindowMode(BOOL bNewWindowMode)
static HRESULT IntSetNewWindowMode(BOOL bNewWindowMode)
{
CABINETSTATE cs;
if (!ReadCabinetState(&cs, sizeof(cs)))
return FALSE;
return E_FAIL;
cs.fNewWindowMode = (bNewWindowMode ? TRUE : FALSE);
return WriteCabinetState(&cs);
BOOL changed = !!cs.fNewWindowMode != !!bNewWindowMode;
cs.fNewWindowMode = !!bNewWindowMode;
return WriteCabinetState(&cs) ? (changed ? S_OK : S_FALSE) : E_FAIL;
}
static BOOL IntGetNewWindowMode(VOID)
@ -247,6 +248,8 @@ static void
GeneralDlg_StoreToUI(HWND hwndDlg, BOOL bDoubleClick, BOOL bUseCommonTasks,
BOOL bUnderline, BOOL bNewWindowMode, PGENERAL_DIALOG pGeneral)
{
EnableWindow(GetDlgItem(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS), bUseCommonTasks); // FIXME: ROS DefView does not support WebView nor the tasks pane
if (bUseCommonTasks)
CheckRadioButton(hwndDlg, IDC_FOLDER_OPTIONS_COMMONTASKS, IDC_FOLDER_OPTIONS_CLASSICFOLDERS, IDC_FOLDER_OPTIONS_COMMONTASKS);
else
@ -300,9 +303,9 @@ GeneralDlg_OnRestoreDefaults(HWND hwndDlg, PGENERAL_DIALOG pGeneral)
{
// default values
BOOL bDoubleClick = TRUE;
BOOL bUseCommonTasks = FALSE;
BOOL bUseCommonTasks = TRUE;
BOOL bUnderline = FALSE;
BOOL bNewWindowMode = FALSE;
BOOL bNewWindowMode = (_WIN32_WINNT < _WIN32_WINNT_WIN2K);
GeneralDlg_StoreToUI(hwndDlg, bDoubleClick, bUseCommonTasks, bUnderline, bNewWindowMode, pGeneral);
GeneralDlg_UpdateIcons(hwndDlg, 0, pGeneral);
@ -317,8 +320,10 @@ GeneralDlg_OnApply(HWND hwndDlg, PGENERAL_DIALOG pGeneral)
BOOL bNewWindowMode = !(IsDlgButtonChecked(hwndDlg, IDC_FOLDER_OPTIONS_SAMEWINDOW) == BST_CHECKED);
IntSetUnderlineState(bUnderline);
IntSetNewWindowMode(bNewWindowMode);
BOOL updateCabinets = IntSetNewWindowMode(bNewWindowMode) == S_OK;
IntSetShellStateSettings(bDoubleClick, bUseCommonTasks);
if (updateCabinets)
PostCabinetMessage(CWM_STATECHANGE, 0, 0);
return TRUE;
}

View file

@ -860,8 +860,9 @@ ScanAdvancedSettings(SHELLSTATE *pSS, DWORD *pdwMask)
}
static BOOL CALLBACK
RefreshBrowsersCallback(HWND hWnd, LPARAM msg)
PostCabinetMessageCallback(HWND hWnd, LPARAM param)
{
MSG &data = *(MSG*)param;
WCHAR ClassName[100];
if (GetClassNameW(hWnd, ClassName, _countof(ClassName)))
{
@ -869,12 +870,22 @@ RefreshBrowsersCallback(HWND hWnd, LPARAM msg)
!wcscmp(ClassName, L"CabinetWClass") ||
!wcscmp(ClassName, L"ExploreWClass"))
{
PostMessage(hWnd, WM_COMMAND, FCIDM_DESKBROWSER_REFRESH, 0);
PostMessage(hWnd, data.message, data.wParam, data.lParam);
}
}
return TRUE;
}
void
PostCabinetMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
{
MSG data;
data.message = Msg;
data.wParam = wParam;
data.lParam = lParam;
EnumWindows(PostCabinetMessageCallback, (LPARAM)&data);
}
static VOID
ViewDlg_Apply(HWND hwndDlg)
{
@ -934,7 +945,7 @@ ViewDlg_Apply(HWND hwndDlg)
// notify all
SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0);
EnumWindows(RefreshBrowsersCallback, NULL);
PostCabinetMessage(WM_COMMAND, FCIDM_DESKBROWSER_REFRESH, 0);
}
// IDD_FOLDER_OPTIONS_VIEW

View file

@ -164,6 +164,8 @@ public:
END_MSG_MAP()
};
void PostCabinetMessage(UINT Msg, WPARAM wParam, LPARAM lParam);
HRESULT
Shell_TranslateIDListAlias(
_In_ LPCITEMIDLIST pidl,

View file

@ -76,6 +76,9 @@ public:
STDMETHOD(OnViewWindowActive)(struct IShellView *ppshv) override;
STDMETHOD(SetToolbarItems)(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags) override;
// *** IBrowserService2 methods (fake for now) ***
inline void SetTopBrowser() const {}
// *** IServiceProvider methods ***
STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void **ppvObject) override;
@ -120,6 +123,7 @@ CDesktopBrowser::CDesktopBrowser():
m_hwndChangeNotifyServer(NULL),
m_dwDrives(::GetLogicalDrives())
{
SetTopBrowser();
}
CDesktopBrowser::~CDesktopBrowser()

View file

@ -1865,6 +1865,9 @@ BOOL WINAPI WriteCabinetState(CABINETSTATE *cs)
RegCloseKey( hkey );
}
#ifdef __REACTOS__
/* TODO: if (r==ERROR_SUCCESS) Increment GLOBALCOUNTER_FOLDERSETTINGSCHANGE */
#endif
return (r==ERROR_SUCCESS);
}

View file

@ -115,7 +115,7 @@ typedef struct ExplorerCommandLineParseResults
// TODO: 'ULONG Padding[0x100];'?
} EXPLORER_CMDLINE_PARSE_RESULTS, *PEXPLORER_CMDLINE_PARSE_RESULTS;
#define SH_EXPLORER_CMDLINE_FLAG_ONE 0x00000001
#define SH_EXPLORER_CMDLINE_FLAG_NEWWND 0x00000001
#define SH_EXPLORER_CMDLINE_FLAG_S 0x00000002
// unknown/unused 0x00000004
#define SH_EXPLORER_CMDLINE_FLAG_E 0x00000008
@ -129,7 +129,7 @@ typedef struct ExplorerCommandLineParseResults
// unknown/unused 0x00000800
#define SH_EXPLORER_CMDLINE_FLAG_NOUI 0x00001000
// unknown/unused 0x00002000
#define SH_EXPLORER_CMDLINE_FLAG_N 0x00004000
#define SH_EXPLORER_CMDLINE_FLAG_NOREUSE 0x00004000 // Don't use IShellWindows
// unknown/unused 0x00008000
// unknown/unused 0x00010000
#define SH_EXPLORER_CMDLINE_FLAG_SEPARATE 0x00020000