https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7ce58e177c98f66a6e50e6538f29d5a286590927

commit 7ce58e177c98f66a6e50e6538f29d5a286590927
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Mon Feb 6 22:46:26 2023 +0900
Commit:     GitHub <[email protected]>
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 <[email protected]>
  *
  * 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 *);

Reply via email to