Reactos
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}