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