https://git.reactos.org/?p=reactos.git;a=commitdiff;h=53e930e97f2cd75760ebdbca3e6e355faec0d52b

commit 53e930e97f2cd75760ebdbca3e6e355faec0d52b
Author:     Whindmar Saksit <whinds...@proton.me>
AuthorDate: Mon Aug 19 00:32:46 2024 +0200
Commit:     GitHub <nore...@github.com>
CommitDate: Mon Aug 19 00:32:46 2024 +0200

    [SHLWAPI] SHInvokeCommandOnContextMenu[Ex] and 
SHInvokeCommandWithFlagsAndSite (#7228)
---
 dll/win32/shlwapi/ordinal.c      |  16 ++++
 dll/win32/shlwapi/shlwapi.spec   |  12 +--
 dll/win32/shlwapi/utils.cpp      | 178 ++++++++++++++++++++++++++++++++-------
 sdk/include/reactos/undocshell.h |  17 ++++
 4 files changed, 186 insertions(+), 37 deletions(-)

diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c
index 5b800df18b2..f36cb6a6b66 100644
--- a/dll/win32/shlwapi/ordinal.c
+++ b/dll/win32/shlwapi/ordinal.c
@@ -61,7 +61,11 @@ extern HINSTANCE shlwapi_hInstance;
 extern DWORD SHLWAPI_ThreadRef_index;
 
 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
+#ifdef __REACTOS__
+HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, 
LPCITEMIDLIST lpApidl, LPCSTR lpVerb);
+#else
 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,DWORD);
+#endif
 BOOL    WINAPI SHAboutInfoW(LPWSTR,DWORD);
 
 /*
@@ -3056,7 +3060,11 @@ HWND WINAPI SHCreateWorkerWindowW(WNDPROC wndProc, HWND 
hWndParent, DWORD dwExSt
 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, 
LPCITEMIDLIST lpApidl)
 {
     TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
+#ifdef __REACTOS__
+    return SHInvokeCommand(hWnd, lpFolder, lpApidl, NULL);
+#else
     return SHInvokeCommand(hWnd, lpFolder, lpApidl, 0);
+#endif
 }
 
 /*************************************************************************
@@ -3615,6 +3623,13 @@ UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, 
int iIndex, UINT uFlags,
  *           executed.
  *  Failure: An HRESULT error code indicating the error.
  */
+#ifdef __REACTOS__
+EXTERN_C HRESULT WINAPI SHInvokeCommandWithFlagsAndSite(HWND, IUnknown*, 
IShellFolder*, LPCITEMIDLIST, UINT, LPCSTR);
+HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, 
LPCITEMIDLIST lpApidl, LPCSTR lpVerb)
+{
+    return SHInvokeCommandWithFlagsAndSite(hWnd, NULL, lpFolder, lpApidl, 0, 
lpVerb);
+}
+#else
 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, 
LPCITEMIDLIST lpApidl, DWORD dwCommandId)
 {
   IContextMenu *iContext;
@@ -3667,6 +3682,7 @@ HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* 
lpFolder, LPCITEMIDLIST
   }
   return hRet;
 }
