[SHLWAPI] SHInvokeCommandOnContextMenu[Ex] and SHInvokeCommandWithFlagsAndSite (#7228)

This commit is contained in:
Whindmar Saksit 2024-08-19 00:32:46 +02:00 committed by GitHub
parent e83ec236fa
commit 53e930e97f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 199 additions and 50 deletions

View file

@ -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]

View file

@ -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)

View file

@ -33,8 +33,164 @@
#include <strsafe.h>
#ifndef FAILED_UNEXPECTEDLY
#define FAILED_UNEXPECTEDLY FAILED /* FIXME: Make shellutils.h usable without ATL */
#endif
WINE_DEFAULT_DEBUG_CHANNEL(shell);
static inline WORD
GetVersionMajorMinor()
{
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];
if (!pCM)
return E_INVALIDARG;
hOldCursor = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
info.nShow = SW_NORMAL;
if (pUnk)
IUnknown_SetSite(pCM, pUnk);
if (IS_INTRESOURCE(pszVerb))
{
hMenu = CreatePopupMenu();
if (hMenu)
{
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);
}
}
SetCursor(hOldCursor);
if (!FAILED_UNEXPECTEDLY(hr) && (iDefItem != -1 || info.lpVerb))
{
if (!hWnd)
info.fMask |= CMIC_MASK_FLAG_NO_UI;
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 */ }
}
if (pUnk)
IUnknown_SetSite(pCM, NULL);
if (hMenu)
DestroyMenu(hMenu);
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;
}
/*************************************************************************
* IContextMenu_Invoke [SHLWAPI.207]
*
@ -48,52 +204,10 @@ IContextMenu_Invoke(
_In_ LPCSTR lpVerb,
_In_ UINT uFlags)
{
CMINVOKECOMMANDINFO info;
BOOL ret = FALSE;
INT iDefItem = 0;
HMENU hMenu = NULL;
HCURSOR hOldCursor;
TRACE("(%p, %p, %s, %u)\n", pContextMenu, hwnd, debugstr_a(lpVerb), uFlags);
if (!pContextMenu)
return FALSE;
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 (IS_INTRESOURCE(lpVerb))
{
hMenu = CreatePopupMenu();
if (hMenu)
{
pContextMenu->QueryContextMenu(hMenu, 0, 1, MAXSHORT, uFlags | CMF_DEFAULTONLY);
iDefItem = GetMenuDefaultItem(hMenu, 0, 0);
if (iDefItem != -1)
info.lpVerb = MAKEINTRESOURCEA(iDefItem - 1);
}
}
if (iDefItem != -1 || info.lpVerb)
{
if (!hwnd)
info.fMask |= CMIC_MASK_FLAG_NO_UI;
ret = SUCCEEDED(pContextMenu->InvokeCommand(&info));
}
/* Invoking itself doesn't need the menu object, but getting the command info
needs the menu. */
if (hMenu)
DestroyMenu(hMenu);
SetCursor(hOldCursor);
return ret;
HRESULT hr = SHInvokeCommandOnContextMenuInternal(hwnd, NULL, pContextMenu, 0,
uFlags, lpVerb, NULL, false);
return !FAILED_UNEXPECTEDLY(hr);
}
/*************************************************************************

View file

@ -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
*/