From 80381b057849bb0c13c7ab3d281ffbd4d0c3ab36 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Sat, 14 Jun 2025 20:57:33 +0900 Subject: [PATCH] [SHLWAPI][SHLWAPI_APITEST][SDK] Implement IsQSForward (#8124) Implementing missing features... JIRA issue: CORE-19278 - Implement IsQSForward function. - Modify IsQSForward prototype in - Add IsQSForward testcase to shlwapi_apitest. --- dll/win32/shlwapi/ordinal.c | 75 ++++++ .../rostests/apitests/shlwapi/CMakeLists.txt | 1 + .../rostests/apitests/shlwapi/IsQSForward.c | 216 ++++++++++++++++++ modules/rostests/apitests/shlwapi/testlist.c | 2 + sdk/include/reactos/shlwapi_undoc.h | 2 +- 5 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 modules/rostests/apitests/shlwapi/IsQSForward.c diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c index 2e58c120644..9106c2696e5 100644 --- a/dll/win32/shlwapi/ordinal.c +++ b/dll/win32/shlwapi/ordinal.c @@ -2232,11 +2232,86 @@ HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGro * @ [SHLWAPI.202] * */ +#ifdef __REACTOS__ +HRESULT WINAPI +IsQSForward(_In_opt_ REFGUID pguidCmdGroup, _In_ ULONG cCmds, _In_ OLECMD *prgCmds) +{ + DWORD cmdFlags = 0; + OLECMDID cmdID; + ULONG iCmd; + enum { + CMD_FLAG_SUPPORTED_BASIC = 0x1, + CMD_FLAG_SUPPORTED_ADVANCED = 0x2, + CMD_FLAG_NOT_SUPPORTED = 0x4, + }; + + TRACE("(%s, %lu, %p)\n", wine_dbgstr_guid(pguidCmdGroup), cCmds, prgCmds); + + if ((LONG)cCmds <= 0) + return OLECMDERR_E_NOTSUPPORTED; + + if (!pguidCmdGroup) + { + for (iCmd = 0; iCmd < cCmds; ++iCmd) + { + cmdID = prgCmds[iCmd].cmdID; + if (cmdID <= OLECMDID_PROPERTIES) + { + cmdFlags |= CMD_FLAG_NOT_SUPPORTED; // Not supported + continue; + } + + if (cmdID <= OLECMDID_PASTE || cmdID == OLECMDID_SELECTALL) + { + cmdFlags |= CMD_FLAG_SUPPORTED_BASIC; + continue; + } + + if (cmdID <= OLECMDID_UPDATECOMMANDS || + (OLECMDID_HIDETOOLBARS <= cmdID && cmdID != OLECMDID_ENABLE_INTERACTION)) + { + cmdFlags |= CMD_FLAG_NOT_SUPPORTED; // Not supported + continue; + } + + cmdFlags |= CMD_FLAG_SUPPORTED_ADVANCED; + } + } + else + { + if (!IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) + { +#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) + return OLECMDERR_E_UNKNOWNGROUP; +#else + return OLECMDERR_E_NOTSUPPORTED; +#endif + } + + for (iCmd = 0; iCmd < cCmds; ++iCmd) + { + cmdID = prgCmds[iCmd].cmdID; + if (cmdID == OLECMDID_SELECTALL || + (OLECMDID_SHOWFIND <= cmdID && cmdID <= OLECMDID_SHOWPRINT)) + { + cmdFlags |= CMD_FLAG_SUPPORTED_BASIC; + break; + } + } + } + + if (!cmdFlags || (cmdFlags & CMD_FLAG_NOT_SUPPORTED)) + return OLECMDERR_E_NOTSUPPORTED; // Not supported + + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, cmdFlags); +} +#else HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds) { FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds); return DRAGDROP_E_NOTREGISTERED; } +#endif /************************************************************************* * @ [SHLWAPI.204] diff --git a/modules/rostests/apitests/shlwapi/CMakeLists.txt b/modules/rostests/apitests/shlwapi/CMakeLists.txt index 49e5ef69056..3138093a85e 100644 --- a/modules/rostests/apitests/shlwapi/CMakeLists.txt +++ b/modules/rostests/apitests/shlwapi/CMakeLists.txt @@ -7,6 +7,7 @@ include_directories($) list(APPEND SOURCE AssocQueryString.c IShellFolderHelpers.cpp + IsQSForward.c PathFileExistsDefExtAndAttributesW.c PathFindOnPath.c PathIsUNC.c diff --git a/modules/rostests/apitests/shlwapi/IsQSForward.c b/modules/rostests/apitests/shlwapi/IsQSForward.c new file mode 100644 index 00000000000..30f0187ff1d --- /dev/null +++ b/modules/rostests/apitests/shlwapi/IsQSForward.c @@ -0,0 +1,216 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Tests for IsQSForward + * COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ + */ + +#include +#include +#include +#include +#include +#include +#include + +static HRESULT +IsQSForwardMockup(_In_opt_ REFGUID pguidCmdGroup, _In_ ULONG cCmds, _In_ OLECMD *prgCmds) +{ + DWORD cmdFlags = 0; + OLECMDID cmdID; + ULONG iCmd; + enum { + CMD_FLAG_SUPPORTED_BASIC = 0x1, + CMD_FLAG_SUPPORTED_ADVANCED = 0x2, + CMD_FLAG_NOT_SUPPORTED = 0x4, + }; + + //TRACE("(%s, %lu, %p)\n", wine_dbgstr_guid(pguidCmdGroup), cCmds, prgCmds); + + if ((LONG)cCmds <= 0) + return OLECMDERR_E_NOTSUPPORTED; + + if (!pguidCmdGroup) + { + for (iCmd = 0; iCmd < cCmds; ++iCmd) + { + cmdID = prgCmds[iCmd].cmdID; + if (cmdID <= OLECMDID_PROPERTIES) + { + cmdFlags |= CMD_FLAG_NOT_SUPPORTED; // Not supported + continue; + } + + if (cmdID <= OLECMDID_PASTE || cmdID == OLECMDID_SELECTALL) + { + cmdFlags |= CMD_FLAG_SUPPORTED_BASIC; + continue; + } + + if (cmdID <= OLECMDID_UPDATECOMMANDS || + (OLECMDID_HIDETOOLBARS <= cmdID && cmdID != OLECMDID_ENABLE_INTERACTION)) + { + cmdFlags |= CMD_FLAG_NOT_SUPPORTED; // Not supported + continue; + } + + cmdFlags |= CMD_FLAG_SUPPORTED_ADVANCED; + } + } + else + { + if (!IsEqualGUID(&CGID_Explorer, pguidCmdGroup)) + { + if (IsWindowsVistaOrGreater()) + return OLECMDERR_E_UNKNOWNGROUP; + else + return OLECMDERR_E_NOTSUPPORTED; + } + + for (iCmd = 0; iCmd < cCmds; ++iCmd) + { + cmdID = prgCmds[iCmd].cmdID; + if (cmdID == OLECMDID_SELECTALL || + (OLECMDID_SHOWFIND <= cmdID && cmdID <= OLECMDID_SHOWPRINT)) + { + cmdFlags |= CMD_FLAG_SUPPORTED_BASIC; + break; + } + } + } + + if (!cmdFlags || (cmdFlags & CMD_FLAG_NOT_SUPPORTED)) + return OLECMDERR_E_NOTSUPPORTED; // Not supported + + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, cmdFlags); +} + +START_TEST(IsQSForward) +{ + OLECMD cmds[2]; + LONG cmdID, cmdID2; + HRESULT ret1, ret2; + ULONG cCmds; + BOOL bExcept1, bExcept2; + const GUID *pGUID = NULL; + enum { LOW_VALUE = -99, HIGH_VALUE = OLECMDID_MEDIA_PLAYBACK }; + + cmds[0].cmdf = 0; + + cCmds = 0; + for (cmdID = LOW_VALUE; cmdID <= HIGH_VALUE; ++cmdID) + { + cmds[0].cmdID = cmdID; + ret1 = IsQSForward(pGUID, cCmds, cmds); + ret2 = IsQSForwardMockup(pGUID, cCmds, cmds); + ok(ret1 == ret2, "cmdID: %ld (%ld vs %ld)\n", cmdID, ret1, ret2); + } + + // cCmds = 0 and NULL cmds + for (cmdID = LOW_VALUE; cmdID <= HIGH_VALUE; ++cmdID) + { + cmds[0].cmdID = cmdID; + ret1 = IsQSForward(pGUID, cCmds, NULL); + ret2 = IsQSForwardMockup(pGUID, cCmds, NULL); + ok(ret1 == ret2, "cmdID: %ld (%ld vs %ld)\n", cmdID, ret1, ret2); + } + + cCmds = 1; + for (cmdID = LOW_VALUE; cmdID <= HIGH_VALUE; ++cmdID) + { + cmds[0].cmdID = cmdID; + ret1 = IsQSForward(pGUID, cCmds, cmds); + ret2 = IsQSForwardMockup(pGUID, cCmds, cmds); + ok(ret1 == ret2, "cmdID: %ld (%ld vs %ld)\n", cmdID, ret1, ret2); + } + + // cCmds = 1 and NULL cmds + for (cmdID = LOW_VALUE; cmdID <= HIGH_VALUE; ++cmdID) + { + cmds[0].cmdID = cmdID; + + ret1 = ret2 = 0xDEADFACE; + bExcept1 = bExcept2 = FALSE; + + _SEH2_TRY + { + ret1 = IsQSForward(pGUID, cCmds, NULL); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + bExcept1 = TRUE; + } + _SEH2_END; + + _SEH2_TRY + { + ret2 = IsQSForwardMockup(pGUID, cCmds, NULL); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + bExcept2 = TRUE; + } + _SEH2_END; + + ok(ret1 == ret2, "cmdID: %ld (%ld vs %ld)\n", cmdID, ret1, ret2); + ok((bExcept1 && bExcept2), "cmdID: %ld (%d vs %d)\n", cmdID, bExcept1, bExcept2); + } + + pGUID = &CGID_Explorer; + for (cmdID = LOW_VALUE; cmdID <= HIGH_VALUE; ++cmdID) + { + cmds[0].cmdID = cmdID; + ret1 = IsQSForward(pGUID, cCmds, cmds); + ret2 = IsQSForwardMockup(pGUID, cCmds, cmds); + ok(ret1 == ret2, "cmdID: %ld (%ld vs %ld)\n", cmdID, ret1, ret2); + } + + pGUID = &IID_IUnknown; + for (cmdID = LOW_VALUE; cmdID <= HIGH_VALUE; ++cmdID) + { + cmds[0].cmdID = cmdID; + ret1 = IsQSForward(pGUID, cCmds, cmds); + ret2 = IsQSForwardMockup(pGUID, cCmds, cmds); + ok(ret1 == ret2, "cmdID: %ld (%ld vs %ld)\n", cmdID, ret1, ret2); + } + + cCmds = 2; + pGUID = NULL; + for (cmdID = LOW_VALUE; cmdID <= HIGH_VALUE; ++cmdID) + { + for (cmdID2 = LOW_VALUE; cmdID2 <= HIGH_VALUE; ++cmdID2) + { + cmds[0].cmdID = cmdID; + cmds[1].cmdID = cmdID2; + ret1 = IsQSForward(pGUID, cCmds, cmds); + ret2 = IsQSForwardMockup(pGUID, cCmds, cmds); + ok(ret1 == ret2, "cmdID: %ld (%ld vs %ld)\n", cmdID, ret1, ret2); + } + } + + pGUID = &CGID_Explorer; + for (cmdID = LOW_VALUE; cmdID <= HIGH_VALUE; ++cmdID) + { + cmds[0].cmdID = cmdID; + for (cmdID2 = LOW_VALUE; cmdID2 <= HIGH_VALUE; ++cmdID2) + { + cmds[1].cmdID = cmdID2; + ret1 = IsQSForward(pGUID, cCmds, cmds); + ret2 = IsQSForwardMockup(pGUID, cCmds, cmds); + ok(ret1 == ret2, "cmdID: %ld (%ld vs %ld)\n", cmdID, ret1, ret2); + } + } + + pGUID = &IID_IUnknown; + for (cmdID = LOW_VALUE; cmdID <= HIGH_VALUE; ++cmdID) + { + cmds[0].cmdID = cmdID; + for (cmdID2 = LOW_VALUE; cmdID2 <= HIGH_VALUE; ++cmdID2) + { + cmds[1].cmdID = cmdID2; + ret1 = IsQSForward(pGUID, cCmds, cmds); + ret2 = IsQSForwardMockup(pGUID, cCmds, cmds); + ok(ret1 == ret2, "cmdID: %ld (%ld vs %ld)\n", cmdID, ret1, ret2); + } + } +} diff --git a/modules/rostests/apitests/shlwapi/testlist.c b/modules/rostests/apitests/shlwapi/testlist.c index b44f2e181fa..f47c496b2b0 100644 --- a/modules/rostests/apitests/shlwapi/testlist.c +++ b/modules/rostests/apitests/shlwapi/testlist.c @@ -5,6 +5,7 @@ extern void func_AssocQueryString(void); extern void func_PathFileExistsDefExtAndAttributesW(void); extern void func_PathFindOnPath(void); extern void func_IShellFolderHelpers(void); +extern void func_IsQSForward(void); extern void func_isuncpath(void); extern void func_isuncpathserver(void); extern void func_isuncpathservershare(void); @@ -24,6 +25,7 @@ const struct test winetest_testlist[] = { "PathFileExistsDefExtAndAttributesW", func_PathFileExistsDefExtAndAttributesW }, { "PathFindOnPath", func_PathFindOnPath }, { "IShellFolderHelpers", func_IShellFolderHelpers }, + { "IsQSForward", func_IsQSForward }, { "PathIsUNC", func_isuncpath }, { "PathIsUNCServer", func_isuncpathserver }, { "PathIsUNCServerShare", func_isuncpathservershare }, diff --git a/sdk/include/reactos/shlwapi_undoc.h b/sdk/include/reactos/shlwapi_undoc.h index 94162ffc34f..61896d93a29 100644 --- a/sdk/include/reactos/shlwapi_undoc.h +++ b/sdk/include/reactos/shlwapi_undoc.h @@ -111,7 +111,7 @@ int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown); HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved, REFGUID riidCmdGrp, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText); HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut); -HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds); +HRESULT WINAPI IsQSForward(_In_opt_ REFGUID pguidCmdGroup, _In_ ULONG cCmds, _In_ OLECMD *prgCmds); BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild); HRESULT WINAPI SHForwardContextMenuMsg(IUnknown* pUnk, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult, BOOL useIContextMenu2); VOID WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id);