1 /* 2 * PROJECT: ReactOS shell extensions 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension) 5 * COPYRIGHT: Copyright Shriraj Sawant a.k.a SR13 <sr.official@hotmail.com> 6 */ 7 8 #define WIN32_NO_STATUS 9 #define _INC_WINDOWS 10 #define COM_NO_WINDOWS_H 11 12 #define COBJMACROS 13 14 #include <windef.h> 15 #include <winbase.h> 16 #include <winreg.h> 17 #include <wingdi.h> 18 #include <winnls.h> 19 #include <wincon.h> 20 #include <shellapi.h> 21 #include <shlobj.h> 22 #include <shlobj_undoc.h> 23 #include <shlwapi.h> 24 #include <shlguid_undoc.h> 25 #include <atlbase.h> 26 #include <atlcom.h> 27 #include <atlwin.h> 28 29 #include <undocshell.h> 30 #include <shellutils.h> 31 32 #include "CQuickLaunchBand.h" 33 34 extern "C" 35 HRESULT WINAPI RSHELL_CISFBand_CreateInstance(REFIID riid, void** ppv); 36 37 // {260CB95D-4544-44F6-A079-575BAA60B72F} 38 const GUID CLSID_QuickLaunchBand = { 0x260cb95d, 0x4544, 0x44f6, { 0xa0, 0x79, 0x57, 0x5b, 0xaa, 0x60, 0xb7, 0x2f } }; 39 40 // Componenet Category Registration 41 HRESULT RegisterComCat() 42 { 43 CComPtr<ICatRegister> pcr; 44 HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICatRegister, &pcr)); 45 if (SUCCEEDED(hr)) 46 { 47 CATID catid = CATID_DeskBand; 48 hr = pcr->RegisterClassImplCategories(CLSID_QuickLaunchBand, 1, &catid); 49 } 50 return hr; 51 } 52 53 HRESULT UnregisterComCat() 54 { 55 CComPtr<ICatRegister> pcr; 56 HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICatRegister, &pcr)); 57 if (SUCCEEDED(hr)) 58 { 59 CATID catid = CATID_DeskBand; 60 hr = pcr->UnRegisterClassImplCategories(CLSID_QuickLaunchBand, 1, &catid); 61 } 62 return hr; 63 } 64 65 // Pidl Browser 66 /*++ 67 * @name PidlBrowse 68 * 69 * Opens a folder browser dialog, 70 * allowing the user to select a folder for enumeration. 71 * 72 * @param hwnd 73 * A handle to browser dialog window. 74 * @param nCSIDL 75 * A CSIDL representing the root from which the browse folder dialog shows the files and folders. 76 * 77 * @return The PIDL to selected folder. 78 * 79 *--*/ 80 LPITEMIDLIST PidlBrowse(HWND hwnd, int nCSIDL) 81 { 82 CComHeapPtr<ITEMIDLIST> pidlRoot; 83 84 WCHAR path[MAX_PATH]; 85 86 if (nCSIDL) 87 { 88 SHGetSpecialFolderLocation(hwnd, nCSIDL, &pidlRoot); 89 } 90 91 BROWSEINFO bi = { hwnd, pidlRoot, path, L"Choose a folder", 0, NULL, 0, 0 }; 92 LPITEMIDLIST pidlSelected = SHBrowseForFolder(&bi); 93 94 return pidlSelected; 95 } 96 97 // CQuickLaunchBand 98 99 CQuickLaunchBand::CQuickLaunchBand() {} 100 101 CQuickLaunchBand::~CQuickLaunchBand() {} 102 103 /*****************************************************************************/ 104 // ATL Construct 105 /*++ 106 * @name FinalConstruct 107 * 108 * Creates an instance of CISFBand, and initializes its Shell Folder Band for enumeration. 109 * 110 * @return The error code. 111 * 112 *--*/ 113 HRESULT CQuickLaunchBand::FinalConstruct() 114 { 115 HRESULT hr = RSHELL_CISFBand_CreateInstance(IID_PPV_ARG(IUnknown, &m_punkISFB)); 116 if (FAILED_UNEXPECTEDLY(hr)) 117 return hr; 118 119 CComPtr<IShellFolderBand> pISFB; 120 hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IShellFolderBand, &pISFB)); 121 if (FAILED_UNEXPECTEDLY(hr)) 122 return hr; 123 124 CComPtr<IShellFolder> pISF; 125 hr = SHGetDesktopFolder(&pISF); 126 if (FAILED_UNEXPECTEDLY(hr)) 127 return hr; 128 129 CComHeapPtr<ITEMIDLIST> pidl(PidlBrowse(m_hWndBro, CSIDL_DESKTOP)); 130 if (pidl == NULL) 131 return E_FAIL; 132 pISFB->InitializeSFB(pISF, pidl); 133 134 return hr; 135 } 136 137 // IObjectWithSite 138 STDMETHODIMP CQuickLaunchBand::SetSite(IUnknown *pUnkSite) 139 { 140 // Internal CISFBand Calls 141 CComPtr<IObjectWithSite> pIOWS; 142 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pIOWS)); 143 if (FAILED(hr)) 144 return hr; 145 146 return pIOWS->SetSite(pUnkSite); 147 } 148 149 STDMETHODIMP CQuickLaunchBand::GetSite(IN REFIID riid, OUT VOID **ppvSite) 150 { 151 CComPtr<IObjectWithSite> pIOWS; 152 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pIOWS)); 153 if (FAILED(hr)) 154 return hr; 155 156 return pIOWS->GetSite(riid, ppvSite); 157 } 158 159 /*****************************************************************************/ 160 // IDeskBand 161 STDMETHODIMP CQuickLaunchBand::GetWindow(OUT HWND *phwnd) 162 { 163 // Internal CISFBand Calls 164 CComPtr<IDeskBand> pIDB; 165 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); 166 if (FAILED(hr)) 167 return hr; 168 169 return pIDB->GetWindow(phwnd); 170 } 171 172 STDMETHODIMP CQuickLaunchBand::ContextSensitiveHelp(IN BOOL fEnterMode) 173 { 174 // Internal CISFBand Calls 175 CComPtr<IDeskBand> pIDB; 176 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); 177 if (FAILED(hr)) 178 return hr; 179 180 return pIDB->ContextSensitiveHelp(fEnterMode); 181 } 182 183 STDMETHODIMP CQuickLaunchBand::ShowDW(IN BOOL bShow) 184 { 185 // Internal CISFBand Calls 186 CComPtr<IDeskBand> pIDB; 187 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); 188 if (FAILED(hr)) 189 return hr; 190 191 return pIDB->ShowDW(bShow); 192 } 193 194 STDMETHODIMP CQuickLaunchBand::CloseDW(IN DWORD dwReserved) 195 { 196 // Internal CISFBand Calls 197 CComPtr<IDeskBand> pIDB; 198 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); 199 if (FAILED(hr)) 200 return hr; 201 202 return pIDB->CloseDW(dwReserved); 203 } 204 205 STDMETHODIMP CQuickLaunchBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved) 206 { 207 // Internal CISFBand Calls 208 CComPtr<IDeskBand> pIDB; 209 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); 210 if (FAILED(hr)) 211 return hr; 212 213 return pIDB->ResizeBorderDW(prcBorder, punkToolbarSite, fReserved); 214 } 215 216 STDMETHODIMP CQuickLaunchBand::GetBandInfo(IN DWORD dwBandID, IN DWORD dwViewMode, IN OUT DESKBANDINFO *pdbi) 217 { 218 // Internal CISFBand Calls 219 CComPtr<IDeskBand> pIDB; 220 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); 221 if (FAILED(hr)) 222 return hr; 223 224 return pIDB->GetBandInfo(dwBandID, dwViewMode, pdbi); 225 } 226 227 /*****************************************************************************/ 228 // IPersistStream 229 STDMETHODIMP CQuickLaunchBand::GetClassID(OUT CLSID *pClassID) 230 { 231 // Internal CISFBand Calls 232 CComPtr<IPersistStream> pIPS; 233 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); 234 if (FAILED(hr)) 235 return hr; 236 237 return pIPS->GetClassID(pClassID); 238 } 239 240 STDMETHODIMP CQuickLaunchBand::IsDirty() 241 { 242 // Internal CISFBand Calls 243 CComPtr<IPersistStream> pIPS; 244 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); 245 if (FAILED(hr)) 246 return hr; 247 248 return pIPS->IsDirty(); 249 } 250 251 STDMETHODIMP CQuickLaunchBand::Load(IN IStream *pStm) 252 { 253 CComPtr<IPersistStream> pIPS; 254 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); 255 if (FAILED(hr)) 256 return hr; 257 258 return pIPS->Load(pStm); 259 } 260 261 STDMETHODIMP CQuickLaunchBand::Save(IN IStream *pStm, IN BOOL fClearDirty) 262 { 263 // Internal CISFBand Calls 264 CComPtr<IPersistStream> pIPS; 265 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); 266 if (FAILED(hr)) 267 return hr; 268 269 return pIPS->Save(pStm, fClearDirty); 270 } 271 272 STDMETHODIMP CQuickLaunchBand::GetSizeMax(OUT ULARGE_INTEGER *pcbSize) 273 { 274 CComPtr<IPersistStream> pIPS; 275 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); 276 if (FAILED(hr)) 277 return hr; 278 279 return pIPS->GetSizeMax(pcbSize); 280 } 281 282 /*****************************************************************************/ 283 // IWinEventHandler 284 STDMETHODIMP CQuickLaunchBand::ContainsWindow(IN HWND hWnd) 285 { 286 return E_NOTIMPL; 287 } 288 289 STDMETHODIMP CQuickLaunchBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) 290 { 291 // Internal CISFBand Calls 292 CComPtr<IWinEventHandler> pWEH; 293 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IWinEventHandler, &pWEH)); 294 if (FAILED(hr)) 295 return hr; 296 297 return pWEH->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult); 298 } 299 300 STDMETHODIMP CQuickLaunchBand::IsWindowOwner(HWND hWnd) 301 { 302 // Internal CISFBand Calls 303 CComPtr<IWinEventHandler> pWEH; 304 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IWinEventHandler, &pWEH)); 305 if (FAILED(hr)) 306 return hr; 307 308 return pWEH->IsWindowOwner(hWnd); 309 } 310 311 /*****************************************************************************/ 312 // *** IOleCommandTarget methods *** 313 STDMETHODIMP CQuickLaunchBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText) 314 { 315 // Internal CISFBand Calls 316 CComPtr<IOleCommandTarget> pOCT; 317 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pOCT)); 318 if (FAILED(hr)) 319 return hr; 320 321 return pOCT->QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText); 322 } 323 324 STDMETHODIMP CQuickLaunchBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 325 { 326 // Internal CISFBand Calls 327 CComPtr<IOleCommandTarget> pOCT; 328 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pOCT)); 329 if (FAILED(hr)) 330 return hr; 331 332 return pOCT->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); 333 } 334 335 /*****************************************************************************/ 336 // *** IContextMenu *** 337 STDMETHODIMP CQuickLaunchBand::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax) 338 { 339 // Internal CISFBand Calls 340 CComPtr<IContextMenu> pICM; 341 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IContextMenu, &pICM)); 342 if (FAILED(hr)) 343 return hr; 344 345 return pICM->GetCommandString(idCmd, uFlags, pwReserved, pszName, cchMax); 346 } 347 348 STDMETHODIMP CQuickLaunchBand::InvokeCommand(LPCMINVOKECOMMANDINFO pici) 349 { 350 // Internal CISFBand Calls 351 CComPtr<IContextMenu> pICM; 352 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IContextMenu, &pICM)); 353 if (FAILED(hr)) 354 return hr; 355 356 return pICM->InvokeCommand(pici); 357 } 358 359 STDMETHODIMP CQuickLaunchBand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) 360 { 361 // Internal CISFBand Calls 362 CComPtr<IContextMenu> pICM; 363 HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IContextMenu, &pICM)); 364 if (FAILED(hr)) 365 return hr; 366 367 return pICM->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags); 368 } 369