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