Reactos
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
23class CStartMenuSite :
24 public CComCoClass<CStartMenuSite>,
25 public CComObjectRootEx<CComMultiThreadModelNoCS>,
26 public IServiceProvider,
27 public ITrayPriv,
28 public IOleCommandTarget,
29 public IMenuPopup
30{
31 CComPtr<ITrayWindow> m_Tray;
32
33public:
34 CStartMenuSite()
35 {
36 }
37
38 virtual ~CStartMenuSite() {}
39
40 // *** IServiceProvider methods ***
41
42 STDMETHODIMP
43 QueryService(
44 IN REFGUID guidService,
45 IN REFIID riid,
46 OUT PVOID *ppvObject) override
47 {
48 if (IsEqualGUID(guidService, SID_SMenuPopup))
49 {
50 return QueryInterface(riid, ppvObject);
51 }
52
53 return E_NOINTERFACE;
54 }
55
56 // *** IOleWindow methods ***
57
58 STDMETHODIMP
59 GetWindow(OUT HWND *phwnd) override
60 {
61 TRACE("ITrayPriv::GetWindow\n");
62
63 *phwnd = m_Tray->GetHWND();
64 if (*phwnd != NULL)
65 return S_OK;
66
67 return E_FAIL;
68 }
69
70 STDMETHODIMP
71 ContextSensitiveHelp(IN BOOL fEnterMode) override
72 {
73 TRACE("ITrayPriv::ContextSensitiveHelp\n");
74 return E_NOTIMPL;
75 }
76
77 STDMETHODIMP
78 Execute(
79 IN IShellFolder *pShellFolder,
80 IN LPCITEMIDLIST pidl) override
81 {
82 HRESULT ret = S_FALSE;
83
84 TRACE("ITrayPriv::Execute\n");
85
86 ret = SHInvokeDefaultCommand(m_Tray->GetHWND(), pShellFolder, pidl);
87
88 return ret;
89 }
90
91 STDMETHODIMP
92 Unknown(
93 IN PVOID Unknown1,
94 IN PVOID Unknown2,
95 IN PVOID Unknown3,
96 IN PVOID Unknown4) override
97 {
98 TRACE("ITrayPriv::Unknown(0x%p,0x%p,0x%p,0x%p)\n", Unknown1, Unknown2, Unknown3, Unknown4);
99 return E_NOTIMPL;
100 }
101
102 virtual BOOL
103 ShowUndockMenuItem(VOID)
104 {
105 TRACE("ShowUndockMenuItem() not implemented!\n");
106 /* FIXME: How do we detect this?! */
107 return FALSE;
108 }
109
110 virtual BOOL
111 ShowSynchronizeMenuItem(VOID)
112 {
113 TRACE("ShowSynchronizeMenuItem() not implemented!\n");
114 /* FIXME: How do we detect this?! */
115 return FALSE;
116 }
117
118 STDMETHODIMP
119 AppendMenu(OUT HMENU* phMenu) override
120 {
121 HMENU hMenu, hSettingsMenu;
122 DWORD dwLogoff;
123 BOOL bWantLogoff;
124 UINT uLastItemsCount = 5; /* 5 menu items below the last separator */
125 WCHAR szUser[128];
126
127 TRACE("ITrayPriv::AppendMenu\n");
128
129 hMenu = LoadPopupMenu(hExplorerInstance, MAKEINTRESOURCEW(IDM_STARTMENU));
130 *phMenu = hMenu;
131 if (hMenu == NULL)
132 return E_FAIL;
133
134 /* Remove menu items that don't apply */
135
136 /* Favorites */
137 if (SHRestricted(REST_NOFAVORITESMENU) ||
138 !GetAdvancedBool(L"StartMenuFavorites", FALSE))
139 {
140 DeleteMenu(hMenu, IDM_FAVORITES, MF_BYCOMMAND);
141 }
142
143 /* Documents */
144 if (SHRestricted(REST_NORECENTDOCSMENU) ||
145 !GetAdvancedBool(L"Start_ShowRecentDocs", TRUE))
146 {
147 DeleteMenu(hMenu, IDM_DOCUMENTS, MF_BYCOMMAND);
148 }
149
150 /* Settings */
151 hSettingsMenu = FindSubMenu(hMenu, IDM_SETTINGS, FALSE);
152
153 /* Control Panel */
154 if (SHRestricted(REST_NOSETFOLDERS) ||
155 SHRestricted(REST_NOCONTROLPANEL) ||
156 !GetAdvancedBool(L"Start_ShowControlPanel", TRUE))
157 {
158 DeleteMenu(hSettingsMenu, IDM_CONTROLPANEL, MF_BYCOMMAND);
159
160 /* Delete the separator below it */
161 DeleteMenu(hSettingsMenu, 0, MF_BYPOSITION);
162 }
163
164 /* Network Connections */
165 if (SHRestricted(REST_NOSETFOLDERS) ||
166 SHRestricted(REST_NONETWORKCONNECTIONS) ||
167 !GetAdvancedBool(L"Start_ShowNetConn", TRUE))
168 {
169 DeleteMenu(hSettingsMenu, IDM_NETWORKCONNECTIONS, MF_BYCOMMAND);
170 }
171
172 /* Printers and Faxes */
173 if (SHRestricted(REST_NOSETFOLDERS) ||
174 !GetAdvancedBool(L"Start_ShowPrinters", TRUE))
175 {
176 DeleteMenu(hSettingsMenu, IDM_PRINTERSANDFAXES, MF_BYCOMMAND);
177 }
178
179 /* Security */
180 if (SHRestricted(REST_NOSETFOLDERS) ||
181 GetSystemMetrics(SM_REMOTECONTROL) == 0 ||
182 SHRestricted(REST_NOSECURITY))
183 {
184 DeleteMenu(hSettingsMenu, IDM_SECURITY, MF_BYCOMMAND);
185 }
186
187 /* Delete Settings menu if it was empty */
188 if (GetMenuItemCount(hSettingsMenu) == 0)
189 {
190 DeleteMenu(hMenu, IDM_SETTINGS, MF_BYCOMMAND);
191 }
192
193 /* Search */
194 if (SHRestricted(REST_NOFIND) ||
195 !GetAdvancedBool(L"Start_ShowSearch", TRUE))
196 {
197 DeleteMenu(hMenu, IDM_SEARCH, MF_BYCOMMAND);
198 }
199
200 /* Help */
201 if (SHRestricted(REST_NOSMHELP) ||
202 !GetAdvancedBool(L"Start_ShowHelp", TRUE))
203 {
204 DeleteMenu(hMenu, IDM_HELPANDSUPPORT, MF_BYCOMMAND);
205 }
206
207 /* Run */
208 if (SHRestricted(REST_NORUN) ||
209 !GetAdvancedBool(L"StartMenuRun", TRUE))
210 {
211 DeleteMenu(hMenu, IDM_RUN, MF_BYCOMMAND);
212 }
213
214 /* Synchronize */
215 if (!ShowSynchronizeMenuItem())
216 {
217 DeleteMenu(hMenu, IDM_SYNCHRONIZE, MF_BYCOMMAND);
218 uLastItemsCount--;
219 }
220
221 /* Log off */
222 dwLogoff = SHRestricted(REST_STARTMENULOGOFF);
223 bWantLogoff = (dwLogoff == 2 ||
224 SHRestricted(REST_FORCESTARTMENULOGOFF) ||
225 GetAdvancedBool(L"StartMenuLogoff", FALSE));
226 if (dwLogoff != 1 && bWantLogoff)
227 {
228 /* FIXME: We need a more sophisticated way to determine whether to show
229 or hide it, it might be hidden in too many cases!!! */
230
231 /* Update Log Off menu item */
232 if (!GetCurrentLoggedOnUserName(szUser, _countof(szUser)))
233 {
234 szUser[0] = _T('\0');
235 }
236
237 if (!FormatMenuString(hMenu,
238 IDM_LOGOFF,
239 MF_BYCOMMAND,
240 szUser))
241 {
242 /* We couldn't update the menu item, delete it... */
243 DeleteMenu(hMenu, IDM_LOGOFF, MF_BYCOMMAND);
244 }
245 }
246 else
247 {
248 DeleteMenu(hMenu, IDM_LOGOFF, MF_BYCOMMAND);
249 uLastItemsCount--;
250 }
251
252 /* Disconnect */
253 if (SHRestricted(REST_NODISCONNECT) ||
254 GetSystemMetrics(SM_REMOTECONTROL) == 0)
255 {
256 DeleteMenu(hMenu, IDM_DISCONNECT, MF_BYCOMMAND);
257 uLastItemsCount--;
258 }
259
260 /* Undock computer */
261 if (!ShowUndockMenuItem())
262 {
263 DeleteMenu(hMenu, IDM_UNDOCKCOMPUTER, MF_BYCOMMAND);
264 uLastItemsCount--;
265 }
266
267 /* Shut down */
268 if (SHRestricted(REST_NOCLOSE))
269 {
270 DeleteMenu(hMenu, IDM_SHUTDOWN, MF_BYCOMMAND);
271 uLastItemsCount--;
272 }
273
274 if (uLastItemsCount == 0)
275 {
276 /* Remove the separator at the end of the menu */
277 DeleteMenu(hMenu, IDM_LASTSTARTMENU_SEPARATOR, MF_BYCOMMAND);
278 }
279
280 return S_OK;
281 }
282
283 /*******************************************************************/
284
285 STDMETHODIMP
286 QueryStatus(
287 IN const GUID *pguidCmdGroup OPTIONAL,
288 IN ULONG cCmds,
289 IN OUT OLECMD *prgCmds,
290 IN OUT OLECMDTEXT *pCmdText OPTIONAL) override
291 {
292 return E_NOTIMPL;
293 }
294
295 STDMETHODIMP
296 Exec(
297 IN const GUID *pguidCmdGroup OPTIONAL,
298 IN DWORD nCmdID,
299 IN DWORD nCmdExecOpt,
300 IN VARIANTARG *pvaIn OPTIONAL,
301 IN VARIANTARG *pvaOut OPTIONAL) override
302 {
303 return E_NOTIMPL;
304 }
305
306 /*******************************************************************/
307
308 STDMETHODIMP
309 SetClient(IUnknown *punkClient) override
310 {
311 return E_NOTIMPL;
312 }
313
314 STDMETHODIMP
315 GetClient(IUnknown ** ppunkClient) override
316 {
317 return E_NOTIMPL;
318 }
319
320 STDMETHODIMP
321 OnPosRectChangeDB(RECT *prc) override
322 {
323 return E_NOTIMPL;
324 }
325
326 // *** IMenuPopup methods ***
327
328 STDMETHODIMP
329 Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags) override
330 {
331 return E_NOTIMPL;
332 }
333
334 STDMETHODIMP
335 OnSelect(DWORD dwSelectType) override
336 {
337 return E_NOTIMPL;
338 }
339
340 STDMETHODIMP
341 SetSubMenu(IMenuPopup *pmp, BOOL fSet) override
342 {
343 if (!fSet)
344 {
345 return Tray_OnStartMenuDismissed(m_Tray);
346 }
347
348 return S_OK;
349 }
350
351 /*******************************************************************/
352
353 HRESULT Initialize(IN ITrayWindow *tray)
354 {
355 m_Tray = tray;
356 return S_OK;
357 }
358
359 DECLARE_NOT_AGGREGATABLE(CStartMenuSite)
360
361 DECLARE_PROTECT_FINAL_CONSTRUCT()
362 BEGIN_COM_MAP(CStartMenuSite)
363 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
364 COM_INTERFACE_ENTRY_IID(IID_ITrayPriv, ITrayPriv)
365 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
366 COM_INTERFACE_ENTRY_IID(IID_IMenuPopup, IMenuPopup)
367 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
368 END_COM_MAP()
369};
370
371HRESULT CStartMenuSite_CreateInstance(IN OUT ITrayWindow *Tray, const IID & riid, PVOID * ppv)
372{
373 return ShellObjectCreatorInit<CStartMenuSite>(Tray, riid, ppv);
374}