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         /* FIXME: Enable after implementing */
212         /* if (SHRestricted(REST_NOFIND)) */
213     {
214         DeleteMenu(hMenu,
215                    IDM_SEARCH,
216                    MF_BYCOMMAND);
217     }
218 
219         /* FIXME: Help */
220 
221         /* Run */
222         if (SHRestricted(REST_NORUN))
223         {
224             DeleteMenu(hMenu,
225                        IDM_RUN,
226                        MF_BYCOMMAND);
227         }
228 
229         /* Synchronize */
230         if (!ShowSynchronizeMenuItem())
231         {
232             DeleteMenu(hMenu,
233                        IDM_SYNCHRONIZE,
234                        MF_BYCOMMAND);
235             uLastItemsCount--;
236         }
237 
238         /* Log off */
239         if (dwLogoff != 1 && bWantLogoff)
240         {
241             /* FIXME: We need a more sophisticated way to determine whether to show
242                       or hide it, it might be hidden in too many cases!!! */
243 
244             /* Update Log Off menu item */
245             if (!GetCurrentLoggedOnUserName(szUser, _countof(szUser)))
246             {
247                 szUser[0] = _T('\0');
248             }
249 
250             if (!FormatMenuString(hMenu,
251                 IDM_LOGOFF,
252                 MF_BYCOMMAND,
253                 szUser))
254             {
255                 /* We couldn't update the menu item, delete it... */
256                 DeleteMenu(hMenu,
257                            IDM_LOGOFF,
258                            MF_BYCOMMAND);
259             }
260         }
261         else
262         {
263             DeleteMenu(hMenu,
264                        IDM_LOGOFF,
265                        MF_BYCOMMAND);
266             uLastItemsCount--;
267         }
268 
269 
270         /* Disconnect */
271         if (GetSystemMetrics(SM_REMOTECONTROL) == 0)
272         {
273             DeleteMenu(hMenu,
274                        IDM_DISCONNECT,
275                        MF_BYCOMMAND);
276             uLastItemsCount--;
277         }
278 
279         /* Undock computer */
280         if (!ShowUndockMenuItem())
281         {
282             DeleteMenu(hMenu,
283                        IDM_UNDOCKCOMPUTER,
284                        MF_BYCOMMAND);
285             uLastItemsCount--;
286         }
287 
288         /* Shut down */
289         if (SHRestricted(REST_NOCLOSE))
290         {
291             DeleteMenu(hMenu,
292                        IDM_SHUTDOWN,
293                        MF_BYCOMMAND);
294             uLastItemsCount--;
295         }
296 
297         if (uLastItemsCount == 0)
298         {
299             /* Remove the separator at the end of the menu */
300             DeleteMenu(hMenu,
301                        IDM_LASTSTARTMENU_SEPARATOR,
302                        MF_BYCOMMAND);
303         }
304 
305         return S_OK;
306     }
307 
308     /*******************************************************************/
309 
310     virtual HRESULT STDMETHODCALLTYPE QueryStatus(
311         IN const GUID *pguidCmdGroup  OPTIONAL,
312         IN ULONG cCmds,
313         IN OUT OLECMD *prgCmds,
314         IN OUT OLECMDTEXT *pCmdText  OPTIONAL)
315     {
316         return E_NOTIMPL;
317     }
318 
319     virtual HRESULT STDMETHODCALLTYPE Exec(
320         IN const GUID *pguidCmdGroup  OPTIONAL,
321         IN DWORD nCmdID,
322         IN DWORD nCmdExecOpt,
323         IN VARIANTARG *pvaIn  OPTIONAL,
324         IN VARIANTARG *pvaOut  OPTIONAL)
325     {
326         return E_NOTIMPL;
327     }
328 
329     /*******************************************************************/
330 
331     virtual HRESULT STDMETHODCALLTYPE SetClient(IUnknown *punkClient)
332     {
333         return E_NOTIMPL;
334     }
335 
336     virtual HRESULT STDMETHODCALLTYPE GetClient(IUnknown ** ppunkClient)
337     {
338         return E_NOTIMPL;
339     }
340 
341     virtual HRESULT STDMETHODCALLTYPE OnPosRectChangeDB(RECT *prc)
342     {
343         return E_NOTIMPL;
344     }
345 
346     virtual HRESULT STDMETHODCALLTYPE Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
347     {
348         return E_NOTIMPL;
349     }
350 
351     virtual HRESULT STDMETHODCALLTYPE OnSelect(DWORD dwSelectType)
352     {
353         return E_NOTIMPL;
354     }
355 
356     virtual HRESULT STDMETHODCALLTYPE SetSubMenu(IMenuPopup *pmp, BOOL fSet)
357     {
358         if (!fSet)
359         {
360             return Tray_OnStartMenuDismissed(m_Tray);
361         }
362 
363         return S_OK;
364     }
365 
366     /*******************************************************************/
367 
368     HRESULT Initialize(IN ITrayWindow *tray)
369     {
370         m_Tray = tray;
371         return S_OK;
372     }
373 
374     DECLARE_NOT_AGGREGATABLE(CStartMenuSite)
375 
376     DECLARE_PROTECT_FINAL_CONSTRUCT()
377     BEGIN_COM_MAP(CStartMenuSite)
378         COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
379         COM_INTERFACE_ENTRY_IID(IID_ITrayPriv, ITrayPriv)
380         COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
381         COM_INTERFACE_ENTRY_IID(IID_IMenuPopup, IMenuPopup)
382         COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
383     END_COM_MAP()
384 };
385 
386 HRESULT CStartMenuSite_CreateInstance(IN OUT ITrayWindow *Tray, const IID & riid, PVOID * ppv)
387 {
388     return ShellObjectCreatorInit<CStartMenuSite>(Tray, riid, ppv);
389 }
390