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 UINT m_idCmdCmLast; 36 37 HWND m_Owner; 38 LPITEMIDLIST m_FolderPidl; 39 40 HRESULT CreateContextMenuFromShellFolderPidl(HMENU hPopup) 41 { 42 HRESULT hRet; 43 44 hRet = m_Folder->GetUIObjectOf(m_Owner, 1, (LPCITEMIDLIST *) &m_FolderPidl, IID_NULL_PPV_ARG(IContextMenu, &m_Inner)); 45 if (SUCCEEDED(hRet)) 46 { 47 if (hPopup != NULL) 48 { 49 hRet = m_Inner->QueryContextMenu( 50 hPopup, 51 0, 52 ID_SHELL_CMD_FIRST, 53 ID_SHELL_CMD_LAST, 54 CMF_VERBSONLY); 55 56 if (SUCCEEDED(hRet)) 57 { 58 return hRet; 59 } 60 61 DestroyMenu(hPopup); 62 } 63 } 64 65 return E_FAIL; 66 } 67 68 VOID AddStartContextMenuItems(IN HMENU hPopup) 69 { 70 WCHAR szBuf[MAX_PATH]; 71 HRESULT hRet; 72 73 /* Add the "Open All Users" menu item */ 74 if (LoadStringW(hExplorerInstance, 75 IDS_PROPERTIES, 76 szBuf, 77 _countof(szBuf))) 78 { 79 AppendMenu(hPopup, 80 MF_STRING, 81 ID_SHELL_CMD_PROPERTIES, 82 szBuf); 83 } 84 85 if (!SHRestricted(REST_NOCOMMONGROUPS)) 86 { 87 /* Check if we should add menu items for the common start menu */ 88 hRet = SHGetFolderPath(m_Owner, 89 CSIDL_COMMON_STARTMENU, 90 NULL, 91 SHGFP_TYPE_CURRENT, 92 szBuf); 93 if (SUCCEEDED(hRet) && hRet != S_FALSE) 94 { 95 /* The directory exists, but only show the items if the 96 user can actually make any changes to the common start 97 menu. This is most likely only the case if the user 98 has administrative rights! */ 99 if (IsUserAnAdmin()) 100 { 101 AppendMenu(hPopup, 102 MF_SEPARATOR, 103 0, 104 NULL); 105 106 /* Add the "Open All Users" menu item */ 107 if (LoadStringW(hExplorerInstance, 108 IDS_OPEN_ALL_USERS, 109 szBuf, 110 _countof(szBuf))) 111 { 112 AppendMenu(hPopup, 113 MF_STRING, 114 ID_SHELL_CMD_OPEN_ALL_USERS, 115 szBuf); 116 } 117 118 /* Add the "Explore All Users" menu item */ 119 if (LoadStringW(hExplorerInstance, 120 IDS_EXPLORE_ALL_USERS, 121 szBuf, 122 _countof(szBuf))) 123 { 124 AppendMenu(hPopup, 125 MF_STRING, 126 ID_SHELL_CMD_EXPLORE_ALL_USERS, 127 szBuf); 128 } 129 } 130 } 131 } 132 } 133 134 public: 135 HRESULT Initialize(ITrayWindow * pTrayWnd, IN HWND hWndOwner) 136 { 137 m_TrayWnd = pTrayWnd; 138 m_Owner = hWndOwner; 139 return S_OK; 140 } 141 142 virtual HRESULT STDMETHODCALLTYPE 143 QueryContextMenu(HMENU hPopup, 144 UINT indexMenu, 145 UINT idCmdFirst, 146 UINT idCmdLast, 147 UINT uFlags) 148 { 149 LPITEMIDLIST pidlStart; 150 CComPtr<IShellFolder> psfDesktop; 151 HRESULT hRet; 152 153 psfDesktop = NULL; 154 m_Inner = NULL; 155 156 pidlStart = SHCloneSpecialIDList(m_Owner, CSIDL_STARTMENU, TRUE); 157 158 if (pidlStart != NULL) 159 { 160 m_FolderPidl = ILClone(ILFindLastID(pidlStart)); 161 ILRemoveLastID(pidlStart); 162 163 if (m_FolderPidl != NULL) 164 { 165 hRet = SHGetDesktopFolder(&psfDesktop); 166 if (SUCCEEDED(hRet)) 167 { 168 hRet = psfDesktop->BindToObject(pidlStart, NULL, IID_PPV_ARG(IShellFolder, &m_Folder)); 169 if (SUCCEEDED(hRet)) 170 { 171 hRet = CreateContextMenuFromShellFolderPidl(hPopup); 172 m_idCmdCmLast = (SUCCEEDED(hRet)) ? HRESULT_CODE(hRet) : ID_SHELL_CMD_LAST; 173 AddStartContextMenuItems(hPopup); 174 } 175 } 176 } 177 178 ILFree(pidlStart); 179 } 180 181 return S_OK; 182 } 183 184 virtual HRESULT STDMETHODCALLTYPE 185 InvokeCommand(LPCMINVOKECOMMANDINFO lpici) 186 { 187 UINT uiCmdId = PtrToUlong(lpici->lpVerb); 188 if (uiCmdId != 0) 189 { 190 if ((uiCmdId >= ID_SHELL_CMD_FIRST) && (uiCmdId < m_idCmdCmLast)) 191 { 192 CMINVOKECOMMANDINFO cmici = { 0 }; 193 CHAR szDir[MAX_PATH]; 194 195 /* Setup and invoke the shell command */ 196 cmici.cbSize = sizeof(cmici); 197 cmici.hwnd = m_Owner; 198 cmici.lpVerb = MAKEINTRESOURCEA(uiCmdId - ID_SHELL_CMD_FIRST); 199 cmici.nShow = SW_NORMAL; 200 201 /* FIXME: Support Unicode!!! */ 202 if (SHGetPathFromIDListA(m_FolderPidl, szDir)) 203 { 204 cmici.lpDirectory = szDir; 205 } 206 207 m_Inner->InvokeCommand(&cmici); 208 } 209 else 210 { 211 m_TrayWnd->ExecContextMenuCmd(uiCmdId); 212 } 213 } 214 return S_OK; 215 } 216 217 virtual HRESULT STDMETHODCALLTYPE 218 GetCommandString(UINT_PTR idCmd, 219 UINT uType, 220 UINT *pwReserved, 221 LPSTR pszName, 222 UINT cchMax) 223 { 224 return E_NOTIMPL; 225 } 226 227 CStartMenuBtnCtxMenu() 228 { 229 m_idCmdCmLast = ID_SHELL_CMD_LAST; 230 } 231 232 virtual ~CStartMenuBtnCtxMenu() 233 { 234 if (m_FolderPidl) 235 ILFree(m_FolderPidl); 236 } 237 238 BEGIN_COM_MAP(CStartMenuBtnCtxMenu) 239 COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) 240 END_COM_MAP() 241 }; 242 243 HRESULT CStartMenuBtnCtxMenu_CreateInstance(ITrayWindow * m_TrayWnd, IN HWND m_Owner, IContextMenu ** ppCtxMenu) 244 { 245 return ShellObjectCreatorInit<CStartMenuBtnCtxMenu>(m_TrayWnd, m_Owner, IID_PPV_ARG(IContextMenu, ppCtxMenu)); 246 } 247