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