Reactos
at master 368 lines 10 kB view raw
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 34extern "C" 35HRESULT WINAPI RSHELL_CISFBand_CreateInstance(REFIID riid, void** ppv); 36 37// {260CB95D-4544-44F6-A079-575BAA60B72F} 38const GUID CLSID_QuickLaunchBand = { 0x260cb95d, 0x4544, 0x44f6, { 0xa0, 0x79, 0x57, 0x5b, 0xaa, 0x60, 0xb7, 0x2f } }; 39 40// Componenet Category Registration 41HRESULT 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 53HRESULT 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*--*/ 80LPITEMIDLIST 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 99CQuickLaunchBand::CQuickLaunchBand() {} 100 101CQuickLaunchBand::~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*--*/ 113HRESULT 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 138STDMETHODIMP 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 149STDMETHODIMP 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 161STDMETHODIMP 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 172STDMETHODIMP 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 183STDMETHODIMP 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 194STDMETHODIMP 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 205STDMETHODIMP 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 216STDMETHODIMP 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 229STDMETHODIMP 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 240STDMETHODIMP 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 251STDMETHODIMP 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 261STDMETHODIMP 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 272STDMETHODIMP 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 284STDMETHODIMP CQuickLaunchBand::ContainsWindow(IN HWND hWnd) 285{ 286 return E_NOTIMPL; 287} 288 289STDMETHODIMP 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 300STDMETHODIMP 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 *** 313STDMETHODIMP 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 324STDMETHODIMP 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 *** 337STDMETHODIMP 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 348STDMETHODIMP 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 359STDMETHODIMP 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}