+#endif /* __REACTOS__ */
 
 /*************************************************************************
  *      @      [SHLWAPI.370]
diff --git a/dll/win32/shlwapi/shlwapi.spec b/dll/win32/shlwapi/shlwapi.spec
index cc625b5a84a..cb72591fbac 100644
--- a/dll/win32/shlwapi/shlwapi.spec
+++ b/dll/win32/shlwapi/shlwapi.spec
@@ -360,7 +360,7 @@
 360 stdcall -noname RemoveDirectoryWrapW(wstr) kernel32.RemoveDirectoryW
 361 stdcall -noname GetShortPathNameWrapW(wstr ptr long) 
kernel32.GetShortPathNameW
 362 stdcall -noname GetUserNameWrapW(ptr ptr) advapi32.GetUserNameW
-363 stdcall -noname SHInvokeCommand(ptr ptr ptr long)
+363 stdcall -noname SHInvokeCommand(ptr ptr ptr str)
 364 stdcall -noname DoesStringRoundTripA(str ptr long)
 365 stdcall -noname DoesStringRoundTripW(wstr ptr long)
 366 stdcall -noname RegEnumValueWrapW(long long ptr ptr ptr ptr ptr ptr) 
advapi32.RegEnumValueW
@@ -537,8 +537,8 @@
 537 stub -noname SHBoolSystemParametersInfo
 538 stdcall -noname IUnknown_QueryServiceForWebBrowserApp(ptr ptr ptr)
 539 stub -noname IUnknown_ShowBrowserBar
-540 stub -noname SHInvokeCommandOnContextMenu
-541 stub -noname SHInvokeCommandsOnContextMen
+540 stdcall -noname SHInvokeCommandOnContextMenu(ptr ptr ptr long str)
+541 stub -noname SHInvokeCommandsOnContextMenu
 542 stdcall -noname GetUIVersion()
 543 stdcall -noname CreateColorSpaceWrapW(ptr) gdi32.CreateColorSpaceW
 544 stub -noname QuerySourceCreateFromKey
@@ -568,7 +568,8 @@
 568 stdcall AssocQueryStringW(long long wstr wstr ptr ptr)
 569 stdcall ChrCmpIA(long long)
 570 stdcall ChrCmpIW(long long)
-571 stdcall ColorAdjustLuma(long long long)
+571 stdcall -noname -version=0x600+ SHInvokeCommandWithFlagsAndSite(ptr ptr 
ptr ptr long str)
+@ stdcall ColorAdjustLuma(long long long)
 572 stdcall ColorHLSToRGB(long long long)
 573 stdcall ColorRGBToHLS(long ptr ptr ptr)
 @ stdcall -private DllGetVersion(ptr)
@@ -636,7 +637,8 @@
 636 stdcall PathIsSameRootA(str str)
 637 stdcall PathIsSameRootW(wstr wstr)
 638 stdcall PathIsSystemFolderA(str long)
-639 stdcall PathIsSystemFolderW(wstr long)
+639 stdcall -noname -version=0x600+ SHInvokeCommandOnContextMenuEx(ptr ptr ptr 
long long str wstr)
+@ stdcall PathIsSystemFolderW(wstr long)
 640 stdcall PathIsUNCA(str)
 641 stdcall PathIsUNCServerA(str)
 642 stdcall PathIsUNCServerShareA(str)
diff --git a/dll/win32/shlwapi/utils.cpp b/dll/win32/shlwapi/utils.cpp
index a452b3f7253..8cfb8ab2d61 100644
--- a/dll/win32/shlwapi/utils.cpp
+++ b/dll/win32/shlwapi/utils.cpp
@@ -33,67 +33,181 @@
 
 #include <strsafe.h>
 
+#ifndef FAILED_UNEXPECTEDLY
+#define FAILED_UNEXPECTEDLY FAILED /* FIXME: Make shellutils.h usable without 
ATL */
+#endif
+
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
-/*************************************************************************
- * IContextMenu_Invoke [SHLWAPI.207]
- *
- * Used by Win:SHELL32!CISFBand::_TrySimpleInvoke.
- */
-EXTERN_C
-BOOL WINAPI
-IContextMenu_Invoke(
-    _In_ IContextMenu *pContextMenu,
-    _In_ HWND hwnd,
-    _In_ LPCSTR lpVerb,
-    _In_ UINT uFlags)
+static inline WORD 
+GetVersionMajorMinor()
 {
-    CMINVOKECOMMANDINFO info;
-    BOOL ret = FALSE;
+    DWORD version = GetVersion();
+    return MAKEWORD(HIBYTE(version), LOBYTE(version));
+}
+
+static HRESULT
+SHInvokeCommandOnContextMenuInternal(
+    _In_opt_ HWND hWnd,
+    _In_opt_ IUnknown* pUnk,
+    _In_ IContextMenu* pCM,
+    _In_ UINT fCMIC,
+    _In_ UINT fCMF,
+    _In_opt_ LPCSTR pszVerb,
+    _In_opt_ LPCWSTR pwszDir,
+    _In_ bool ForceQCM)
+{
+    CMINVOKECOMMANDINFOEX info = { sizeof(info), fCMIC, hWnd, pszVerb };
     INT iDefItem = 0;
     HMENU hMenu = NULL;
     HCURSOR hOldCursor;
+    HRESULT hr = S_OK;
+    WCHAR wideverb[MAX_PATH];
 
-    TRACE("(%p, %p, %s, %u)\n", pContextMenu, hwnd, debugstr_a(lpVerb), 
uFlags);
-
-    if (!pContextMenu)
-        return FALSE;
+    if (!pCM)
+        return E_INVALIDARG;
 
     hOldCursor = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
-
-    ZeroMemory(&info, sizeof(info));
-    info.cbSize = sizeof(info);
-    info.hwnd = hwnd;
     info.nShow = SW_NORMAL;
-    info.lpVerb = lpVerb;
+    if (pUnk)
+        IUnknown_SetSite(pCM, pUnk);
 
-    if (IS_INTRESOURCE(lpVerb))
+    if (IS_INTRESOURCE(pszVerb))
     {
         hMenu = CreatePopupMenu();
         if (hMenu)
         {
-            pContextMenu->QueryContextMenu(hMenu, 0, 1, MAXSHORT, uFlags | 
CMF_DEFAULTONLY);
+            hr = pCM->QueryContextMenu(hMenu, 0, 1, MAXSHORT, fCMF | 
CMF_DEFAULTONLY);
             iDefItem = GetMenuDefaultItem(hMenu, 0, 0);
             if (iDefItem != -1)
                 info.lpVerb = MAKEINTRESOURCEA(iDefItem - 1);
         }
+        info.lpVerbW = MAKEINTRESOURCEW(info.lpVerb);
+    }
+    else
+    {
+        if (GetVersionMajorMinor() >= _WIN32_WINNT_WIN7)
+        {
+            info.fMask |= CMF_OPTIMIZEFORINVOKE;
+        }
+        if (pszVerb && SHAnsiToUnicode(pszVerb, wideverb, _countof(wideverb)))
+        {
+            info.fMask |= CMIC_MASK_UNICODE;
+            info.lpVerbW = wideverb;
+        }
+        if (ForceQCM)
+        {
+            hMenu = CreatePopupMenu();
+            hr = pCM->QueryContextMenu(hMenu, 0, 1, MAXSHORT, fCMF);
+        }
     }
 
-    if (iDefItem != -1 || info.lpVerb)
+    SetCursor(hOldCursor);
+
+    if (!FAILED_UNEXPECTEDLY(hr) && (iDefItem != -1 || info.lpVerb))
     {
-        if (!hwnd)
+        if (!hWnd)
             info.fMask |= CMIC_MASK_FLAG_NO_UI;
-        ret = SUCCEEDED(pContextMenu->InvokeCommand(&info));
+
+        CHAR dir[MAX_PATH];
+        if (pwszDir)
+        {
+            info.fMask |= CMIC_MASK_UNICODE;
+            info.lpDirectoryW = pwszDir;
+            if (SHUnicodeToAnsi(pwszDir, dir, _countof(dir)))
+                info.lpDirectory = dir;
+        }
+
+        hr = pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)&info);
+        if (FAILED_UNEXPECTEDLY(hr)) { /* Diagnostic message */ }
     }
 
