xref: /reactos/dll/win32/shlwapi/utils.cpp (revision ac0bcf4a)
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 
81 /*************************************************************************
82  * PathFileExistsDefExtAndAttributesW [SHLWAPI.511]
83  *
84  * @param pszPath The path string.
85  * @param dwWhich The WHICH_... flags.
86  * @param pdwFileAttributes A pointer to the file attributes. Optional.
87  * @return TRUE if successful.
88  */
89 BOOL WINAPI
90 PathFileExistsDefExtAndAttributesW(
91     _Inout_ LPWSTR pszPath,
92     _In_ DWORD dwWhich,
93     _Out_opt_ LPDWORD pdwFileAttributes)
94 {
95     TRACE("(%s, 0x%lX, %p)\n", debugstr_w(pszPath), dwWhich, pdwFileAttributes);
96 
97     if (pdwFileAttributes)
98         *pdwFileAttributes = INVALID_FILE_ATTRIBUTES;
99 
100     if (!pszPath)
101         return FALSE;
102 
103     if (!dwWhich || (*PathFindExtensionW(pszPath) && (dwWhich & WHICH_OPTIONAL)))
104         return PathFileExistsAndAttributesW(pszPath, pdwFileAttributes);
105 
106     if (!PathFileExistsDefExtW(pszPath, dwWhich))
107     {
108         if (pdwFileAttributes)
109             *pdwFileAttributes = INVALID_FILE_ATTRIBUTES;
110         return FALSE;
111     }
112 
113     if (pdwFileAttributes)
114         *pdwFileAttributes = GetFileAttributesW(pszPath);
115 
116     return TRUE;
117 }
118