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