https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7ce58e177c98f66a6e50e6...
commit 7ce58e177c98f66a6e50e6538f29d5a286590927 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Mon Feb 6 22:46:26 2023 +0900 Commit: GitHub noreply@github.com CommitDate: Mon Feb 6 22:46:26 2023 +0900
[BROWSEUI] Execute command line from address bar (#5026)
CORE-15453 --- dll/win32/browseui/addresseditbox.cpp | 125 ++++++++++++++++++++++------------ dll/win32/browseui/addresseditbox.h | 3 + 2 files changed, 86 insertions(+), 42 deletions(-)
diff --git a/dll/win32/browseui/addresseditbox.cpp b/dll/win32/browseui/addresseditbox.cpp index 4e018cc5bc1..e1faf69b38f 100644 --- a/dll/win32/browseui/addresseditbox.cpp +++ b/dll/win32/browseui/addresseditbox.cpp @@ -2,6 +2,7 @@ * ReactOS Explorer * * Copyright 2009 Andrew Hill <ash77 at domain reactos.org> + * Copyright 2023 Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -94,6 +95,68 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::SetCurrentDir(long paramC) return E_NOTIMPL; }
+BOOL CAddressEditBox::GetComboBoxText(CComHeapPtr<WCHAR>& pszText) +{ + pszText.Free(); + INT cchMax = fCombobox.GetWindowTextLength() + sizeof(UNICODE_NULL); + if (!pszText.Allocate(cchMax)) + return FALSE; + return fCombobox.GetWindowText(pszText, cchMax); +} + +HRESULT CAddressEditBox::GetAbsolutePidl(PIDLIST_ABSOLUTE *pAbsolutePIDL) +{ + CComPtr<IBrowserService> isb; + HRESULT hr = IUnknown_QueryService(fSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &isb)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = isb->GetPidl(pAbsolutePIDL); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + return S_OK; +} + +/* Execute command line from address bar */ +BOOL CAddressEditBox::ExecuteCommandLine() +{ + /* Get command line */ + CComHeapPtr<WCHAR> pszCmdLine; + if (!GetComboBoxText(pszCmdLine)) + return FALSE; + + /* Split 1st parameter from trailing arguments */ + PWCHAR args = PathGetArgsW(pszCmdLine); + PathRemoveArgsW(pszCmdLine); + + PathUnquoteSpacesW(pszCmdLine); /* Unquote the 1st parameter */ + + /* Get ready for execution */ + SHELLEXECUTEINFOW info = { sizeof(info), SEE_MASK_FLAG_NO_UI, m_hWnd }; + info.lpFile = pszCmdLine; + info.lpParameters = args; + info.nShow = SW_SHOWNORMAL; + + /* Set current directory */ + WCHAR dir[MAX_PATH] = L""; + CComHeapPtr<ITEMIDLIST> pidl; + if (SUCCEEDED(GetAbsolutePidl(&pidl))) + { + if (SHGetPathFromIDListW(pidl, dir) && PathIsDirectoryW(dir)) + info.lpDirectory = dir; + } + + if (!::ShellExecuteExW(&info)) /* Execute! */ + return FALSE; + + /* Execution succeeded. Reset the combobox. */ + if (dir[0] != UNICODE_NULL) + fCombobox.SetWindowText(dir); + + return TRUE; +} + HRESULT STDMETHODCALLTYPE CAddressEditBox::ParseNow(long paramC) { ULONG eaten; @@ -114,28 +177,17 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::ParseNow(long paramC) return hr;
/* Get the path to browse and expand it if needed */ - LPWSTR input; - int inputLength = fCombobox.GetWindowTextLength() + 2; - - input = new WCHAR[inputLength]; - fCombobox.GetWindowText(input, inputLength); - - LPWSTR address; - int addressLength = ExpandEnvironmentStrings(input, NULL, 0); - - if (addressLength <= 0) + CComHeapPtr<WCHAR> input, address; + if (!GetComboBoxText(input)) + return E_FAIL; + + INT addressLength = (wcschr(input, L'%') ? ::SHExpandEnvironmentStringsW(input, NULL, 0) : 0); + if (addressLength <= 0 || + !address.Allocate(addressLength + 1) || + !::SHExpandEnvironmentStringsW(input, address, addressLength)) { - address = input; - } - else - { - addressLength += 2; - address = new WCHAR[addressLength]; - if (!ExpandEnvironmentStrings(input, address, addressLength)) - { - delete[] address; - address = input; - } + address.Free(); + address.Attach(input.Detach()); }
/* Try to parse a relative path and if it fails, try to browse an absolute path */ @@ -167,20 +219,14 @@ parseabsolute: cleanup: if (pidlCurrent) ILFree(pidlCurrent); - if (address != input) - delete[] address; - delete[] input; - return hr; }
HRESULT STDMETHODCALLTYPE CAddressEditBox::ShowFileNotFoundError(HRESULT hRet) { CComHeapPtr<WCHAR> input; - int inputLength = fCombobox.GetWindowTextLength() + 2; - - input.Allocate(inputLength); - fCombobox.GetWindowText(input, inputLength); + if (!GetComboBoxText(input)) + return E_FAIL;
ShellMessageBoxW(_AtlBaseModule.GetResourceInstance(), fCombobox.m_hWnd, MAKEINTRESOURCEW(IDS_PARSE_ADDR_ERR_TEXT), MAKEINTRESOURCEW(IDS_PARSE_ADDR_ERR_TITLE), MB_OK | MB_ICONERROR, input.m_pData);
@@ -200,7 +246,12 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Execute(long paramC)
/* If the destination path doesn't exist then display an error message */ if (hr == HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) + { + if (ExecuteCommandLine()) + return S_OK; + return ShowFileNotFoundError(hr); + }
if (!pidlLastParsed) return E_FAIL; @@ -214,16 +265,11 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Execute(long paramC) if (FAILED(hr)) return hr;
- CComPtr<IBrowserService> pbs; - pisb->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs)); - if (FAILED(hr)) - return hr; - /* * Get the current pidl of the shellbrowser and check if it is the same with the parsed one */ PIDLIST_ABSOLUTE pidl; - hr = pbs->GetPidl(&pidl); + hr = GetAbsolutePidl(&pidl); if (FAILED(hr)) return hr;
@@ -361,7 +407,6 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::GetIDsOfNames( HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { - CComPtr<IBrowserService> isb; CComPtr<IShellFolder> sf; HRESULT hr; PIDLIST_ABSOLUTE absolutePIDL; @@ -382,12 +427,8 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID ri pidlLastParsed = NULL;
/* Get the current pidl of the browser */ - hr = IUnknown_QueryService(fSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &isb)); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - hr = isb->GetPidl(&absolutePIDL); - if (FAILED_UNEXPECTEDLY(hr)) + hr = GetAbsolutePidl(&absolutePIDL); + if (FAILED(hr)) return hr;
if (!absolutePIDL) diff --git a/dll/win32/browseui/addresseditbox.h b/dll/win32/browseui/addresseditbox.h index 4b56a0f997b..1f0e003d06a 100644 --- a/dll/win32/browseui/addresseditbox.h +++ b/dll/win32/browseui/addresseditbox.h @@ -48,6 +48,9 @@ private: void FillOneLevel(int index, int levelIndent, int indent); LPITEMIDLIST GetItemData(int index); HRESULT STDMETHODCALLTYPE ShowFileNotFoundError(HRESULT hRet); + HRESULT GetAbsolutePidl(PIDLIST_ABSOLUTE *pAbsolutePIDL); + BOOL ExecuteCommandLine(); + BOOL GetComboBoxText(CComHeapPtr<WCHAR>& pszText); public: // *** IShellService methods *** virtual HRESULT STDMETHODCALLTYPE SetOwner(IUnknown *);