xref: /reactos/dll/win32/shlwapi/utils.cpp (revision cce399e7)
1 /*
2  * PROJECT:     ReactOS Shell
3  * LICENSE:     LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4  * PURPOSE:     Implement shell light-weight utility functions
5  * COPYRIGHT:   Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6  */
7 
8 #define _ATL_NO_EXCEPTIONS
9 #include "precomp.h"
10 #include <shellapi.h>
11 #include <shlwapi.h>
12 #include <shlwapi_undoc.h>
13 #include <shlobj_undoc.h>
14 #include <shlguid_undoc.h>
15 #include <atlstr.h>
16 #include <strsafe.h>
17 
18 WINE_DEFAULT_DEBUG_CHANNEL(shell);
19 
20 /*************************************************************************
21  * IContextMenu_Invoke [SHLWAPI.207]
22  *
23  * Used by Win:SHELL32!CISFBand::_TrySimpleInvoke.
24  */
25 EXTERN_C
26 BOOL WINAPI
27 IContextMenu_Invoke(
28     _In_ IContextMenu *pContextMenu,
29     _In_ HWND hwnd,
30     _In_ LPCSTR lpVerb,
31     _In_ UINT uFlags)
32 {
33     CMINVOKECOMMANDINFO info;
34     BOOL ret = FALSE;
35     INT iDefItem = 0;
36     HMENU hMenu = NULL;
37     HCURSOR hOldCursor;
38 
39     TRACE("(%p, %p, %s, %u)\n", pContextMenu, hwnd, debugstr_a(lpVerb), uFlags);
40 
41     if (!pContextMenu)
42         return FALSE;
43 
44     hOldCursor = SetCursor(LoadCursorW(NULL, (LPCWSTR)IDC_WAIT));
45 
46     ZeroMemory(&info, sizeof(info));
47     info.cbSize = sizeof(info);
48     info.hwnd = hwnd;
49     info.nShow = SW_NORMAL;
50     info.lpVerb = lpVerb;
51 
52     if (IS_INTRESOURCE(lpVerb))
53     {
54         hMenu = CreatePopupMenu();
55         if (hMenu)
56         {
57             pContextMenu->QueryContextMenu(hMenu, 0, 1, MAXSHORT, uFlags | CMF_DEFAULTONLY);
58             iDefItem = GetMenuDefaultItem(hMenu, 0, 0);
59             if (iDefItem != -1)
60                 info.lpVerb = MAKEINTRESOURCEA(iDefItem - 1);
61         }
62     }
63 
64     if (iDefItem != -1 || info.lpVerb)
65     {
66         if (!hwnd)
67             info.fMask |= CMIC_MASK_FLAG_NO_UI;
68         ret = SUCCEEDED(pContextMenu->InvokeCommand(&info));
69     }
70 
71     /* Invoking itself doesn't need the menu object, but getting the command info
72        needs the menu. */
73     if (hMenu)
74         DestroyMenu(hMenu);
75 
76     SetCursor(hOldCursor);
77 
78     return ret;
79 }
80