[EXPLORER-NEW]
[reactos.git] / base / shell / explorer-new / startctxmnu.cpp
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 HWND hWndOwner;
33 CComPtr<ITrayWindow> TrayWnd;
34 CComPtr<IContextMenu> pcm;
35 CComPtr<IShellFolder> psf;
36 LPITEMIDLIST pidl;
37
38 HRESULT CreateContextMenuFromShellFolderPidl(HMENU hPopup)
39 {
40 CComPtr<IContextMenu> pcm;
41 HRESULT hRet;
42
43 hRet = psf->GetUIObjectOf(hWndOwner, 1, (LPCITEMIDLIST *) &pidl, IID_NULL_PPV_ARG(IContextMenu, &pcm));
44 if (SUCCEEDED(hRet))
45 {
46 if (hPopup != NULL)
47 {
48 hRet = pcm->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 (LoadString(hExplorerInstance,
74 IDS_PROPERTIES,
75 szBuf,
76 sizeof(szBuf) / sizeof(szBuf[0])))
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(hWndOwner,
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 (LoadString(hExplorerInstance,
107 IDS_OPEN_ALL_USERS,
108 szBuf,
109 sizeof(szBuf) / sizeof(szBuf[0])))
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 (LoadString(hExplorerInstance,
119 IDS_EXPLORE_ALL_USERS,
120 szBuf,
121 sizeof(szBuf) / sizeof(szBuf[0])))
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 this->TrayWnd = pTrayWnd;
137 this->hWndOwner = 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 pcm = NULL;
154
155 pidlStart = SHCloneSpecialIDList(hWndOwner, CSIDL_STARTMENU, TRUE);
156
157 if (pidlStart != NULL)
158 {
159 pidl = ILClone(ILFindLastID(pidlStart));
160 ILRemoveLastID(pidlStart);
161
162 if (pidl != NULL)
163 {
164 hRet = SHGetDesktopFolder(&psfDesktop);
165 if (SUCCEEDED(hRet))
166 {
167 hRet = psfDesktop->BindToObject(pidlStart, NULL, IID_PPV_ARG(IShellFolder, &psf));
168 if (SUCCEEDED(hRet))
169 {
170 CreateContextMenuFromShellFolderPidl(hPopup);
171 AddStartContextMenuItems(hPopup);
172 }
173 }
174 }
175
176 ILFree(pidlStart);
177 }
178
179 return NULL;
180 }
181
182 virtual HRESULT STDMETHODCALLTYPE
183 InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
184 {
185 UINT uiCmdId = (UINT)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 = hWndOwner;
196 cmici.lpVerb = MAKEINTRESOURCEA(uiCmdId - ID_SHELL_CMD_FIRST);
197 cmici.nShow = SW_NORMAL;
198
199 /* FIXME: Support Unicode!!! */
200 if (SHGetPathFromIDListA(pidl, szDir))
201 {
202 cmici.lpDirectory = szDir;
203 }
204
205 pcm->InvokeCommand(&cmici);
206 }
207 else
208 {
209 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 (pidl)
232 ILFree(pidl);
233 }
234
235 BEGIN_COM_MAP(CStartMenuBtnCtxMenu)
236 COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
237 END_COM_MAP()
238 };
239 HRESULT StartMenuBtnCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu)
240 {
241 CStartMenuBtnCtxMenu * mnu = new CComObject<CStartMenuBtnCtxMenu>();
242 mnu->Initialize(TrayWnd, hWndOwner);
243 *ppCtxMenu = mnu;
244 return S_OK;
245 }