https://git.reactos.org/?p=reactos.git;a=commitdiff;h=53e930e97f2cd75760ebd…
commit 53e930e97f2cd75760ebdbca3e6e355faec0d52b
Author: Whindmar Saksit <whindsaks(a)proton.me>
AuthorDate: Mon Aug 19 00:32:46 2024 +0200
Commit: GitHub <noreply(a)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
*/