-    /* Invoking itself doesn't need the menu object, but getting the command 
info
-       needs the menu. */
+    if (pUnk)
+        IUnknown_SetSite(pCM, NULL);
     if (hMenu)
         DestroyMenu(hMenu);
 
-    SetCursor(hOldCursor);
+    return hr;
+}
+
+/*************************************************************************
+ * SHInvokeCommandOnContextMenuEx [SHLWAPI.639]
+ */
+EXTERN_C
+HRESULT WINAPI
+SHInvokeCommandOnContextMenuEx(
+    _In_opt_ HWND hWnd,
+    _In_opt_ IUnknown* pUnk,
+    _In_ IContextMenu* pCM,
+    _In_ UINT fCMIC,
+    _In_ UINT fCMF,
+    _In_opt_ LPCSTR pszVerb,
+    _In_opt_ LPCWSTR pwszDir)
+{
+    return SHInvokeCommandOnContextMenuInternal(hWnd, pUnk, pCM, fCMIC, fCMF, 
pszVerb, pwszDir, true);
+}
+
+/*************************************************************************
+ * SHInvokeCommandOnContextMenu [SHLWAPI.540]
+ */
+EXTERN_C
+HRESULT WINAPI
+SHInvokeCommandOnContextMenu(
+    _In_opt_ HWND hWnd,
+    _In_opt_ IUnknown* pUnk,
+    _In_ IContextMenu* pCM,
+    _In_ UINT fCMIC,
+    _In_opt_ LPCSTR pszVerb)
+{
+    return SHInvokeCommandOnContextMenuEx(hWnd, pUnk, pCM, fCMIC, 
CMF_EXTENDEDVERBS, pszVerb, NULL);
+}
+
+/*************************************************************************
+ * SHInvokeCommandWithFlagsAndSite [SHLWAPI.571]
+ */
+EXTERN_C
+HRESULT WINAPI
+SHInvokeCommandWithFlagsAndSite(
+    _In_opt_ HWND hWnd,
+    _In_opt_ IUnknown* pUnk,
+    _In_ IShellFolder* pShellFolder,
+    _In_ LPCITEMIDLIST pidl,
+    _In_ UINT fCMIC,
+    _In_opt_ LPCSTR pszVerb)
+{
+    HRESULT hr = E_INVALIDARG;
+    if (pShellFolder)
+    {
+        IContextMenu *pCM;
+        hr = pShellFolder->GetUIObjectOf(hWnd, 1, &pidl, IID_IContextMenu, 
NULL, (void**)&pCM);
+        if (SUCCEEDED(hr))
+        {
+            fCMIC |= CMIC_MASK_FLAG_LOG_USAGE;
+            hr = SHInvokeCommandOnContextMenuEx(hWnd, pUnk, pCM, fCMIC, 0, 
pszVerb, NULL);
+            pCM->Release();
+        }
+    }
+    return hr;
+}
+
 
