[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; extern DWORD SHLWAPI_ThreadRef_index;
HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*); 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); HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,DWORD);
#endif
BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD); 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) HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
{ {
TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl); TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
#ifdef __REACTOS__
return SHInvokeCommand(hWnd, lpFolder, lpApidl, NULL);
#else
return SHInvokeCommand(hWnd, lpFolder, lpApidl, 0); return SHInvokeCommand(hWnd, lpFolder, lpApidl, 0);
#endif
} }
/************************************************************************* /*************************************************************************
@ -3615,6 +3623,13 @@ UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags,
* executed. * executed.
* Failure: An HRESULT error code indicating the error. * 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) HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, DWORD dwCommandId)
{ {
IContextMenu *iContext; IContextMenu *iContext;
@ -3667,6 +3682,7 @@ HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST
} }
return hRet; return hRet;
} }
#endif /* __REACTOS__ */
/************************************************************************* /*************************************************************************
* @ [SHLWAPI.370] * @ [SHLWAPI.370]

View File

@ -360,7 +360,7 @@
360 stdcall -noname RemoveDirectoryWrapW(wstr) kernel32.RemoveDirectoryW 360 stdcall -noname RemoveDirectoryWrapW(wstr) kernel32.RemoveDirectoryW
361 stdcall -noname GetShortPathNameWrapW(wstr ptr long) kernel32.GetShortPathNameW 361 stdcall -noname GetShortPathNameWrapW(wstr ptr long) kernel32.GetShortPathNameW
362 stdcall -noname GetUserNameWrapW(ptr ptr) advapi32.GetUserNameW 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) 364 stdcall -noname DoesStringRoundTripA(str ptr long)
365 stdcall -noname DoesStringRoundTripW(wstr ptr long) 365 stdcall -noname DoesStringRoundTripW(wstr ptr long)
366 stdcall -noname RegEnumValueWrapW(long long ptr ptr ptr ptr ptr ptr) advapi32.RegEnumValueW 366 stdcall -noname RegEnumValueWrapW(long long ptr ptr ptr ptr ptr ptr) advapi32.RegEnumValueW
@ -537,8 +537,8 @@
537 stub -noname SHBoolSystemParametersInfo 537 stub -noname SHBoolSystemParametersInfo
538 stdcall -noname IUnknown_QueryServiceForWebBrowserApp(ptr ptr ptr) 538 stdcall -noname IUnknown_QueryServiceForWebBrowserApp(ptr ptr ptr)
539 stub -noname IUnknown_ShowBrowserBar 539 stub -noname IUnknown_ShowBrowserBar
540 stub -noname SHInvokeCommandOnContextMenu 540 stdcall -noname SHInvokeCommandOnContextMenu(ptr ptr ptr long str)
541 stub -noname SHInvokeCommandsOnContextMen 541 stub -noname SHInvokeCommandsOnContextMenu
542 stdcall -noname GetUIVersion() 542 stdcall -noname GetUIVersion()
543 stdcall -noname CreateColorSpaceWrapW(ptr) gdi32.CreateColorSpaceW 543 stdcall -noname CreateColorSpaceWrapW(ptr) gdi32.CreateColorSpaceW
544 stub -noname QuerySourceCreateFromKey 544 stub -noname QuerySourceCreateFromKey
@ -568,7 +568,8 @@
568 stdcall AssocQueryStringW(long long wstr wstr ptr ptr) 568 stdcall AssocQueryStringW(long long wstr wstr ptr ptr)
569 stdcall ChrCmpIA(long long) 569 stdcall ChrCmpIA(long long)
570 stdcall ChrCmpIW(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) 572 stdcall ColorHLSToRGB(long long long)
573 stdcall ColorRGBToHLS(long ptr ptr ptr) 573 stdcall ColorRGBToHLS(long ptr ptr ptr)
@ stdcall -private DllGetVersion(ptr) @ stdcall -private DllGetVersion(ptr)
@ -636,7 +637,8 @@
636 stdcall PathIsSameRootA(str str) 636 stdcall PathIsSameRootA(str str)
637 stdcall PathIsSameRootW(wstr wstr) 637 stdcall PathIsSameRootW(wstr wstr)
638 stdcall PathIsSystemFolderA(str long) 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) 640 stdcall PathIsUNCA(str)
641 stdcall PathIsUNCServerA(str) 641 stdcall PathIsUNCServerA(str)
642 stdcall PathIsUNCServerShareA(str) 642 stdcall PathIsUNCServerShareA(str)

View File

@ -33,8 +33,164 @@
#include <strsafe.h> #include <strsafe.h>
#ifndef FAILED_UNEXPECTEDLY
#define FAILED_UNEXPECTEDLY FAILED /* FIXME: Make shellutils.h usable without ATL */
#endif
WINE_DEFAULT_DEBUG_CHANNEL(shell); 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] * IContextMenu_Invoke [SHLWAPI.207]
* *
@ -48,52 +204,10 @@ IContextMenu_Invoke(
_In_ LPCSTR lpVerb, _In_ LPCSTR lpVerb,
_In_ UINT uFlags) _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); TRACE("(%p, %p, %s, %u)\n", pContextMenu, hwnd, debugstr_a(lpVerb), uFlags);
HRESULT hr = SHInvokeCommandOnContextMenuInternal(hwnd, NULL, pContextMenu, 0,
if (!pContextMenu) uFlags, lpVerb, NULL, false);
return FALSE; return !FAILED_UNEXPECTEDLY(hr);
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;
} }
/************************************************************************* /*************************************************************************

View File

@ -93,6 +93,23 @@ HRESULT WINAPI SHILCreateFromPathW (
LPITEMIDLIST * ppidl, LPITEMIDLIST * ppidl,
DWORD *attributes); 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 string functions
*/ */