xref: /reactos/base/shell/explorer/startctxmnu.cpp (revision 426598c6)
1 /*
2  * ReactOS Explorer
3  *
4  * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "precomp.h"
22 
23 /*
24  * Start menu button context menu
25  */
26 
27 class CStartMenuBtnCtxMenu :
28     public CComCoClass<CStartMenuBtnCtxMenu>,
29     public CComObjectRootEx<CComMultiThreadModelNoCS>,
30     public IContextMenu
31 {
32     CComPtr<ITrayWindow>  m_TrayWnd;
33     CComPtr<IContextMenu> m_Inner;
34     CComPtr<IShellFolder> m_Folder;
35     UINT m_idCmdCmLast;
36 
37     HWND m_Owner;
38     LPITEMIDLIST m_FolderPidl;
39 
40     HRESULT CreateContextMenuFromShellFolderPidl(HMENU hPopup)
41     {
42         HRESULT hRet;
43 
44         hRet = m_Folder->GetUIObjectOf(m_Owner, 1, (LPCITEMIDLIST *) &m_FolderPidl, IID_NULL_PPV_ARG(IContextMenu, &m_Inner));
45         if (SUCCEEDED(hRet))
46         {
47             if (hPopup != NULL)
48             {
49                 hRet = m_Inner->QueryContextMenu(
50                     hPopup,
51                     0,
52                     ID_SHELL_CMD_FIRST,
53                     ID_SHELL_CMD_LAST,
54                     CMF_VERBSONLY);
55 
56                 if (SUCCEEDED(hRet))
57                 {
58                     return hRet;
59                 }
60 
61                 DestroyMenu(hPopup);
62             }
63         }
64 
65         return E_FAIL;
66     }
67 
68     VOID AddStartContextMenuItems(IN HMENU hPopup)
69     {
70         WCHAR szBuf[MAX_PATH];
71         HRESULT hRet;
72 
73         /* Add the "Open All Users" menu item */
74         if (LoadStringW(hExplorerInstance,
75                         IDS_PROPERTIES,
76                         szBuf,
77                         _countof(szBuf)))
78         {
79             AppendMenu(hPopup,
80                        MF_STRING,
81                        ID_SHELL_CMD_PROPERTIES,
82                        szBuf);
83         }
84 
85         if (!SHRestricted(REST_NOCOMMONGROUPS))
86         {
87             /* Check if we should add menu items for the common start menu */
88             hRet = SHGetFolderPath(m_Owner,
89                                    CSIDL_COMMON_STARTMENU,
90                                    NULL,
91                                    SHGFP_TYPE_CURRENT,
92                                    szBuf);
93             if (SUCCEEDED(hRet) && hRet != S_FALSE)
94             {
95                 /* The directory exists, but only show the items if the
96                 user can actually make any changes to the common start
97                 menu. This is most likely only the case if the user
98                 has administrative rights! */
99                 if (IsUserAnAdmin())
100                 {
101                     AppendMenu(hPopup,
102                                MF_SEPARATOR,
103                                0,
104                                NULL);
105 
106                     /* Add the "Open All Users" menu item */
107                     if (LoadStringW(hExplorerInstance,
108                                     IDS_OPEN_ALL_USERS,
109                                     szBuf,
110                                     _countof(szBuf)))
111                     {
112                         AppendMenu(hPopup,
113                                    MF_STRING,
114                                    ID_SHELL_CMD_OPEN_ALL_USERS,
115                                    szBuf);
116                     }
117 
118                     /* Add the "Explore All Users" menu item */
119                     if (LoadStringW(hExplorerInstance,
120                                     IDS_EXPLORE_ALL_USERS,
121                                     szBuf,
122                                     _countof(szBuf)))
123                     {
124                         AppendMenu(hPopup,
125                                    MF_STRING,
126                                    ID_SHELL_CMD_EXPLORE_ALL_USERS,
127                                    szBuf);
128                     }
129                 }
130             }
131         }
132     }
133 
134 public:
135     HRESULT Initialize(ITrayWindow * pTrayWnd, IN HWND hWndOwner)
136     {
137         m_TrayWnd = pTrayWnd;
138         m_Owner = hWndOwner;
139         return S_OK;
140     }
141 
142     virtual HRESULT STDMETHODCALLTYPE
143         QueryContextMenu(HMENU hPopup,
144                          UINT indexMenu,
145                          UINT idCmdFirst,
146                          UINT idCmdLast,
147                          UINT uFlags)
148     {
149         LPITEMIDLIST pidlStart;
150         CComPtr<IShellFolder> psfDesktop;
151         HRESULT hRet;
152 
153         psfDesktop = NULL;
154         m_Inner = NULL;
155 
156         pidlStart = SHCloneSpecialIDList(m_Owner, CSIDL_STARTMENU, TRUE);
157 
158         if (pidlStart != NULL)
159         {
160             m_FolderPidl = ILClone(ILFindLastID(pidlStart));
161             ILRemoveLastID(pidlStart);
162 
163             if (m_FolderPidl != NULL)
164             {
165                 hRet = SHGetDesktopFolder(&psfDesktop);
166                 if (SUCCEEDED(hRet))
167                 {
168                     hRet = psfDesktop->BindToObject(pidlStart, NULL, IID_PPV_ARG(IShellFolder, &m_Folder));
169                     if (SUCCEEDED(hRet))
170                     {
171                         hRet = CreateContextMenuFromShellFolderPidl(hPopup);
172                         m_idCmdCmLast = (SUCCEEDED(hRet)) ? HRESULT_CODE(hRet) : ID_SHELL_CMD_LAST;
173                         AddStartContextMenuItems(hPopup);
174                     }
175                 }
176             }
177 
178             ILFree(pidlStart);
179         }
180 
181         return S_OK;
182     }
183 
184     virtual HRESULT STDMETHODCALLTYPE
185         InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
186     {
187         UINT uiCmdId = PtrToUlong(lpici->lpVerb);
188         if (uiCmdId != 0)
189         {
190             if ((uiCmdId >= ID_SHELL_CMD_FIRST) && (uiCmdId < m_idCmdCmLast))
191             {
192                 CMINVOKECOMMANDINFO cmici = { 0 };
193                 CHAR szDir[MAX_PATH];
194 
195                 /* Setup and invoke the shell command */
196                 cmici.cbSize = sizeof(cmici);
197                 cmici.hwnd = m_Owner;
198                 cmici.lpVerb = MAKEINTRESOURCEA(uiCmdId - ID_SHELL_CMD_FIRST);
199                 cmici.nShow = SW_NORMAL;
200 
201                 /* FIXME: Support Unicode!!! */
202                 if (SHGetPathFromIDListA(m_FolderPidl, szDir))
203                 {
204                     cmici.lpDirectory = szDir;
205                 }
206 
207                 m_Inner->InvokeCommand(&cmici);
208             }
209             else
210             {
211                 m_TrayWnd->ExecContextMenuCmd(uiCmdId);
212             }
213         }
214         return S_OK;
215     }
216 
217     virtual HRESULT STDMETHODCALLTYPE
218         GetCommandString(UINT_PTR idCmd,
219                          UINT uType,
220                          UINT *pwReserved,
221                          LPSTR pszName,
222                          UINT cchMax)
223     {
224         return E_NOTIMPL;
225     }
226 
227     CStartMenuBtnCtxMenu()
228     {
229         m_idCmdCmLast = ID_SHELL_CMD_LAST;
230     }
231 
232     virtual ~CStartMenuBtnCtxMenu()
233     {
234         if (m_FolderPidl)
235             ILFree(m_FolderPidl);
236     }
237 
238     BEGIN_COM_MAP(CStartMenuBtnCtxMenu)
239         COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
240     END_COM_MAP()
241 };
242 
243 HRESULT CStartMenuBtnCtxMenu_CreateInstance(ITrayWindow * m_TrayWnd, IN HWND m_Owner, IContextMenu ** ppCtxMenu)
244 {
245     return ShellObjectCreatorInit<CStartMenuBtnCtxMenu>(m_TrayWnd, m_Owner, IID_PPV_ARG(IContextMenu, ppCtxMenu));
246 }
247