/* * PROJECT: ReactOS shell extensions * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension) * COPYRIGHT: Copyright Shriraj Sawant a.k.a SR13 */ #define WIN32_NO_STATUS #define _INC_WINDOWS #define COM_NO_WINDOWS_H #define COBJMACROS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "CQuickLaunchBand.h" extern "C" HRESULT WINAPI RSHELL_CISFBand_CreateInstance(REFIID riid, void** ppv); // {260CB95D-4544-44F6-A079-575BAA60B72F} const GUID CLSID_QuickLaunchBand = { 0x260cb95d, 0x4544, 0x44f6, { 0xa0, 0x79, 0x57, 0x5b, 0xaa, 0x60, 0xb7, 0x2f } }; // Componenet Category Registration HRESULT RegisterComCat() { CComPtr pcr; HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICatRegister, &pcr)); if (SUCCEEDED(hr)) { CATID catid = CATID_DeskBand; hr = pcr->RegisterClassImplCategories(CLSID_QuickLaunchBand, 1, &catid); } return hr; } HRESULT UnregisterComCat() { CComPtr pcr; HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICatRegister, &pcr)); if (SUCCEEDED(hr)) { CATID catid = CATID_DeskBand; hr = pcr->UnRegisterClassImplCategories(CLSID_QuickLaunchBand, 1, &catid); } return hr; } // Pidl Browser /*++ * @name PidlBrowse * * Opens a folder browser dialog, * allowing the user to select a folder for enumeration. * * @param hwnd * A handle to browser dialog window. * @param nCSIDL * A CSIDL representing the root from which the browse folder dialog shows the files and folders. * * @return The PIDL to selected folder. * *--*/ LPITEMIDLIST PidlBrowse(HWND hwnd, int nCSIDL) { CComHeapPtr pidlRoot; WCHAR path[MAX_PATH]; if (nCSIDL) { SHGetSpecialFolderLocation(hwnd, nCSIDL, &pidlRoot); } BROWSEINFO bi = { hwnd, pidlRoot, path, L"Choose a folder", 0, NULL, 0, 0 }; LPITEMIDLIST pidlSelected = SHBrowseForFolder(&bi); return pidlSelected; } // CQuickLaunchBand CQuickLaunchBand::CQuickLaunchBand() {} CQuickLaunchBand::~CQuickLaunchBand() {} /*****************************************************************************/ // ATL Construct /*++ * @name FinalConstruct * * Creates an instance of CISFBand, and initializes its Shell Folder Band for enumeration. * * @return The error code. * *--*/ HRESULT CQuickLaunchBand::FinalConstruct() { HRESULT hr = RSHELL_CISFBand_CreateInstance(IID_PPV_ARG(IUnknown, &m_punkISFB)); if (FAILED_UNEXPECTEDLY(hr)) return hr; CComPtr pISFB; hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IShellFolderBand, &pISFB)); if (FAILED_UNEXPECTEDLY(hr)) return hr; CComPtr pISF; hr = SHGetDesktopFolder(&pISF); if (FAILED_UNEXPECTEDLY(hr)) return hr; CComHeapPtr pidl(PidlBrowse(m_hWndBro, CSIDL_DESKTOP)); if (pidl == NULL) return E_FAIL; pISFB->InitializeSFB(pISF, pidl); return hr; } // IObjectWithSite STDMETHODIMP CQuickLaunchBand::SetSite(IUnknown *pUnkSite) { // Internal CISFBand Calls CComPtr pIOWS; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pIOWS)); if (FAILED(hr)) return hr; return pIOWS->SetSite(pUnkSite); } STDMETHODIMP CQuickLaunchBand::GetSite(IN REFIID riid, OUT VOID **ppvSite) { CComPtr pIOWS; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pIOWS)); if (FAILED(hr)) return hr; return pIOWS->GetSite(riid, ppvSite); } /*****************************************************************************/ // IDeskBand STDMETHODIMP CQuickLaunchBand::GetWindow(OUT HWND *phwnd) { // Internal CISFBand Calls CComPtr pIDB; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); if (FAILED(hr)) return hr; return pIDB->GetWindow(phwnd); } STDMETHODIMP CQuickLaunchBand::ContextSensitiveHelp(IN BOOL fEnterMode) { // Internal CISFBand Calls CComPtr pIDB; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); if (FAILED(hr)) return hr; return pIDB->ContextSensitiveHelp(fEnterMode); } STDMETHODIMP CQuickLaunchBand::ShowDW(IN BOOL bShow) { // Internal CISFBand Calls CComPtr pIDB; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); if (FAILED(hr)) return hr; return pIDB->ShowDW(bShow); } STDMETHODIMP CQuickLaunchBand::CloseDW(IN DWORD dwReserved) { // Internal CISFBand Calls CComPtr pIDB; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); if (FAILED(hr)) return hr; return pIDB->CloseDW(dwReserved); } STDMETHODIMP CQuickLaunchBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved) { // Internal CISFBand Calls CComPtr pIDB; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); if (FAILED(hr)) return hr; return pIDB->ResizeBorderDW(prcBorder, punkToolbarSite, fReserved); } STDMETHODIMP CQuickLaunchBand::GetBandInfo(IN DWORD dwBandID, IN DWORD dwViewMode, IN OUT DESKBANDINFO *pdbi) { // Internal CISFBand Calls CComPtr pIDB; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); if (FAILED(hr)) return hr; return pIDB->GetBandInfo(dwBandID, dwViewMode, pdbi); } /*****************************************************************************/ // IPersistStream STDMETHODIMP CQuickLaunchBand::GetClassID(OUT CLSID *pClassID) { // Internal CISFBand Calls CComPtr pIPS; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); if (FAILED(hr)) return hr; return pIPS->GetClassID(pClassID); } STDMETHODIMP CQuickLaunchBand::IsDirty() { // Internal CISFBand Calls CComPtr pIPS; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); if (FAILED(hr)) return hr; return pIPS->IsDirty(); } STDMETHODIMP CQuickLaunchBand::Load(IN IStream *pStm) { CComPtr pIPS; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); if (FAILED(hr)) return hr; return pIPS->Load(pStm); } STDMETHODIMP CQuickLaunchBand::Save(IN IStream *pStm, IN BOOL fClearDirty) { // Internal CISFBand Calls CComPtr pIPS; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); if (FAILED(hr)) return hr; return pIPS->Save(pStm, fClearDirty); } STDMETHODIMP CQuickLaunchBand::GetSizeMax(OUT ULARGE_INTEGER *pcbSize) { CComPtr pIPS; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); if (FAILED(hr)) return hr; return pIPS->GetSizeMax(pcbSize); } /*****************************************************************************/ // IWinEventHandler STDMETHODIMP CQuickLaunchBand::ContainsWindow(IN HWND hWnd) { return E_NOTIMPL; } STDMETHODIMP CQuickLaunchBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) { // Internal CISFBand Calls CComPtr pWEH; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IWinEventHandler, &pWEH)); if (FAILED(hr)) return hr; return pWEH->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult); } STDMETHODIMP CQuickLaunchBand::IsWindowOwner(HWND hWnd) { // Internal CISFBand Calls CComPtr pWEH; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IWinEventHandler, &pWEH)); if (FAILED(hr)) return hr; return pWEH->IsWindowOwner(hWnd); } /*****************************************************************************/ // *** IOleCommandTarget methods *** STDMETHODIMP CQuickLaunchBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText) { // Internal CISFBand Calls CComPtr pOCT; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pOCT)); if (FAILED(hr)) return hr; return pOCT->QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText); } STDMETHODIMP CQuickLaunchBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) { // Internal CISFBand Calls CComPtr pOCT; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pOCT)); if (FAILED(hr)) return hr; return pOCT->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); } /*****************************************************************************/ // *** IContextMenu *** STDMETHODIMP CQuickLaunchBand::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax) { // Internal CISFBand Calls CComPtr pICM; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IContextMenu, &pICM)); if (FAILED(hr)) return hr; return pICM->GetCommandString(idCmd, uFlags, pwReserved, pszName, cchMax); } STDMETHODIMP CQuickLaunchBand::InvokeCommand(LPCMINVOKECOMMANDINFO pici) { // Internal CISFBand Calls CComPtr pICM; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IContextMenu, &pICM)); if (FAILED(hr)) return hr; return pICM->InvokeCommand(pici); } STDMETHODIMP CQuickLaunchBand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { // Internal CISFBand Calls CComPtr pICM; HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IContextMenu, &pICM)); if (FAILED(hr)) return hr; return pICM->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags); }