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