-    return ret;
+/*************************************************************************
+ * IContextMenu_Invoke [SHLWAPI.207]
+ *
+ * Used by Win:SHELL32!CISFBand::_TrySimpleInvoke.
+ */
+EXTERN_C
+BOOL WINAPI
+IContextMenu_Invoke(
+    _In_ IContextMenu *pContextMenu,
+    _In_ HWND hwnd,
+    _In_ LPCSTR lpVerb,
+    _In_ UINT uFlags)
+{
+    TRACE("(%p, %p, %s, %u)\n", pContextMenu, hwnd, debugstr_a(lpVerb), 
uFlags);
+    HRESULT hr = SHInvokeCommandOnContextMenuInternal(hwnd, NULL, 
pContextMenu, 0,
+                                                      uFlags, lpVerb, NULL, 
false);
+    return !FAILED_UNEXPECTEDLY(hr);
 }
 
 /*************************************************************************
diff --git a/sdk/include/reactos/undocshell.h b/sdk/include/reactos/undocshell.h
index 84b0f54e206..f5bd2cd7f2e 100644
--- a/sdk/include/reactos/undocshell.h
+++ b/sdk/include/reactos/undocshell.h
@@ -93,6 +93,23 @@ HRESULT WINAPI SHILCreateFromPathW (
     LPITEMIDLIST * ppidl,
     DWORD *attributes);
 
+HRESULT WINAPI SHInvokeCommand(
+    HWND hWnd,
+    IShellFolder* lpFolder,
+    LPCITEMIDLIST lpApidl,
+    LPCSTR lpVerb);
+HRESULT WINAPI SHInvokeCommandOnContextMenu(
+    _In_opt_ HWND hWnd,
+    _In_opt_ IUnknown* pUnk,
+    _In_ IContextMenu* pCM,
+    _In_ UINT fCMIC,
+    _In_opt_ LPCSTR pszVerb);
+BOOL WINAPI IContextMenu_Invoke(
+    _In_ IContextMenu *pContextMenu,
+    _In_ HWND hwnd,
+    _In_ LPCSTR lpVerb,
+    _In_ UINT uFlags);
+
 /*
     string functions
 */

Reply via email to