xref: /reactos/base/shell/explorer/tbsite.cpp (revision 853b8ebd)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * ReactOS Explorer
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck 
21c2c66affSColin Finck #include "precomp.h"
22c2c66affSColin Finck 
23c2c66affSColin Finck #include <shdeprecated.h>
24c2c66affSColin Finck 
25c2c66affSColin Finck /*****************************************************************************
26c2c66affSColin Finck  ** ITrayBandSite ************************************************************
27c2c66affSColin Finck  *****************************************************************************/
28c2c66affSColin Finck 
29c2c66affSColin Finck // WARNING: Can't use ATL for this class due to our ATL not fully supporting the AGGREGATION functions needed for this class to be an "outer" class
30c2c66affSColin Finck // it works just fine this way.
31c2c66affSColin Finck class CTrayBandSite :
32c2c66affSColin Finck     public ITrayBandSite,
33c2c66affSColin Finck     public IBandSite,
34c2c66affSColin Finck     public IBandSiteStreamCallback
35c2c66affSColin Finck     /* TODO: IWinEventHandler */
36c2c66affSColin Finck {
37c2c66affSColin Finck     volatile LONG m_RefCount;
38c2c66affSColin Finck 
39c2c66affSColin Finck     CComPtr<ITrayWindow> m_Tray;
40c2c66affSColin Finck 
41c2c66affSColin Finck     CComPtr<IUnknown> m_Inner;
42c2c66affSColin Finck     CComPtr<IBandSite> m_BandSite;
43c2c66affSColin Finck     CComPtr<IDeskBand> m_TaskBand;
44c2c66affSColin Finck     CComPtr<IWinEventHandler> m_WindowEventHandler;
45c2c66affSColin Finck     CComPtr<IContextMenu> m_ContextMenu;
46c2c66affSColin Finck 
47c2c66affSColin Finck     HWND m_Rebar;
48c2c66affSColin Finck 
49c2c66affSColin Finck     union
50c2c66affSColin Finck     {
51c2c66affSColin Finck         DWORD dwFlags;
52c2c66affSColin Finck         struct
53c2c66affSColin Finck         {
54c2c66affSColin Finck             DWORD Locked : 1;
55c2c66affSColin Finck         };
56c2c66affSColin Finck     };
57c2c66affSColin Finck 
58c2c66affSColin Finck public:
59*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP_(ULONG)
AddRef()60*853b8ebdSKatayama Hirofumi MZ     AddRef() override
61c2c66affSColin Finck     {
62c2c66affSColin Finck         return InterlockedIncrement(&m_RefCount);
63c2c66affSColin Finck     }
64c2c66affSColin Finck 
65*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP_(ULONG)
Release()66*853b8ebdSKatayama Hirofumi MZ     Release() override
67c2c66affSColin Finck     {
68c2c66affSColin Finck         ULONG Ret = InterlockedDecrement(&m_RefCount);
69c2c66affSColin Finck 
70c2c66affSColin Finck         if (Ret == 0)
71c2c66affSColin Finck             delete this;
72c2c66affSColin Finck 
73c2c66affSColin Finck         return Ret;
74c2c66affSColin Finck     }
75c2c66affSColin Finck 
76*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
QueryInterface(IN REFIID riid,OUT LPVOID * ppvObj)77*853b8ebdSKatayama Hirofumi MZ     QueryInterface(IN REFIID riid, OUT LPVOID *ppvObj) override
78c2c66affSColin Finck     {
79c2c66affSColin Finck         if (ppvObj == NULL)
80c2c66affSColin Finck             return E_POINTER;
81c2c66affSColin Finck 
82c2c66affSColin Finck         if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IBandSiteHelper))
83c2c66affSColin Finck         {
84c2c66affSColin Finck             // return IBandSiteStreamCallback's IUnknown
85c2c66affSColin Finck             *ppvObj = static_cast<IBandSiteStreamCallback*>(this);
86c2c66affSColin Finck         }
87c2c66affSColin Finck         else if (IsEqualIID(riid, IID_IBandSite))
88c2c66affSColin Finck         {
89c2c66affSColin Finck             *ppvObj = static_cast<IBandSite*>(this);
90c2c66affSColin Finck         }
91c2c66affSColin Finck         else if (IsEqualIID(riid, IID_IWinEventHandler))
92c2c66affSColin Finck         {
93c2c66affSColin Finck             TRACE("ITaskBandSite: IWinEventHandler queried!\n");
94c2c66affSColin Finck             *ppvObj = NULL;
95c2c66affSColin Finck             return E_NOINTERFACE;
96c2c66affSColin Finck         }
97c2c66affSColin Finck         else if (m_Inner != NULL)
98c2c66affSColin Finck         {
99c2c66affSColin Finck             return m_Inner->QueryInterface(riid, ppvObj);
100c2c66affSColin Finck         }
101c2c66affSColin Finck         else
102c2c66affSColin Finck         {
103c2c66affSColin Finck             *ppvObj = NULL;
104c2c66affSColin Finck             return E_NOINTERFACE;
105c2c66affSColin Finck         }
106c2c66affSColin Finck 
107c2c66affSColin Finck         AddRef();
108c2c66affSColin Finck         return S_OK;
109c2c66affSColin Finck     }
110c2c66affSColin Finck 
111c2c66affSColin Finck public:
CTrayBandSite()112c2c66affSColin Finck     CTrayBandSite() :
113c2c66affSColin Finck         m_RefCount(0),
114c2c66affSColin Finck         m_Rebar(NULL)
115c2c66affSColin Finck     {
116c2c66affSColin Finck     }
117c2c66affSColin Finck 
~CTrayBandSite()118c2c66affSColin Finck     virtual ~CTrayBandSite() { }
119c2c66affSColin Finck 
120*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
OnLoad(IN OUT IStream * pStm,IN REFIID riid,OUT PVOID * pvObj)121*853b8ebdSKatayama Hirofumi MZ     OnLoad(
122c2c66affSColin Finck         IN OUT IStream *pStm,
123c2c66affSColin Finck         IN REFIID riid,
124*853b8ebdSKatayama Hirofumi MZ         OUT PVOID *pvObj) override
125c2c66affSColin Finck     {
126c2c66affSColin Finck         LARGE_INTEGER liPosZero;
127c2c66affSColin Finck         ULARGE_INTEGER liCurrent;
128c2c66affSColin Finck         CLSID clsid;
129c2c66affSColin Finck         ULONG ulRead;
130c2c66affSColin Finck         HRESULT hRet;
131c2c66affSColin Finck 
132c2c66affSColin Finck         /* NOTE: Callback routine called by the shell while loading the task band
133c2c66affSColin Finck                  stream. We use it to intercept the default behavior when the task
134c2c66affSColin Finck                  band is loaded from the stream.
135c2c66affSColin Finck 
136c2c66affSColin Finck                  NOTE: riid always points to IID_IUnknown! This is because the shell hasn't
137c2c66affSColin Finck                  read anything from the stream and therefore doesn't know what CLSID
138c2c66affSColin Finck                  it's dealing with. We'll have to find it out ourselves by reading
139c2c66affSColin Finck                  the GUID from the stream. */
140c2c66affSColin Finck 
141c2c66affSColin Finck         /* Read the current position of the stream, we'll have to reset it everytime
142c2c66affSColin Finck            we read a CLSID that's not the task band... */
143c2c66affSColin Finck         ZeroMemory(&liPosZero, sizeof(liPosZero));
144c2c66affSColin Finck         hRet = pStm->Seek(liPosZero, STREAM_SEEK_CUR, &liCurrent);
145c2c66affSColin Finck 
146c2c66affSColin Finck         if (SUCCEEDED(hRet))
147c2c66affSColin Finck         {
148c2c66affSColin Finck             /* Now let's read the CLSID from the stream and see if it's our task band */
149c2c66affSColin Finck             hRet = pStm->Read(&clsid, (ULONG)sizeof(clsid), &ulRead);
150c2c66affSColin Finck 
151c2c66affSColin Finck             if (SUCCEEDED(hRet) && ulRead == sizeof(clsid))
152c2c66affSColin Finck             {
153c2c66affSColin Finck                 if (IsEqualGUID(clsid, CLSID_ITaskBand))
154c2c66affSColin Finck                 {
155c2c66affSColin Finck                     ASSERT(m_TaskBand != NULL);
156c2c66affSColin Finck                     /* We're trying to load the task band! Let's create it... */
157c2c66affSColin Finck 
158c2c66affSColin Finck                     hRet = m_TaskBand->QueryInterface(
159c2c66affSColin Finck                         riid,
160c2c66affSColin Finck                         pvObj);
161c2c66affSColin Finck                     if (SUCCEEDED(hRet))
162c2c66affSColin Finck                     {
163c2c66affSColin Finck                         /* Load the stream */
164c2c66affSColin Finck                         TRACE("IBandSiteStreamCallback::OnLoad intercepted the task band CLSID!\n");
165c2c66affSColin Finck                     }
166c2c66affSColin Finck 
167c2c66affSColin Finck                     return hRet;
168c2c66affSColin Finck                 }
169c2c66affSColin Finck             }
170c2c66affSColin Finck         }
171c2c66affSColin Finck 
172c2c66affSColin Finck         /* Reset the position and let the shell do all the work for us */
173c2c66affSColin Finck         hRet = pStm->Seek(
174c2c66affSColin Finck             *(LARGE_INTEGER*) &liCurrent,
175c2c66affSColin Finck             STREAM_SEEK_SET,
176c2c66affSColin Finck             NULL);
177c2c66affSColin Finck         if (SUCCEEDED(hRet))
178c2c66affSColin Finck         {
179c2c66affSColin Finck             /* Let the shell handle everything else for us :) */
180c2c66affSColin Finck             hRet = OleLoadFromStream(pStm,
181c2c66affSColin Finck                 riid,
182c2c66affSColin Finck                 pvObj);
183c2c66affSColin Finck         }
184c2c66affSColin Finck 
185c2c66affSColin Finck         if (!SUCCEEDED(hRet))
186c2c66affSColin Finck         {
187c2c66affSColin Finck             TRACE("IBandSiteStreamCallback::OnLoad(0x%p, 0x%p, 0x%p) returns 0x%x\n", pStm, riid, pvObj, hRet);
188c2c66affSColin Finck         }
189c2c66affSColin Finck 
190c2c66affSColin Finck         return hRet;
191c2c66affSColin Finck     }
192c2c66affSColin Finck 
193*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
OnSave(IN OUT IUnknown * pUnk,IN OUT IStream * pStm)194*853b8ebdSKatayama Hirofumi MZ     OnSave(
195c2c66affSColin Finck         IN OUT IUnknown *pUnk,
196*853b8ebdSKatayama Hirofumi MZ         IN OUT IStream *pStm) override
197c2c66affSColin Finck     {
198c2c66affSColin Finck         /* NOTE: Callback routine called by the shell while saving the task band
199c2c66affSColin Finck                  stream. We use it to intercept the default behavior when the task
200c2c66affSColin Finck                  band is saved to the stream */
201c2c66affSColin Finck         /* FIXME: Implement */
202c2c66affSColin Finck         TRACE("IBandSiteStreamCallback::OnSave(0x%p, 0x%p) returns E_NOTIMPL\n", pUnk, pStm);
203c2c66affSColin Finck         return E_NOTIMPL;
204c2c66affSColin Finck     }
205c2c66affSColin Finck 
206*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
IsTaskBand(IN IUnknown * punk)207*853b8ebdSKatayama Hirofumi MZ     IsTaskBand(IN IUnknown *punk) override
208c2c66affSColin Finck     {
209c2c66affSColin Finck         return IsSameObject(m_BandSite, punk);
210c2c66affSColin Finck     }
211c2c66affSColin Finck 
212*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
ProcessMessage(IN HWND hWnd,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam,OUT LRESULT * plResult)213*853b8ebdSKatayama Hirofumi MZ     ProcessMessage(
214c2c66affSColin Finck         IN HWND hWnd,
215c2c66affSColin Finck         IN UINT uMsg,
216c2c66affSColin Finck         IN WPARAM wParam,
217c2c66affSColin Finck         IN LPARAM lParam,
218*853b8ebdSKatayama Hirofumi MZ         OUT LRESULT *plResult) override
219c2c66affSColin Finck     {
220c2c66affSColin Finck         HRESULT hRet;
221c2c66affSColin Finck 
222c2c66affSColin Finck         ASSERT(m_Rebar != NULL);
223c2c66affSColin Finck 
224c2c66affSColin Finck         /* Custom task band behavior */
225c2c66affSColin Finck         switch (uMsg)
226c2c66affSColin Finck         {
227c2c66affSColin Finck         case WM_NOTIFY:
228c2c66affSColin Finck         {
229c2c66affSColin Finck             const NMHDR *nmh = (const NMHDR *) lParam;
230c2c66affSColin Finck 
231c2c66affSColin Finck             if (nmh->hwndFrom == m_Rebar)
232c2c66affSColin Finck             {
233c2c66affSColin Finck                 switch (nmh->code)
234c2c66affSColin Finck                 {
235c2c66affSColin Finck                 case NM_NCHITTEST:
236c2c66affSColin Finck                 {
237c2c66affSColin Finck                     LPNMMOUSE nmm = (LPNMMOUSE) lParam;
238c2c66affSColin Finck 
239c2c66affSColin Finck                     if (nmm->dwHitInfo == RBHT_CLIENT || nmm->dwHitInfo == RBHT_NOWHERE ||
240c2c66affSColin Finck                         nmm->dwItemSpec == (DWORD_PTR) -1)
241c2c66affSColin Finck                     {
242c2c66affSColin Finck                         /* Make the rebar control appear transparent so the user
243c2c66affSColin Finck                            can drag the tray window */
244c2c66affSColin Finck                         *plResult = HTTRANSPARENT;
245c2c66affSColin Finck                     }
246c2c66affSColin Finck                     return S_OK;
247c2c66affSColin Finck                 }
248c2c66affSColin Finck 
249c2c66affSColin Finck                 case RBN_MINMAX:
250c2c66affSColin Finck                     /* Deny if an Administrator disabled this "feature" */
251c2c66affSColin Finck                     *plResult = (SHRestricted(REST_NOMOVINGBAND) != 0);
252c2c66affSColin Finck                     return S_OK;
253c2c66affSColin Finck                 }
254c2c66affSColin Finck             }
255c2c66affSColin Finck 
256c2c66affSColin Finck             //TRACE("ITrayBandSite::ProcessMessage: WM_NOTIFY for 0x%p, From: 0x%p, Code: NM_FIRST-%u...\n", hWnd, nmh->hwndFrom, NM_FIRST - nmh->code);
257c2c66affSColin Finck             break;
258c2c66affSColin Finck         }
259c2c66affSColin Finck         }
260c2c66affSColin Finck 
261c2c66affSColin Finck         /* Forward to the shell's IWinEventHandler interface to get the default shell behavior! */
262c2c66affSColin Finck         if (!m_WindowEventHandler)
263c2c66affSColin Finck             return E_FAIL;
264c2c66affSColin Finck 
265c2c66affSColin Finck         /*TRACE("Calling IWinEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p) hWndRebar=0x%p\n", hWnd, uMsg, wParam, lParam, plResult, hWndRebar);*/
266c2c66affSColin Finck         hRet = m_WindowEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, plResult);
267c2c66affSColin Finck 
268c2c66affSColin Finck #if 0
269c2c66affSColin Finck         if (FAILED(hRet))
270c2c66affSColin Finck         {
271c2c66affSColin Finck             if (uMsg == WM_NOTIFY)
272c2c66affSColin Finck             {
273c2c66affSColin Finck                 const NMHDR *nmh = (const NMHDR *) lParam;
274c2c66affSColin Finck                 ERR("ITrayBandSite->IWinEventHandler::ProcessMessage: WM_NOTIFY for 0x%p, From: 0x%p, Code: NM_FIRST-%u returned 0x%x\n", hWnd, nmh->hwndFrom, NM_FIRST - nmh->code, hRet);
275c2c66affSColin Finck             }
276c2c66affSColin Finck             else
277c2c66affSColin Finck             {
278c2c66affSColin Finck                 ERR("ITrayBandSite->IWinEventHandler::ProcessMessage(0x%p,0x%x,0x%p,0x%p,0x%p->0x%p) returned: 0x%x\n", hWnd, uMsg, wParam, lParam, plResult, *plResult, hRet);
279c2c66affSColin Finck             }
280c2c66affSColin Finck         }
281c2c66affSColin Finck #endif
282c2c66affSColin Finck 
283c2c66affSColin Finck         return hRet;
284c2c66affSColin Finck     }
285c2c66affSColin Finck 
286*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
AddContextMenus(IN HMENU hmenu,IN UINT indexMenu,IN UINT idCmdFirst,IN UINT idCmdLast,IN UINT uFlags,OUT IContextMenu ** ppcm)287*853b8ebdSKatayama Hirofumi MZ     AddContextMenus(
288c2c66affSColin Finck         IN HMENU hmenu,
289c2c66affSColin Finck         IN UINT indexMenu,
290c2c66affSColin Finck         IN UINT idCmdFirst,
291c2c66affSColin Finck         IN UINT idCmdLast,
292c2c66affSColin Finck         IN UINT uFlags,
293*853b8ebdSKatayama Hirofumi MZ         OUT IContextMenu **ppcm) override
294c2c66affSColin Finck     {
295c2c66affSColin Finck         HRESULT hRet;
296c2c66affSColin Finck 
297c2c66affSColin Finck         if (m_ContextMenu == NULL)
298c2c66affSColin Finck         {
299c2c66affSColin Finck             /* Cache the context menu so we don't need to CoCreateInstance all the time... */
300c2c66affSColin Finck             hRet = _CBandSiteMenu_CreateInstance(IID_PPV_ARG(IContextMenu, &m_ContextMenu));
301c2c66affSColin Finck             if (FAILED_UNEXPECTEDLY(hRet))
302c2c66affSColin Finck                 return hRet;
303c2c66affSColin Finck 
304c2c66affSColin Finck             hRet = IUnknown_SetOwner(m_ContextMenu, (IBandSite*)this);
305c2c66affSColin Finck             if (FAILED_UNEXPECTEDLY(hRet))
306c2c66affSColin Finck                 return hRet;
307c2c66affSColin Finck         }
308c2c66affSColin Finck 
309c2c66affSColin Finck         if (ppcm != NULL)
310c2c66affSColin Finck         {
311c2c66affSColin Finck             *ppcm = m_ContextMenu;
312cd2d2841SMark Jansen             (*ppcm)->AddRef();
313c2c66affSColin Finck         }
314c2c66affSColin Finck 
315c2c66affSColin Finck         /* Add the menu items */
316c2c66affSColin Finck         hRet = m_ContextMenu->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
317c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
318c2c66affSColin Finck             return hRet;
319c2c66affSColin Finck 
320c2c66affSColin Finck         return S_OK;
321c2c66affSColin Finck     }
322c2c66affSColin Finck 
323*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
Lock(IN BOOL bLock)324*853b8ebdSKatayama Hirofumi MZ     Lock(IN BOOL bLock) override
325c2c66affSColin Finck     {
326c2c66affSColin Finck         BOOL bPrevLocked = Locked;
327c2c66affSColin Finck         BANDSITEINFO bsi;
328c2c66affSColin Finck         HRESULT hRet;
329c2c66affSColin Finck 
330c2c66affSColin Finck         ASSERT(m_BandSite != NULL);
331c2c66affSColin Finck 
332c2c66affSColin Finck         if (bPrevLocked != bLock)
333c2c66affSColin Finck         {
334c2c66affSColin Finck             Locked = bLock;
335c2c66affSColin Finck 
336c2c66affSColin Finck             bsi.dwMask = BSIM_STYLE;
337c2c66affSColin Finck             bsi.dwStyle = (Locked ? BSIS_LOCKED | BSIS_NOGRIPPER : BSIS_AUTOGRIPPER);
338c2c66affSColin Finck 
339c2c66affSColin Finck             hRet = m_BandSite->SetBandSiteInfo(&bsi);
340c2c66affSColin Finck             if (SUCCEEDED(hRet))
341c2c66affSColin Finck             {
342c2c66affSColin Finck                 hRet = Update();
343c2c66affSColin Finck             }
344c2c66affSColin Finck 
345c2c66affSColin Finck             return hRet;
346c2c66affSColin Finck         }
347c2c66affSColin Finck 
348c2c66affSColin Finck         return S_FALSE;
349c2c66affSColin Finck     }
350c2c66affSColin Finck 
351c2c66affSColin Finck     /*******************************************************************/
352c2c66affSColin Finck 
353*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
AddBand(IN IUnknown * punk)354*853b8ebdSKatayama Hirofumi MZ     AddBand(IN IUnknown *punk) override
355c2c66affSColin Finck     {
356c2c66affSColin Finck         /* Send the DBID_DELAYINIT command to initialize the band to be added */
357c2c66affSColin Finck         /* FIXME: Should be delayed */
358c2c66affSColin Finck         IUnknown_Exec(punk, IID_IDeskBand, DBID_DELAYINIT, 0, NULL, NULL);
359c2c66affSColin Finck 
36071e66c69SGiannis Adamopoulos         HRESULT hr = m_BandSite->AddBand(punk);
36171e66c69SGiannis Adamopoulos         if (FAILED_UNEXPECTEDLY(hr))
36271e66c69SGiannis Adamopoulos             return hr;
36371e66c69SGiannis Adamopoulos 
36471e66c69SGiannis Adamopoulos         VARIANT vThemeName;
36571e66c69SGiannis Adamopoulos         V_VT(&vThemeName) = VT_BSTR;
36671e66c69SGiannis Adamopoulos         V_BSTR(&vThemeName) = SysAllocString(L"TaskBar");
36771e66c69SGiannis Adamopoulos         IUnknown_Exec(punk,
36871e66c69SGiannis Adamopoulos                       IID_IDeskBand,
36971e66c69SGiannis Adamopoulos                       DBID_SETWINDOWTHEME,
37071e66c69SGiannis Adamopoulos                       0,
37171e66c69SGiannis Adamopoulos                       &vThemeName,
37271e66c69SGiannis Adamopoulos                       NULL);
37371e66c69SGiannis Adamopoulos 
37471e66c69SGiannis Adamopoulos         SysFreeString(V_BSTR(&vThemeName));
37571e66c69SGiannis Adamopoulos 
37671e66c69SGiannis Adamopoulos         return S_OK;
377c2c66affSColin Finck     }
378c2c66affSColin Finck 
379*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
EnumBands(IN UINT uBand,OUT DWORD * pdwBandID)380*853b8ebdSKatayama Hirofumi MZ     EnumBands(
381c2c66affSColin Finck         IN UINT uBand,
382*853b8ebdSKatayama Hirofumi MZ         OUT DWORD *pdwBandID) override
383c2c66affSColin Finck     {
384c2c66affSColin Finck         return m_BandSite->EnumBands(uBand, pdwBandID);
385c2c66affSColin Finck     }
386c2c66affSColin Finck 
387*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
QueryBand(IN DWORD dwBandID,OUT IDeskBand ** ppstb,OUT DWORD * pdwState,OUT LPWSTR pszName,IN int cchName)388*853b8ebdSKatayama Hirofumi MZ     QueryBand(
389c2c66affSColin Finck         IN DWORD dwBandID,
390c2c66affSColin Finck         OUT IDeskBand **ppstb,
391c2c66affSColin Finck         OUT DWORD *pdwState,
392c2c66affSColin Finck         OUT LPWSTR pszName,
393*853b8ebdSKatayama Hirofumi MZ         IN int cchName) override
394c2c66affSColin Finck     {
395c2c66affSColin Finck         HRESULT hRet;
396c2c66affSColin Finck         IDeskBand *pstb = NULL;
397c2c66affSColin Finck 
398c2c66affSColin Finck         hRet = m_BandSite->QueryBand(
399c2c66affSColin Finck             dwBandID,
400c2c66affSColin Finck             &pstb,
401c2c66affSColin Finck             pdwState,
402c2c66affSColin Finck             pszName,
403c2c66affSColin Finck             cchName);
404c2c66affSColin Finck 
405c2c66affSColin Finck         if (SUCCEEDED(hRet))
406c2c66affSColin Finck         {
407c2c66affSColin Finck             hRet = IsSameObject(pstb, m_TaskBand);
408c2c66affSColin Finck             if (hRet == S_OK)
409c2c66affSColin Finck             {
410c2c66affSColin Finck                 /* Add the BSSF_UNDELETEABLE flag to pdwState because the task bar band shouldn't be deletable */
411c2c66affSColin Finck                 if (pdwState != NULL)
412c2c66affSColin Finck                     *pdwState |= BSSF_UNDELETEABLE;
413c2c66affSColin Finck             }
414c2c66affSColin Finck             else if (!SUCCEEDED(hRet))
415c2c66affSColin Finck             {
416c2c66affSColin Finck                 pstb->Release();
417c2c66affSColin Finck                 pstb = NULL;
418c2c66affSColin Finck             }
419c2c66affSColin Finck 
420c2c66affSColin Finck             if (ppstb != NULL)
421c2c66affSColin Finck                 *ppstb = pstb;
422c2c66affSColin Finck         }
423c2c66affSColin Finck         else if (ppstb != NULL)
424c2c66affSColin Finck             *ppstb = NULL;
425c2c66affSColin Finck 
426c2c66affSColin Finck         return hRet;
427c2c66affSColin Finck     }
428c2c66affSColin Finck 
429*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
SetBandState(IN DWORD dwBandID,IN DWORD dwMask,IN DWORD dwState)430*853b8ebdSKatayama Hirofumi MZ     SetBandState(
431c2c66affSColin Finck         IN DWORD dwBandID,
432c2c66affSColin Finck         IN DWORD dwMask,
433*853b8ebdSKatayama Hirofumi MZ         IN DWORD dwState) override
434c2c66affSColin Finck     {
435c2c66affSColin Finck         return m_BandSite->SetBandState(dwBandID, dwMask, dwState);
436c2c66affSColin Finck     }
437c2c66affSColin Finck 
438*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
RemoveBand(IN DWORD dwBandID)439*853b8ebdSKatayama Hirofumi MZ     RemoveBand(IN DWORD dwBandID) override
440c2c66affSColin Finck     {
441c2c66affSColin Finck         return m_BandSite->RemoveBand(dwBandID);
442c2c66affSColin Finck     }
443c2c66affSColin Finck 
444*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
GetBandObject(IN DWORD dwBandID,IN REFIID riid,OUT VOID ** ppv)445*853b8ebdSKatayama Hirofumi MZ     GetBandObject(
446c2c66affSColin Finck         IN DWORD dwBandID,
447c2c66affSColin Finck         IN REFIID riid,
448*853b8ebdSKatayama Hirofumi MZ         OUT VOID **ppv) override
449c2c66affSColin Finck     {
450c2c66affSColin Finck         return m_BandSite->GetBandObject(dwBandID, riid, ppv);
451c2c66affSColin Finck     }
452c2c66affSColin Finck 
453*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
SetBandSiteInfo(IN const BANDSITEINFO * pbsinfo)454*853b8ebdSKatayama Hirofumi MZ     SetBandSiteInfo(IN const BANDSITEINFO *pbsinfo) override
455c2c66affSColin Finck     {
456c2c66affSColin Finck         return m_BandSite->SetBandSiteInfo(pbsinfo);
457c2c66affSColin Finck     }
458c2c66affSColin Finck 
459*853b8ebdSKatayama Hirofumi MZ     STDMETHODIMP
GetBandSiteInfo(IN OUT BANDSITEINFO * pbsinfo)460*853b8ebdSKatayama Hirofumi MZ     GetBandSiteInfo(IN OUT BANDSITEINFO *pbsinfo) override
461c2c66affSColin Finck     {
462c2c66affSColin Finck         return m_BandSite->GetBandSiteInfo(pbsinfo);
463c2c66affSColin Finck     }
464c2c66affSColin Finck 
HasTaskBand()465c2c66affSColin Finck     virtual BOOL HasTaskBand()
466c2c66affSColin Finck     {
467c2c66affSColin Finck         CComPtr<IPersist> pBand;
468c2c66affSColin Finck         CLSID BandCLSID;
469c2c66affSColin Finck         DWORD dwBandID;
470c2c66affSColin Finck         UINT uBand = 0;
471c2c66affSColin Finck 
472c2c66affSColin Finck         /* Enumerate all bands */
473c2c66affSColin Finck         while (SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID)))
474c2c66affSColin Finck         {
475ea34ecc9SCarl J. Bialorucki             if (dwBandID && SUCCEEDED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IPersist, &pBand))))
476c2c66affSColin Finck             {
477c2c66affSColin Finck                 if (SUCCEEDED(pBand->GetClassID(&BandCLSID)))
478c2c66affSColin Finck                 {
479c2c66affSColin Finck                     if (IsEqualGUID(BandCLSID, CLSID_ITaskBand))
480c2c66affSColin Finck                     {
481c2c66affSColin Finck                         return TRUE;
482c2c66affSColin Finck                     }
483c2c66affSColin Finck                 }
484c2c66affSColin Finck             }
485c2c66affSColin Finck             uBand++;
486c2c66affSColin Finck         }
487c2c66affSColin Finck 
488c2c66affSColin Finck         return FALSE;
489c2c66affSColin Finck     }
490c2c66affSColin Finck 
Update()491c2c66affSColin Finck     virtual HRESULT Update()
492c2c66affSColin Finck     {
493c2c66affSColin Finck         return IUnknown_Exec(m_Inner,
494c2c66affSColin Finck                 IID_IDeskBand,
495c2c66affSColin Finck                 DBID_BANDINFOCHANGED,
496c2c66affSColin Finck                 0,
497c2c66affSColin Finck                 NULL,
498c2c66affSColin Finck                 NULL);
499c2c66affSColin Finck     }
500c2c66affSColin Finck 
BroadcastOleCommandExec(REFGUID pguidCmdGroup,DWORD nCmdID,DWORD nCmdExecOpt,VARIANTARG * pvaIn,VARIANTARG * pvaOut)501c2c66affSColin Finck     virtual VOID BroadcastOleCommandExec(REFGUID pguidCmdGroup,
502c2c66affSColin Finck         DWORD nCmdID,
503c2c66affSColin Finck         DWORD nCmdExecOpt,
504c2c66affSColin Finck         VARIANTARG *pvaIn,
505c2c66affSColin Finck         VARIANTARG *pvaOut)
506c2c66affSColin Finck     {
507c2c66affSColin Finck         IOleCommandTarget *pOct;
508c2c66affSColin Finck         DWORD dwBandID;
509c2c66affSColin Finck         UINT uBand = 0;
510c2c66affSColin Finck 
511c2c66affSColin Finck         /* Enumerate all bands */
512c2c66affSColin Finck         while (SUCCEEDED(m_BandSite->EnumBands(uBand, &dwBandID)))
513c2c66affSColin Finck         {
514c2c66affSColin Finck             if (SUCCEEDED(m_BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IOleCommandTarget, &pOct))))
515c2c66affSColin Finck             {
516c2c66affSColin Finck                 /* Execute the command */
517c2c66affSColin Finck                 pOct->Exec(
518c2c66affSColin Finck                     &pguidCmdGroup,
519c2c66affSColin Finck                     nCmdID,
520c2c66affSColin Finck                     nCmdExecOpt,
521c2c66affSColin Finck                     pvaIn,
522c2c66affSColin Finck                     pvaOut);
523c2c66affSColin Finck 
524c2c66affSColin Finck                 pOct->Release();
525c2c66affSColin Finck             }
526c2c66affSColin Finck 
527c2c66affSColin Finck             uBand++;
528c2c66affSColin Finck         }
529c2c66affSColin Finck     }
530c2c66affSColin Finck 
FinishInit()531c2c66affSColin Finck     virtual HRESULT FinishInit()
532c2c66affSColin Finck     {
533c2c66affSColin Finck         /* Broadcast the DBID_FINISHINIT command */
534c2c66affSColin Finck         BroadcastOleCommandExec(IID_IDeskBand, DBID_FINISHINIT, 0, NULL, NULL);
535c2c66affSColin Finck 
536c2c66affSColin Finck         return S_OK;
537c2c66affSColin Finck     }
538c2c66affSColin Finck 
Show(IN BOOL bShow)539c2c66affSColin Finck     virtual HRESULT Show(IN BOOL bShow)
540c2c66affSColin Finck     {
541c2c66affSColin Finck         CComPtr<IDeskBarClient> pDbc;
542c2c66affSColin Finck         HRESULT hRet;
543c2c66affSColin Finck 
544c2c66affSColin Finck         hRet = m_BandSite->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDbc));
545c2c66affSColin Finck         if (SUCCEEDED(hRet))
546c2c66affSColin Finck         {
547c2c66affSColin Finck             hRet = pDbc->UIActivateDBC(bShow ? DBC_SHOW : DBC_HIDE);
548c2c66affSColin Finck         }
549c2c66affSColin Finck 
550c2c66affSColin Finck         return hRet;
551c2c66affSColin Finck     }
552c2c66affSColin Finck 
LoadFromStream(IN OUT IStream * pStm)553c2c66affSColin Finck     virtual HRESULT LoadFromStream(IN OUT IStream *pStm)
554c2c66affSColin Finck     {
555c2c66affSColin Finck         CComPtr<IPersistStream> pPStm;
556c2c66affSColin Finck         HRESULT hRet;
557c2c66affSColin Finck 
558c2c66affSColin Finck         ASSERT(m_BandSite != NULL);
559c2c66affSColin Finck 
560c2c66affSColin Finck         /* We implement the undocumented COM interface IBandSiteStreamCallback
561c2c66affSColin Finck            that the shell will query so that we can intercept and custom-load
562c2c66affSColin Finck            the task band when it finds the task band's CLSID (which is internal).
563c2c66affSColin Finck            This way we can prevent the shell from attempting to CoCreateInstance
564c2c66affSColin Finck            the (internal) task band, resulting in a failure... */
565c2c66affSColin Finck         hRet = m_BandSite->QueryInterface(IID_PPV_ARG(IPersistStream, &pPStm));
566c2c66affSColin Finck         if (SUCCEEDED(hRet))
567c2c66affSColin Finck         {
568c2c66affSColin Finck             hRet = pPStm->Load(pStm);
569c2c66affSColin Finck             TRACE("->Load() returned 0x%x\n", hRet);
570c2c66affSColin Finck         }
571c2c66affSColin Finck 
572c2c66affSColin Finck         return hRet;
573c2c66affSColin Finck     }
574c2c66affSColin Finck 
GetUserBandsStream(IN DWORD grfMode)575c2c66affSColin Finck     virtual IStream * GetUserBandsStream(IN DWORD grfMode)
576c2c66affSColin Finck     {
577c2c66affSColin Finck         HKEY hkStreams;
578c2c66affSColin Finck         IStream *Stream = NULL;
579c2c66affSColin Finck 
580c2c66affSColin Finck         if (RegCreateKeyW(hkExplorer,
581c2c66affSColin Finck                           L"Streams",
582c2c66affSColin Finck                           &hkStreams) == ERROR_SUCCESS)
583c2c66affSColin Finck         {
584c2c66affSColin Finck             Stream = SHOpenRegStreamW(hkStreams,
585c2c66affSColin Finck                                       L"Desktop",
586c2c66affSColin Finck                                       L"TaskbarWinXP",
587c2c66affSColin Finck                                       grfMode);
588c2c66affSColin Finck 
589c2c66affSColin Finck             RegCloseKey(hkStreams);
590c2c66affSColin Finck         }
591c2c66affSColin Finck 
592c2c66affSColin Finck         return Stream;
593c2c66affSColin Finck     }
594c2c66affSColin Finck 
GetDefaultBandsStream(IN DWORD grfMode)595c2c66affSColin Finck     virtual IStream * GetDefaultBandsStream(IN DWORD grfMode)
596c2c66affSColin Finck     {
597c2c66affSColin Finck         HKEY hkStreams;
598c2c66affSColin Finck         IStream *Stream = NULL;
599c2c66affSColin Finck 
600c2c66affSColin Finck         if (RegCreateKeyW(HKEY_LOCAL_MACHINE,
601c2c66affSColin Finck             L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Streams",
602c2c66affSColin Finck             &hkStreams) == ERROR_SUCCESS)
603c2c66affSColin Finck         {
604c2c66affSColin Finck             Stream = SHOpenRegStreamW(hkStreams,
605c2c66affSColin Finck                                       L"Desktop",
606c2c66affSColin Finck                                       L"Default Taskbar",
607c2c66affSColin Finck                                       grfMode);
608c2c66affSColin Finck 
609c2c66affSColin Finck             RegCloseKey(hkStreams);
610c2c66affSColin Finck         }
611c2c66affSColin Finck 
612c2c66affSColin Finck         return Stream;
613c2c66affSColin Finck     }
614c2c66affSColin Finck 
Load()615c2c66affSColin Finck     virtual HRESULT Load()
616c2c66affSColin Finck     {
617c2c66affSColin Finck         IStream *pStm;
618c2c66affSColin Finck         HRESULT hRet;
619c2c66affSColin Finck 
620c2c66affSColin Finck         /* Try to load the user's settings */
621c2c66affSColin Finck         pStm = GetUserBandsStream(STGM_READ);
622c2c66affSColin Finck         if (pStm != NULL)
623c2c66affSColin Finck         {
624c2c66affSColin Finck             hRet = LoadFromStream(pStm);
625c2c66affSColin Finck 
626c2c66affSColin Finck             TRACE("Loaded user bands settings: 0x%x\n", hRet);
627c2c66affSColin Finck             pStm->Release();
628c2c66affSColin Finck         }
629c2c66affSColin Finck         else
630c2c66affSColin Finck             hRet = E_FAIL;
631c2c66affSColin Finck 
632c2c66affSColin Finck         /* If the user's settings couldn't be loaded, try with
633c2c66affSColin Finck            default settings (ie. when the user logs in for the
634c2c66affSColin Finck            first time! */
635c2c66affSColin Finck         if (!SUCCEEDED(hRet))
636c2c66affSColin Finck         {
637c2c66affSColin Finck             pStm = GetDefaultBandsStream(STGM_READ);
638c2c66affSColin Finck             if (pStm != NULL)
639c2c66affSColin Finck             {
640c2c66affSColin Finck                 hRet = LoadFromStream(pStm);
641c2c66affSColin Finck 
642c2c66affSColin Finck                 TRACE("Loaded default user bands settings: 0x%x\n", hRet);
643c2c66affSColin Finck                 pStm->Release();
644c2c66affSColin Finck             }
645c2c66affSColin Finck             else
646c2c66affSColin Finck                 hRet = E_FAIL;
647c2c66affSColin Finck         }
648c2c66affSColin Finck 
649c2c66affSColin Finck         return hRet;
650c2c66affSColin Finck     }
651c2c66affSColin Finck 
_Init(IN ITrayWindow * tray,IN IDeskBand * pTaskBand)652c2c66affSColin Finck     HRESULT _Init(IN ITrayWindow *tray, IN IDeskBand* pTaskBand)
653c2c66affSColin Finck     {
654c2c66affSColin Finck         CComPtr<IDeskBarClient> pDbc;
655c2c66affSColin Finck         CComPtr<IDeskBand> pDb;
656c2c66affSColin Finck         CComPtr<IOleWindow> pOw;
657c2c66affSColin Finck         HRESULT hRet;
658c2c66affSColin Finck 
659c2c66affSColin Finck         m_Tray = tray;
660c2c66affSColin Finck         m_TaskBand = pTaskBand;
661c2c66affSColin Finck 
662c2c66affSColin Finck         /* Create the RebarBandSite */
663c2c66affSColin Finck         hRet = _CBandSite_CreateInstance(static_cast<IBandSite*>(this), IID_PPV_ARG(IUnknown, &m_Inner));
664c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
665c2c66affSColin Finck             return hRet;
666c2c66affSColin Finck 
667c2c66affSColin Finck         hRet = m_Inner->QueryInterface(IID_PPV_ARG(IBandSite, &m_BandSite));
668c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
669c2c66affSColin Finck             return hRet;
670c2c66affSColin Finck 
671c2c66affSColin Finck         hRet = m_Inner->QueryInterface(IID_PPV_ARG(IWinEventHandler, &m_WindowEventHandler));
672c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
673c2c66affSColin Finck             return hRet;
674c2c66affSColin Finck 
675c2c66affSColin Finck         hRet = m_Inner->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDbc));
676c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
677c2c66affSColin Finck             return hRet;
678c2c66affSColin Finck 
679c2c66affSColin Finck 
680c2c66affSColin Finck 
681c2c66affSColin Finck 
682c2c66affSColin Finck         /* Crete the rebar in the tray */
683c2c66affSColin Finck         hRet = pDbc->SetDeskBarSite(tray);
684c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
685c2c66affSColin Finck             return hRet;
686c2c66affSColin Finck 
687c2c66affSColin Finck         hRet = pDbc->GetWindow(&m_Rebar);
688c2c66affSColin Finck         if (FAILED_UNEXPECTEDLY(hRet))
689c2c66affSColin Finck             return hRet;
690c2c66affSColin Finck 
691c2c66affSColin Finck         SetWindowStyle(m_Rebar, RBS_BANDBORDERS, 0);
692c2c66affSColin Finck 
693c2c66affSColin Finck         /* Set the Desk Bar mode to the current one */
694c2c66affSColin Finck         DWORD dwMode = 0;
695c2c66affSColin Finck         /* FIXME: We need to set the mode (and update) whenever the user docks
696c2c66affSColin Finck                   the tray window to another monitor edge! */
697c2c66affSColin Finck         if (!m_Tray->IsHorizontal())
698c2c66affSColin Finck             dwMode = DBIF_VIEWMODE_VERTICAL;
699c2c66affSColin Finck 
700c2c66affSColin Finck         hRet = pDbc->SetModeDBC(dwMode);
701c2c66affSColin Finck 
702c2c66affSColin Finck         /* Load the saved state of the task band site */
703c2c66affSColin Finck         /* FIXME: We should delay loading shell extensions, also see DBID_DELAYINIT */
704c2c66affSColin Finck         Load();
705c2c66affSColin Finck 
706c2c66affSColin Finck         /* Add the task bar band if it hasn't been added while loading */
707c2c66affSColin Finck         if (!HasTaskBand())
708c2c66affSColin Finck         {
709c2c66affSColin Finck             hRet = m_BandSite->AddBand(m_TaskBand);
710c2c66affSColin Finck             if (FAILED_UNEXPECTEDLY(hRet))
711c2c66affSColin Finck                 return hRet;
712c2c66affSColin Finck         }
713c2c66affSColin Finck 
714c2c66affSColin Finck         /* Should we send this after showing it? */
715c2c66affSColin Finck         Update();
716c2c66affSColin Finck 
717c2c66affSColin Finck         /* FIXME: When should we send this? Does anyone care anyway? */
718c2c66affSColin Finck         FinishInit();
719c2c66affSColin Finck 
720c2c66affSColin Finck         /* Activate the band site */
721c2c66affSColin Finck         Show(TRUE);
722c2c66affSColin Finck 
723c2c66affSColin Finck         return S_OK;
724c2c66affSColin Finck     }
725c2c66affSColin Finck };
726c2c66affSColin Finck /*******************************************************************/
727c2c66affSColin Finck 
CTrayBandSite_CreateInstance(IN ITrayWindow * tray,IN IDeskBand * pTaskBand,OUT ITrayBandSite ** pBandSite)728c2c66affSColin Finck HRESULT CTrayBandSite_CreateInstance(IN ITrayWindow *tray, IN IDeskBand* pTaskBand, OUT ITrayBandSite** pBandSite)
729c2c66affSColin Finck {
730c2c66affSColin Finck     HRESULT hr;
731c2c66affSColin Finck 
732c2c66affSColin Finck     CTrayBandSite * tb = new CTrayBandSite();
733c2c66affSColin Finck     if (!tb)
734c2c66affSColin Finck         return E_FAIL;
735c2c66affSColin Finck 
736c2c66affSColin Finck     tb->AddRef();
737c2c66affSColin Finck 
738c2c66affSColin Finck     hr = tb->_Init(tray, pTaskBand);
739c2c66affSColin Finck     if (FAILED_UNEXPECTEDLY(hr))
740c2c66affSColin Finck     {
741c2c66affSColin Finck         tb->Release();
742c2c66affSColin Finck         return hr;
743c2c66affSColin Finck     }
744c2c66affSColin Finck 
745c2c66affSColin Finck     *pBandSite = tb;
746c2c66affSColin Finck 
747c2c66affSColin Finck     return S_OK;
748c2c66affSColin Finck }
749