xref: /reactos/base/shell/explorer/startctxmnu.cpp (revision 02e84521)
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 
36     HWND m_Owner;
37     LPITEMIDLIST m_FolderPidl;
38 
39     HRESULT CreateContextMenuFromShellFolderPidl(HMENU hPopup)
40     {
41         HRESULT hRet;
42 
43         hRet = m_Folder->GetUIObjectOf(m_Owner, 1, (LPCITEMIDLIST *) &m_FolderPidl, IID_NULL_PPV_ARG(IContextMenu, &m_Inner));
44         if (SUCCEEDED(hRet))
45         {
46             if (hPopup != NULL)
47             {
48                 hRet = m_Inner->QueryContextMenu(
49                     hPopup,
50                     0,
51                     ID_SHELL_CMD_FIRST,
52                     ID_SHELL_CMD_LAST,
53                     CMF_VERBSONLY);
54 
55                 if (SUCCEEDED(hRet))
56                 {
57                     return hRet;
58                 }
59 
60                 DestroyMenu(hPopup);
61             }
62         }
63 
64         return E_FAIL;
65     }
66 
67     VOID AddStartContextMenuItems(IN HMENU hPopup)
68     {
69         WCHAR szBuf[MAX_PATH];
70         HRESULT hRet;
71 
72         /* Add the "Open All Users" menu item */
73         if (LoadStringW(hExplorerInstance,
74                         IDS_PROPERTIES,
75                         szBuf,
76                         _countof(szBuf)))
77         {
78             AppendMenu(hPopup,
79                        MF_STRING,
80                        ID_SHELL_CMD_PROPERTIES,
81                        szBuf);
82         }
83 
84         if (!SHRestricted(REST_NOCOMMONGROUPS))
85         {
86             /* Check if we should add menu items for the common start menu */
87             hRet = SHGetFolderPath(m_Owner,
88                                    CSIDL_COMMON_STARTMENU,
89                                    NULL,
90                                    SHGFP_TYPE_CURRENT,
91                                    szBuf);
92             if (SUCCEEDED(hRet) && hRet != S_FALSE)
93             {
94                 /* The directory exists, but only show the items if the
95                 user can actually make any changes to the common start
96                 menu. This is most likely only the case if the user
97                 has administrative rights! */
98                 if (IsUserAnAdmin())
99                 {
100                     AppendMenu(hPopup,
101                                MF_SEPARATOR,
102                                0,
103                                NULL);
104 
105                     /* Add the "Open All Users" menu item */
106                     if (LoadStringW(hExplorerInstance,
107                                     IDS_OPEN_ALL_USERS,
108                                     szBuf,
109                                     _countof(szBuf)))
110                     {
111                         AppendMenu(hPopup,
112                                    MF_STRING,
113                                    ID_SHELL_CMD_OPEN_ALL_USERS,
114                                    szBuf);
115                     }
116 
117                     /* Add the "Explore All Users" menu item */
118                     if (LoadStringW(hExplorerInstance,
119                                     IDS_EXPLORE_ALL_USERS,
120                                     szBuf,
121                                     _countof(szBuf)))
122                     {
123                         AppendMenu(hPopup,
124                                    MF_STRING,
125                                    ID_SHELL_CMD_EXPLORE_ALL_USERS,
126                                    szBuf);
127                     }
128                 }
129             }
130         }
131     }
132 
133 public:
134     HRESULT Initialize(ITrayWindow * pTrayWnd, IN HWND hWndOwner)
135     {
136         m_TrayWnd = pTrayWnd;
137         m_Owner = hWndOwner;
138         return S_OK;
139     }
140 
141     virtual HRESULT STDMETHODCALLTYPE
142         QueryContextMenu(HMENU hPopup,
143                          UINT indexMenu,
144                          UINT idCmdFirst,
145                          UINT idCmdLast,
146                          UINT uFlags)
147     {
148         LPITEMIDLIST pidlStart;
149         CComPtr<IShellFolder> psfDesktop;
150         HRESULT hRet;
151 
152         psfDesktop = NULL;
153         m_Inner = NULL;
154 
155         pidlStart = SHCloneSpecialIDList(m_Owner, CSIDL_STARTMENU, TRUE);
156 
157         if (pidlStart != NULL)
158         {
159             m_FolderPidl = ILClone(ILFindLastID(pidlStart));
160             ILRemoveLastID(pidlStart);
161 
162             if (m_FolderPidl != NULL)
163             {
164                 hRet = SHGetDesktopFolder(&psfDesktop);
165                 if (SUCCEEDED(hRet))
166                 {
167                     hRet = psfDesktop->BindToObject(pidlStart, NULL, IID_PPV_ARG(IShellFolder, &m_Folder));
168                     if (SUCCEEDED(hRet))
169                     {
170                         CreateContextMenuFromShellFolderPidl(hPopup);
171                         AddStartContextMenuItems(hPopup);
172                     }
173                 }
174             }
175 
176             ILFree(pidlStart);
177         }
178 
179         return S_OK;
180     }
181 
182     virtual HRESULT STDMETHODCALLTYPE
183         InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
184     {
185         UINT uiCmdId = PtrToUlong(lpici->lpVerb);
186         if (uiCmdId != 0)
187         {
188             if ((uiCmdId >= ID_SHELL_CMD_FIRST) && (uiCmdId <= ID_SHELL_CMD_LAST))
189             {
190                 CMINVOKECOMMANDINFO cmici = { 0 };
191                 CHAR szDir[MAX_PATH];
192 
193                 /* Setup and invoke the shell command */
194                 cmici.cbSize = sizeof(cmici);
195                 cmici.hwnd = m_Owner;
196                 cmici.lpVerb = MAKEINTRESOURCEA(uiCmdId - ID_SHELL_CMD_FIRST);
197                 cmici.nShow = SW_NORMAL;
198 
199                 /* FIXME: Support Unicode!!! */
200                 if (SHGetPathFromIDListA(m_FolderPidl, szDir))
201                 {
202                     cmici.lpDirectory = szDir;
203                 }
204 
205                 m_Inner->InvokeCommand(&cmici);
206             }
207             else
208             {
209                 m_TrayWnd->ExecContextMenuCmd(uiCmdId);
210             }
211         }
212         return S_OK;
213     }
214 
215     virtual HRESULT STDMETHODCALLTYPE
216         GetCommandString(UINT_PTR idCmd,
217                          UINT uType,
218                          UINT *pwReserved,
219                          LPSTR pszName,
220                          UINT cchMax)
221     {
222         return E_NOTIMPL;
223     }
224 
225     CStartMenuBtnCtxMenu()
226     {
227     }
228 
229     virtual ~CStartMenuBtnCtxMenu()
230     {
231         if (m_FolderPidl)
232             ILFree(m_FolderPidl);
233     }
234 
235     BEGIN_COM_MAP(CStartMenuBtnCtxMenu)
236         COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
237     END_COM_MAP()
238 };
239 
240 HRESULT CStartMenuBtnCtxMenu_CreateInstance(ITrayWindow * m_TrayWnd, IN HWND m_Owner, IContextMenu ** ppCtxMenu)
241 {
242     CStartMenuBtnCtxMenu * mnu = new CComObject<CStartMenuBtnCtxMenu>();
243     mnu->Initialize(m_TrayWnd, m_Owner);
244     *ppCtxMenu = mnu;
245     return S_OK;
246 }
247