https://git.reactos.org/?p=reactos.git;a=commitdiff;h=724b20d41453a9d55b9213149893f4d9bd41a29e

commit 724b20d41453a9d55b9213149893f4d9bd41a29e
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Thu Aug 8 19:30:14 2024 +0200
Commit:     GitHub <nore...@github.com>
CommitDate: Thu Aug 8 19:30:14 2024 +0200

    [SHELL32] Don't add the file to the parameters if the registry command did 
not ask for a file (#7139)
    
    Bugs fixed:
     - fDefault detection of default verb is flawed because it checks the ici 
struct after conversion instead of the source sei struct.
     - The command to execute should not have the filename appended just 
because %1 nor %L did not appear in the registry command template.
---
 dll/win32/shell32/CDefaultContextMenu.cpp | 32 ++++++++++++++++++-------------
 dll/win32/shell32/CShellLink.cpp          |  3 +--
 dll/win32/shell32/precomp.h               |  9 +++++++++
 dll/win32/shell32/shlexec.cpp             | 22 +++++++++++----------
 sdk/include/reactos/shellutils.h          | 21 +++++++++++++++++++-
 5 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/dll/win32/shell32/CDefaultContextMenu.cpp 
b/dll/win32/shell32/CDefaultContextMenu.cpp
index b7dd4eedf40..f55ed72dc3c 100644
--- a/dll/win32/shell32/CDefaultContextMenu.cpp
+++ b/dll/win32/shell32/CDefaultContextMenu.cpp
@@ -1302,8 +1302,7 @@ CDefaultContextMenu::TryToBrowse(
 HRESULT
 CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST 
pidl, PStaticShellEntry pEntry)
 {
-    BOOL unicode = lpcmi->cbSize >= FIELD_OFFSET(CMINVOKECOMMANDINFOEX, 
ptInvoke) &&
-                   (lpcmi->fMask & CMIC_MASK_UNICODE);
+    const BOOL unicode = IsUnicode(*lpcmi);
 
     LPITEMIDLIST pidlFull = ILCombine(m_pidlFolder, pidl);
     if (pidlFull == NULL)
@@ -1315,7 +1314,23 @@ CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFOEX 
lpcmi, LPCITEMIDLIST pid
     BOOL bHasPath = SHGetPathFromIDListW(pidlFull, wszPath);
 
     WCHAR wszDir[MAX_PATH];
-    if (bHasPath)
+
+    SHELLEXECUTEINFOW sei = { sizeof(sei) };
+    sei.fMask = SEE_MASK_CLASSKEY | SEE_MASK_IDLIST | 
(CmicFlagsToSeeFlags(lpcmi->fMask) & ~SEE_MASK_INVOKEIDLIST);
+    sei.hwnd = lpcmi->hwnd;
+    sei.nShow = lpcmi->nShow;
+    sei.lpVerb = pEntry->Verb;
+    sei.lpIDList = pidlFull;
+    sei.hkeyClass = pEntry->hkClass;
+    sei.dwHotKey = lpcmi->dwHotKey;
+    sei.hIcon = lpcmi->hIcon;
+    sei.lpDirectory = wszDir;
+
+    if (unicode && !StrIsNullOrEmpty(lpcmi->lpDirectoryW))
+    {
+        sei.lpDirectory = lpcmi->lpDirectoryW;
+    }
+    else if (bHasPath)
     {
         wcscpy(wszDir, wszPath);
         PathRemoveFileSpec(wszDir);
@@ -1326,25 +1341,16 @@ CDefaultContextMenu::InvokePidl(LPCMINVOKECOMMANDINFOEX 
lpcmi, LPCITEMIDLIST pid
             *wszDir = UNICODE_NULL;
     }
 
-    CComHeapPtr<WCHAR> pszParamsW;
-    SHELLEXECUTEINFOW sei = { sizeof(sei) };
-    sei.hwnd = lpcmi->hwnd;
-    sei.nShow = SW_SHOWNORMAL;
-    sei.lpVerb = pEntry->Verb;
-    sei.lpDirectory = wszDir;
-    sei.lpIDList = pidlFull;
-    sei.hkeyClass = pEntry->hkClass;
-    sei.fMask = SEE_MASK_CLASSKEY | SEE_MASK_IDLIST;
     if (bHasPath)
         sei.lpFile = wszPath;
 
+    CComHeapPtr<WCHAR> pszParamsW;
     if (unicode && !StrIsNullOrEmpty(lpcmi->lpParametersW))
         sei.lpParameters = lpcmi->lpParametersW;
     else if (!StrIsNullOrEmpty(lpcmi->lpParameters) && 
__SHCloneStrAtoW(&pszParamsW, lpcmi->lpParameters))
         sei.lpParameters = pszParamsW;
 
     ShellExecuteExW(&sei);
-
     ILFree(pidlFull);
 
     return S_OK;
diff --git a/dll/win32/shell32/CShellLink.cpp b/dll/win32/shell32/CShellLink.cpp
index 218fa2a8825..5a73cb3fe49 100644
--- a/dll/win32/shell32/CShellLink.cpp
+++ b/dll/win32/shell32/CShellLink.cpp
@@ -2592,8 +2592,7 @@ HRESULT STDMETHODCALLTYPE 
CShellLink::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
 
 HRESULT CShellLink::DoOpen(LPCMINVOKECOMMANDINFO lpici)
 {
-    BOOL unicode = lpici->cbSize >= FIELD_OFFSET(CMINVOKECOMMANDINFOEX, 
ptInvoke) &&
-                   (lpici->fMask & CMIC_MASK_UNICODE);
+    const BOOL unicode = IsUnicode(*lpici);
 
     CStringW args;
     if (m_sArgs)
diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h
index 5b319322af6..8389048af63 100644
--- a/dll/win32/shell32/precomp.h
+++ b/dll/win32/shell32/precomp.h
@@ -155,6 +155,15 @@ UINT
 GetDfmCmd(_In_ IContextMenu *pCM, _In_ LPCSTR verba);
 #define SHELL_ExecuteControlPanelCPL(hwnd, cpl) SHRunControlPanel((cpl), 
(hwnd))
 
+#define CmicFlagsToSeeFlags(flags)  ((flags) & SEE_CMIC_COMMON_FLAGS)
+static inline UINT SeeFlagsToCmicFlags(UINT flags)
+{
+    if (flags & SEE_MASK_CLASSNAME)
+        flags &= ~(SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE);
+    return flags & SEE_CMIC_COMMON_FLAGS;
+}
+
+
 // CStubWindow32 --- The owner window of file property sheets.
 // This window hides taskbar button of property sheet.
 class CStubWindow32 : public CWindowImpl<CStubWindow32>
diff --git a/dll/win32/shell32/shlexec.cpp b/dll/win32/shell32/shlexec.cpp
index a74e1ff0f44..00b29dc27b7 100644
--- a/dll/win32/shell32/shlexec.cpp
+++ b/dll/win32/shell32/shlexec.cpp
@@ -491,7 +491,7 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR 
*env, BOOL shWait,
 
     /* make sure we don't fail the CreateProcess if the calling app passes in
      * a bad working directory */
-    if (psei->lpDirectory && psei->lpDirectory[0])
+    if (!StrIsNullOrEmpty(psei->lpDirectory))
     {
         DWORD attr = GetFileAttributesW(psei->lpDirectory);
         if (attr != INVALID_FILE_ATTRIBUTES && attr & FILE_ATTRIBUTE_DIRECTORY)
@@ -1559,9 +1559,9 @@ static HRESULT 
ShellExecute_ContextMenuVerb(LPSHELLEXECUTEINFOW sei)
     __SHCloneStrWtoA(&verb, sei->lpVerb);
     __SHCloneStrWtoA(&parameters, sei->lpParameters);
 
-    BOOL fDefault = !sei->lpVerb || !sei->lpVerb[0];
+    BOOL fDefault = StrIsNullOrEmpty(sei->lpVerb);
     CMINVOKECOMMANDINFOEX ici = { sizeof(ici) };
-    ici.fMask = (sei->fMask & (SEE_MASK_NO_CONSOLE | SEE_MASK_ASYNCOK | 
SEE_MASK_FLAG_NO_UI)) | CMIC_MASK_UNICODE;
+    ici.fMask = SeeFlagsToCmicFlags(sei->fMask) | CMIC_MASK_UNICODE;
     ici.nShow = sei->nShow;
     if (!fDefault)
     {
@@ -1571,20 +1571,20 @@ static HRESULT 
ShellExecute_ContextMenuVerb(LPSHELLEXECUTEINFOW sei)
     ici.hwnd = sei->hwnd;
     ici.lpParameters = parameters;
     ici.lpParametersW = sei->lpParameters;
-    if ((sei->fMask & (SEE_MASK_HASLINKNAME | SEE_MASK_CLASSNAME)) == 
SEE_MASK_HASLINKNAME)
-    {
-        ici.fMask |= CMIC_MASK_HASLINKNAME;
+    ici.dwHotKey = sei->dwHotKey;
+    ici.hIcon = sei->hIcon;
+    if (ici.fMask & (CMIC_MASK_HASLINKNAME | CMIC_MASK_HASTITLE))
         ici.lpTitleW = sei->lpClass;
-    }
 
+    enum { idFirst = 1, idLast = 0x7fff };
     HMENU hMenu = CreatePopupMenu();
-    hr = cm->QueryContextMenu(hMenu, 0, 1, 0x7fff, fDefault ? CMF_DEFAULTONLY 
: 0);
+    hr = cm->QueryContextMenu(hMenu, 0, idFirst, idLast, fDefault ? 
CMF_DEFAULTONLY : 0);
     if (!FAILED_UNEXPECTEDLY(hr))
     {
         if (fDefault)
         {
             INT uDefault = GetMenuDefaultItem(hMenu, FALSE, 0);
-            uDefault = (uDefault != -1) ? uDefault - 1 : 0;
+            uDefault = (uDefault != -1) ? uDefault - idFirst : 0;
             ici.lpVerb = MAKEINTRESOURCEA(uDefault);
             ici.lpVerbW = MAKEINTRESOURCEW(uDefault);
         }
@@ -1600,7 +1600,6 @@ static HRESULT 
ShellExecute_ContextMenuVerb(LPSHELLEXECUTEINFOW sei)
 }
 
 
-
 /*************************************************************************
  *    ShellExecute_FromContextMenu [Internal]
  */
@@ -1676,6 +1675,8 @@ static UINT_PTR SHELL_execute_class(LPCWSTR 
wszApplicationName, LPSHELLEXECUTEIN
                              &resultLen, (psei->lpDirectory && 
*psei->lpDirectory) ? psei->lpDirectory : NULL);
         if (!done && wszApplicationName[0])
         {
+#if 0       // Given HKCR\.test=SZ:"test" and 
HKCR\test\shell\open\command=SZ:"cmd.exe /K echo.Hello", no filename is
+            // appended on Windows when there is no %1 nor %L when executed 
with: shlextdbg.exe /shellexec=c:\file.test /INVOKE
             strcatW(wcmd, L" ");
             if (*wszApplicationName != '"')
             {
@@ -1685,6 +1686,7 @@ static UINT_PTR SHELL_execute_class(LPCWSTR 
wszApplicationName, LPSHELLEXECUTEIN
             }
             else
                 strcatW(wcmd, wszApplicationName);
+#endif
         }
         if (resultLen > ARRAY_SIZE(wcmd))
             ERR("Argify buffer not large enough... truncating\n");
diff --git a/sdk/include/reactos/shellutils.h b/sdk/include/reactos/shellutils.h
index 7487288cee1..17d7e0e74e7 100644
--- a/sdk/include/reactos/shellutils.h
+++ b/sdk/include/reactos/shellutils.h
@@ -609,6 +609,12 @@ struct CCoInit
 #define S_GREATERTHAN S_FALSE
 #define MAKE_COMPARE_HRESULT(x) ((x)>0 ? S_GREATERTHAN : ((x)<0 ? S_LESSTHAN : 
S_EQUAL))
 
+#define SEE_CMIC_COMMON_BASICFLAGS (SEE_MASK_NOASYNC | SEE_MASK_ASYNCOK | 
SEE_MASK_UNICODE | \
+                                    SEE_MASK_NO_CONSOLE | SEE_MASK_FLAG_NO_UI 
| SEE_MASK_FLAG_SEPVDM | \
+                                    SEE_MASK_FLAG_LOG_USAGE | 
SEE_MASK_NOZONECHECKS)
+#define SEE_CMIC_COMMON_FLAGS      (SEE_CMIC_COMMON_BASICFLAGS | 
SEE_MASK_HOTKEY | SEE_MASK_ICON | \
+                                    SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE)
+
 static inline BOOL ILIsSingle(LPCITEMIDLIST pidl)
 {
     return pidl == ILFindLastID(pidl);
@@ -627,6 +633,19 @@ static inline PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA 
const* pida, SIZE_T i)
 
 #ifdef __cplusplus
 
+#if defined(CMIC_MASK_UNICODE) && defined(SEE_MASK_UNICODE)
+static inline bool IsUnicode(const CMINVOKECOMMANDINFOEX &ici)
+{
+    const UINT minsize = FIELD_OFFSET(CMINVOKECOMMANDINFOEX, ptInvoke);
+    return (ici.fMask & CMIC_MASK_UNICODE) && ici.cbSize >= minsize;
+}
+
+static inline bool IsUnicode(const CMINVOKECOMMANDINFO &ici)
+{
+    return IsUnicode(*(CMINVOKECOMMANDINFOEX*)&ici);
+}
+#endif // CMIC_MASK_UNICODE
+
 DECLSPEC_SELECTANY CLIPFORMAT g_cfHIDA = NULL;
 DECLSPEC_SELECTANY CLIPFORMAT g_cfShellIdListOffsets = NULL;
 
@@ -784,7 +803,7 @@ DataObject_SetOffset(IDataObject* pDataObject, POINT* point)
     return DataObject_SetData(pDataObject, g_cfShellIdListOffsets, point, 
sizeof(point[0]));
 }
 
-#endif
+#endif // __cplusplus
 
 #ifdef __cplusplus
 struct SHELL_GetSettingImpl

Reply via email to