Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

901 lines
23 KiB

  1. #include "cabinet.h"
  2. #include "rcids.h"
  3. #include <shguidp.h>
  4. #include "bandsite.h"
  5. #include "shellp.h"
  6. #include "shdguid.h"
  7. #include "taskband.h"
  8. #include "taskbar.h"
  9. #include <regstr.h>
  10. #include "util.h"
  11. extern IStream *GetDesktopViewStream(DWORD grfMode, LPCTSTR pszName);
  12. HRESULT PersistStreamLoad(IStream *pstm, IUnknown *punk);
  13. HRESULT PersistStreamSave(IStream *pstm, BOOL fClearDirty, IUnknown *punk);
  14. const TCHAR c_szTaskbarWinXP[] = TEXT("TaskbarWinXP");
  15. const TCHAR c_szTaskbar[] = TEXT("Taskbar");
  16. // {69B3F106-0F04-11d3-AE2E-00C04F8EEA99}
  17. static const GUID CLSID_TrayBandSite = { 0x69b3f106, 0xf04, 0x11d3, { 0xae, 0x2e, 0x0, 0xc0, 0x4f, 0x8e, 0xea, 0x99 } };
  18. // {8B4A02DB-97BB-4C1B-BE75-8827A7358CD0}
  19. static const GUID CLSID_TipBand = { 0x8B4A02DB, 0x97BB, 0x4C1B, { 0xBE, 0x75, 0x88, 0x27, 0xA7, 0x35, 0x8C, 0xD0 } };
  20. class CTrayBandSite : public IBandSite
  21. , public IClassFactory
  22. {
  23. public:
  24. // *** IUnknown ***
  25. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  26. virtual STDMETHODIMP_(ULONG) AddRef(void) ;
  27. virtual STDMETHODIMP_(ULONG) Release(void);
  28. // *** IBandSite methods ***
  29. STDMETHOD(AddBand) (THIS_ IUnknown* punk);
  30. STDMETHOD(EnumBands) (THIS_ UINT uBand, DWORD* pdwBandID);
  31. STDMETHOD(QueryBand) (THIS_ DWORD dwBandID, IDeskBand** ppstb, DWORD* pdwState, LPWSTR pszName, int cchName) ;
  32. STDMETHOD(SetBandState) (THIS_ DWORD dwBandID, DWORD dwMask, DWORD dwState) ;
  33. STDMETHOD(RemoveBand) (THIS_ DWORD dwBandID);
  34. STDMETHOD(GetBandObject) (THIS_ DWORD dwBandID, REFIID riid, void ** ppvObj);
  35. STDMETHOD(SetBandSiteInfo) (THIS_ const BANDSITEINFO * pbsinfo);
  36. STDMETHOD(GetBandSiteInfo) (THIS_ BANDSITEINFO * pbsinfo);
  37. // *** IClassFactory methods ***
  38. HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObj)
  39. {
  40. if (pUnkOuter != NULL)
  41. return CLASS_E_NOAGGREGATION;
  42. return QueryInterface(riid, ppvObj);
  43. }
  44. HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock)
  45. {
  46. return S_OK;
  47. }
  48. IContextMenu3* GetContextMenu();
  49. void SetInner(IUnknown* punk);
  50. void SetLoaded(BOOL fLoaded) {_fLoaded = fLoaded;}
  51. BOOL HandleMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres);
  52. protected:
  53. CTrayBandSite();
  54. virtual ~CTrayBandSite();
  55. BOOL _CreateBandSiteMenu(IUnknown* punk);
  56. HRESULT _AddRequiredBands();
  57. void _BroadcastExec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
  58. HRESULT _SetWindowTheme(LPWSTR pwzTheme);
  59. friend IBandSite* BandSite_CreateView();
  60. friend void BandSite_HandleDelayBootStuff(IUnknown* punk);
  61. friend void BandSite_Load();
  62. friend HRESULT BandSite_SetWindowTheme(IBandSite* pbs, LPWSTR pwzTheme);
  63. LONG _cRef;
  64. IUnknown *_punkInner;
  65. IBandSite *_pbsInner;
  66. // bandsite context menu
  67. IContextMenu3* _pcm;
  68. HWND _hwnd;
  69. BOOL _fLoaded;
  70. BOOL _fDelayBootStuffHandled;
  71. DWORD _dwClassObject;
  72. WCHAR* _pwzTheme;
  73. };
  74. CTrayBandSite* IUnknownToCTrayBandSite(IUnknown* punk)
  75. {
  76. CTrayBandSite* ptbs;
  77. punk->QueryInterface(CLSID_TrayBandSite, (void **)&ptbs);
  78. ASSERT(ptbs);
  79. punk->Release();
  80. return ptbs;
  81. }
  82. CTrayBandSite::CTrayBandSite() : _cRef(1)
  83. {
  84. }
  85. CTrayBandSite::~CTrayBandSite()
  86. {
  87. if (_pcm)
  88. _pcm->Release();
  89. if (_pwzTheme)
  90. delete[] _pwzTheme;
  91. return;
  92. }
  93. ULONG CTrayBandSite::AddRef()
  94. {
  95. return InterlockedIncrement(&_cRef);
  96. }
  97. ULONG CTrayBandSite::Release()
  98. {
  99. ASSERT(_cRef > 0);
  100. if (InterlockedDecrement(&_cRef))
  101. return _cRef;
  102. _cRef = 1000; // guard against recursion
  103. if (_pbsInner)
  104. {
  105. AddRef();
  106. _pbsInner->Release();
  107. }
  108. // this must come last
  109. if (_punkInner)
  110. _punkInner->Release(); // paired w/ CCI aggregation
  111. ASSERT(_cRef == 1000);
  112. delete this;
  113. return 0;
  114. }
  115. HRESULT CTrayBandSite::QueryInterface(REFIID riid, LPVOID * ppvObj)
  116. {
  117. static const QITAB qit[] =
  118. {
  119. QITABENT(CTrayBandSite, IBandSite),
  120. QITABENT(CTrayBandSite, IClassFactory),
  121. { 0 },
  122. };
  123. HRESULT hr = QISearch(this, qit, riid, ppvObj);
  124. if (FAILED(hr) && IsEqualIID(riid, CLSID_TrayBandSite))
  125. {
  126. *ppvObj = this;
  127. AddRef();
  128. hr = S_OK;
  129. }
  130. if (FAILED(hr) && _punkInner)
  131. {
  132. hr = _punkInner->QueryInterface(riid, ppvObj);
  133. }
  134. return hr;
  135. }
  136. static BOOL CALLBACK SetTransparency(HWND hwnd, LPARAM lParam)
  137. {
  138. SetWindowStyleEx(hwnd, WS_EX_TRANSPARENT, (BOOL)lParam);
  139. return TRUE;
  140. }
  141. // *** IBandSite methods ***
  142. HRESULT CTrayBandSite::AddBand(IUnknown* punk)
  143. {
  144. CLSID clsid;
  145. HRESULT hr = S_OK;
  146. if (!_fDelayBootStuffHandled)
  147. {
  148. //
  149. // Tell the band to go into "delay init" mode. When the tray
  150. // timer goes off we'll tell the band to finish up. (See
  151. // BandSite_HandleDelayBootStuff).
  152. //
  153. IUnknown_Exec(punk, &CGID_DeskBand, DBID_DELAYINIT, 0, NULL, NULL);
  154. }
  155. if (c_tray.GetIsNoToolbarsOnTaskbarPolicyEnabled())
  156. {
  157. hr = IUnknown_GetClassID(punk, &clsid);
  158. if (SUCCEEDED(hr))
  159. {
  160. hr = IsEqualGUID(clsid, CLSID_TaskBand) ? S_OK : E_FAIL;
  161. }
  162. }
  163. if (SUCCEEDED(hr))
  164. {
  165. hr = _pbsInner->AddBand(punk);
  166. if (SUCCEEDED(hr))
  167. {
  168. IShellFolderBand *pisfBand;
  169. HRESULT hrInner = punk->QueryInterface(IID_PPV_ARG(IShellFolderBand, &pisfBand));
  170. if (SUCCEEDED(hrInner))
  171. {
  172. BANDINFOSFB bi;
  173. bi.dwMask = ISFB_MASK_STATE;
  174. hrInner = pisfBand->GetBandInfoSFB(&bi);
  175. if (SUCCEEDED(hrInner))
  176. {
  177. bi.dwState |= ISFB_STATE_BTNMINSIZE;
  178. hrInner = pisfBand->SetBandInfoSFB(&bi);
  179. }
  180. pisfBand->Release();
  181. }
  182. // tell the band to use the taskbar theme
  183. if (_pwzTheme)
  184. {
  185. VARIANTARG var;
  186. var.vt = VT_BSTR;
  187. var.bstrVal = _pwzTheme;
  188. IUnknown_Exec(punk, &CGID_DeskBand, DBID_SETWINDOWTHEME, 0, &var, NULL);
  189. }
  190. if (GetWindowLong(_hwnd, GWL_EXSTYLE) & WS_EX_TRANSPARENT)
  191. {
  192. EnumChildWindows(_hwnd, SetTransparency, (LPARAM)TRUE);
  193. }
  194. }
  195. }
  196. return hr;
  197. }
  198. HRESULT CTrayBandSite::EnumBands(UINT uBand, DWORD* pdwBandID)
  199. {
  200. return _pbsInner->EnumBands(uBand, pdwBandID);
  201. }
  202. HRESULT CTrayBandSite::QueryBand(DWORD dwBandID, IDeskBand** ppstb, DWORD* pdwState, LPWSTR pszName, int cchName)
  203. {
  204. return _pbsInner->QueryBand(dwBandID, ppstb, pdwState, pszName, cchName);
  205. }
  206. HRESULT CTrayBandSite::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
  207. {
  208. return _pbsInner->SetBandState(dwBandID, dwMask, dwState);
  209. }
  210. HRESULT CTrayBandSite::RemoveBand(DWORD dwBandID)
  211. {
  212. return _pbsInner->RemoveBand(dwBandID);
  213. }
  214. HRESULT CTrayBandSite::GetBandObject(DWORD dwBandID, REFIID riid, void ** ppvObj)
  215. {
  216. return _pbsInner->GetBandObject(dwBandID, riid, ppvObj);
  217. }
  218. HRESULT CTrayBandSite::SetBandSiteInfo (const BANDSITEINFO * pbsinfo)
  219. {
  220. return _pbsInner->SetBandSiteInfo(pbsinfo);
  221. }
  222. HRESULT CTrayBandSite::GetBandSiteInfo (BANDSITEINFO * pbsinfo)
  223. {
  224. return _pbsInner->GetBandSiteInfo(pbsinfo);
  225. }
  226. HRESULT CTrayBandSite::_AddRequiredBands()
  227. {
  228. IDeskBand* pdb;
  229. HRESULT hr = CoCreateInstance(CLSID_TaskBand, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IDeskBand, &pdb));
  230. if (SUCCEEDED(hr))
  231. {
  232. hr = AddBand(pdb);
  233. pdb->Release();
  234. }
  235. return hr;
  236. }
  237. HRESULT CTrayBandSite::_SetWindowTheme(LPWSTR pwzTheme)
  238. {
  239. if (_pwzTheme)
  240. {
  241. delete[] _pwzTheme;
  242. _pwzTheme = NULL;
  243. }
  244. if (pwzTheme)
  245. {
  246. int iLen = lstrlen(pwzTheme);
  247. _pwzTheme = new WCHAR[iLen + 1];
  248. if (_pwzTheme)
  249. {
  250. lstrcpy(_pwzTheme, pwzTheme);
  251. }
  252. }
  253. return S_OK;
  254. }
  255. HRESULT BandSite_TestBandCLSID(IBandSite *pbs, DWORD idBand, REFIID riid)
  256. {
  257. HRESULT hr = E_FAIL;
  258. IPersist *pp;
  259. if (pbs)
  260. {
  261. hr = pbs->GetBandObject(idBand, IID_PPV_ARG(IPersist, &pp));
  262. if (SUCCEEDED(hr))
  263. {
  264. CLSID clsid;
  265. hr = pp->GetClassID(&clsid);
  266. if (SUCCEEDED(hr))
  267. {
  268. hr = IsEqualGUID(clsid, riid) ? S_OK : S_FALSE;
  269. }
  270. pp->Release();
  271. }
  272. }
  273. return hr;
  274. }
  275. HRESULT BandSite_SetWindowTheme(IBandSite* pbs, LPWSTR pwzTheme)
  276. {
  277. HRESULT hr = E_FAIL;
  278. if (pbs)
  279. {
  280. CTrayBandSite* ptbs = IUnknownToCTrayBandSite(pbs);
  281. if (ptbs)
  282. {
  283. ptbs->_SetWindowTheme(pwzTheme);
  284. }
  285. DWORD dwBandID;
  286. BOOL fFound = FALSE;
  287. for (int i = 0; !fFound && SUCCEEDED(pbs->EnumBands(i, &dwBandID)); i++)
  288. {
  289. IUnknown* punk;
  290. HRESULT hrInner = pbs->GetBandObject(dwBandID, IID_PPV_ARG(IUnknown, &punk));
  291. if (SUCCEEDED(hrInner))
  292. {
  293. VARIANTARG var;
  294. var.vt = VT_BSTR;
  295. var.bstrVal = pwzTheme;
  296. IUnknown_Exec(punk, &CGID_DeskBand, DBID_SETWINDOWTHEME, 0, &var, NULL);
  297. }
  298. }
  299. }
  300. return hr;
  301. }
  302. HRESULT BandSite_RemoveAllBands(IBandSite* pbs)
  303. {
  304. if (pbs)
  305. {
  306. DWORD dwBandID;
  307. while (SUCCEEDED(pbs->EnumBands(0, &dwBandID)))
  308. {
  309. pbs->RemoveBand(dwBandID);
  310. }
  311. }
  312. return S_OK;
  313. }
  314. HRESULT BandSite_FindBand(IBandSite* pbs, REFCLSID rclsid, REFIID riid, void **ppv, int *piCount, DWORD* pdwBandID)
  315. {
  316. HRESULT hr = E_FAIL;
  317. int iCount = 0;
  318. if (pbs)
  319. {
  320. DWORD dwBandID;
  321. for (int i = 0; SUCCEEDED(pbs->EnumBands(i, &dwBandID)); i++)
  322. {
  323. if (BandSite_TestBandCLSID(pbs, dwBandID, rclsid) == S_OK)
  324. {
  325. iCount++;
  326. if (pdwBandID)
  327. {
  328. *pdwBandID = dwBandID;
  329. }
  330. if (ppv)
  331. hr = pbs->GetBandObject(dwBandID, riid, ppv);
  332. else
  333. hr = S_OK;
  334. }
  335. }
  336. }
  337. if (piCount)
  338. {
  339. *piCount = iCount;
  340. }
  341. return hr;
  342. }
  343. void BandSite_Initialize(IBandSite* pbs)
  344. {
  345. HWND hwnd = v_hwndTray;
  346. CTaskBar *pow = new CTaskBar();
  347. if (pow)
  348. {
  349. IDeskBarClient* pdbc;
  350. if (SUCCEEDED(pbs->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pdbc))))
  351. {
  352. // we need to set a dummy tray IOleWindow
  353. pdbc->SetDeskBarSite(SAFECAST(pow, IOleWindow*));
  354. pdbc->GetWindow(&hwnd);
  355. if (hwnd)
  356. {
  357. // taskbar windows are themed under Taskbar subapp name
  358. SendMessage(hwnd, RB_SETWINDOWTHEME, 0, (LPARAM)c_wzTaskbarTheme);
  359. pow->_hwndRebar = hwnd;
  360. }
  361. pdbc->Release();
  362. }
  363. pow->Release();
  364. }
  365. }
  366. IContextMenu3* CTrayBandSite::GetContextMenu()
  367. {
  368. if (!_pcm)
  369. {
  370. if (SUCCEEDED(CoCreateInstance(CLSID_BandSiteMenu, NULL,CLSCTX_INPROC_SERVER,
  371. IID_PPV_ARG(IContextMenu3, &_pcm))))
  372. {
  373. IShellService* pss;
  374. if (SUCCEEDED(_pcm->QueryInterface(IID_PPV_ARG(IShellService, &pss))))
  375. {
  376. pss->SetOwner(SAFECAST(this, IBandSite*));
  377. pss->Release();
  378. }
  379. }
  380. }
  381. if (_pcm)
  382. _pcm->AddRef();
  383. return _pcm;
  384. }
  385. HRESULT BandSite_AddMenus(IUnknown* punk, HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast)
  386. {
  387. HRESULT hr = E_FAIL;
  388. CTrayBandSite* ptbs = IUnknownToCTrayBandSite(punk);
  389. IContextMenu3* pcm = ptbs->GetContextMenu();
  390. if (pcm)
  391. {
  392. hr = pcm->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, CMF_ICM3);
  393. pcm->Release();
  394. }
  395. return hr;
  396. }
  397. void BandSite_HandleMenuCommand(IUnknown* punk, UINT idCmd)
  398. {
  399. CTrayBandSite* ptbs = IUnknownToCTrayBandSite(punk);
  400. IContextMenu3* pcm = ptbs->GetContextMenu();
  401. if (pcm)
  402. {
  403. CMINVOKECOMMANDINFOEX ici =
  404. {
  405. sizeof(CMINVOKECOMMANDINFOEX),
  406. 0L,
  407. NULL,
  408. (LPSTR)MAKEINTRESOURCE(idCmd),
  409. NULL, NULL,
  410. SW_NORMAL,
  411. };
  412. pcm->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
  413. pcm->Release();
  414. }
  415. }
  416. void CTrayBandSite::SetInner(IUnknown* punk)
  417. {
  418. _punkInner = punk;
  419. _punkInner->QueryInterface(IID_PPV_ARG(IBandSite, &_pbsInner));
  420. Release();
  421. ASSERT(_pbsInner);
  422. }
  423. IBandSite* BandSite_CreateView()
  424. {
  425. IUnknown *punk;
  426. HRESULT hr = E_FAIL;
  427. // aggregate a TrayBandSite (from a RebarBandSite)
  428. CTrayBandSite *ptbs = new CTrayBandSite;
  429. if (ptbs)
  430. {
  431. hr = CoCreateInstance(CLSID_RebarBandSite, (IBandSite*)ptbs, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &punk));
  432. if (SUCCEEDED(hr))
  433. {
  434. ptbs->SetInner(punk); // paired w/ Release in outer (TBS::Release)
  435. BandSite_Initialize(ptbs);
  436. return SAFECAST(ptbs, IBandSite*);
  437. }
  438. else
  439. {
  440. delete ptbs;
  441. return NULL;
  442. }
  443. }
  444. return NULL;
  445. }
  446. HRESULT BandSite_SaveView(IUnknown *pbs)
  447. {
  448. HRESULT hr = E_FAIL;
  449. IStream *pstm = GetDesktopViewStream(STGM_WRITE, c_szTaskbarWinXP);
  450. if (pstm)
  451. {
  452. hr = PersistStreamSave(pstm, TRUE, pbs);
  453. pstm->Release();
  454. }
  455. return hr;
  456. }
  457. BOOL CTrayBandSite::HandleMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
  458. {
  459. if (!_hwnd)
  460. {
  461. IUnknown_GetWindow(SAFECAST(this, IBandSite*), &_hwnd);
  462. }
  463. switch (uMsg)
  464. {
  465. case WM_INITMENUPOPUP:
  466. case WM_MEASUREITEM:
  467. case WM_DRAWITEM:
  468. case WM_MENUCHAR:
  469. if (_pcm)
  470. {
  471. _pcm->HandleMenuMsg2(uMsg, wParam, lParam, plres);
  472. return TRUE;
  473. }
  474. break;
  475. case WM_NOTIFY:
  476. switch (((LPNMHDR)lParam)->code)
  477. {
  478. case NM_NCHITTEST:
  479. {
  480. NMMOUSE *pnm = (LPNMMOUSE)lParam;
  481. if (_hwnd == pnm->hdr.hwndFrom)
  482. {
  483. if (pnm->dwHitInfo == RBHT_CLIENT || pnm->dwItemSpec == -1)
  484. {
  485. if (plres)
  486. *plres = HTTRANSPARENT;
  487. }
  488. return TRUE;
  489. }
  490. }
  491. break;
  492. case RBN_MINMAX:
  493. *plres = SHRestricted(REST_NOMOVINGBAND);
  494. return TRUE;
  495. }
  496. break;
  497. }
  498. IWinEventHandler *pweh;
  499. if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IWinEventHandler, &pweh))))
  500. {
  501. HRESULT hr = pweh->OnWinEvent(hwnd, uMsg, wParam, lParam, plres);
  502. pweh->Release();
  503. return SUCCEEDED(hr);
  504. }
  505. ASSERT(0); // we know we support IWinEventHandler
  506. return FALSE;
  507. }
  508. void CTrayBandSite::_BroadcastExec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  509. {
  510. // Broadcast an Exec to all child bands
  511. DWORD dwBandID;
  512. UINT uBand = 0;
  513. while (SUCCEEDED(EnumBands(uBand, &dwBandID)))
  514. {
  515. IOleCommandTarget* pct;
  516. if (SUCCEEDED(GetBandObject(dwBandID, IID_PPV_ARG(IOleCommandTarget, &pct))))
  517. {
  518. pct->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  519. pct->Release();
  520. }
  521. uBand++;
  522. }
  523. }
  524. void BandSite_HandleDelayBootStuff(IUnknown* punk)
  525. {
  526. if (punk)
  527. {
  528. CTrayBandSite* pbs = IUnknownToCTrayBandSite(punk);
  529. pbs->_fDelayBootStuffHandled = TRUE;
  530. pbs->_BroadcastExec(&CGID_DeskBand, DBID_FINISHINIT, 0, NULL, NULL);
  531. }
  532. }
  533. // returns true or false whether it handled it
  534. BOOL BandSite_HandleMessage(IUnknown *punk, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
  535. {
  536. if (punk)
  537. {
  538. CTrayBandSite* pbs = IUnknownToCTrayBandSite(punk);
  539. return pbs->HandleMessage(hwnd, uMsg, wParam, lParam, plres);
  540. }
  541. return FALSE;
  542. }
  543. void BandSite_SetMode(IUnknown *punk, DWORD dwMode)
  544. {
  545. IBandSite* pbs = (IBandSite*)punk;
  546. if (pbs)
  547. {
  548. IDeskBarClient *pdbc;
  549. if (SUCCEEDED(pbs->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pdbc))))
  550. {
  551. pdbc->SetModeDBC(dwMode);
  552. pdbc->Release();
  553. }
  554. }
  555. }
  556. void BandSite_Update(IUnknown *punk)
  557. {
  558. IBandSite* pbs = (IBandSite*)punk;
  559. if (pbs)
  560. {
  561. IOleCommandTarget *pct;
  562. if (SUCCEEDED(pbs->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pct))))
  563. {
  564. pct->Exec(&CGID_DeskBand, DBID_BANDINFOCHANGED, 0, NULL, NULL);
  565. pct->Release();
  566. }
  567. }
  568. }
  569. void BandSite_UIActivateDBC(IUnknown *punk, DWORD dwState)
  570. {
  571. IBandSite* pbs = (IBandSite*)punk;
  572. if (pbs)
  573. {
  574. IDeskBarClient *pdbc;
  575. if (SUCCEEDED(pbs->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pdbc))))
  576. {
  577. pdbc->UIActivateDBC(dwState);
  578. pdbc->Release();
  579. }
  580. }
  581. }
  582. //*** PersistStreamLoad, PersistStreamSave
  583. // NOTES
  584. // we don't insist on finding IPersistStream iface; absence of it is
  585. // assumed to mean there's nothing to init.
  586. HRESULT PersistStreamLoad(IStream *pstm, IUnknown *punk)
  587. {
  588. IPersistStream *pps;
  589. HRESULT hr = punk->QueryInterface(IID_PPV_ARG(IPersistStream, &pps));
  590. if (SUCCEEDED(hr))
  591. {
  592. hr = pps->Load(pstm);
  593. pps->Release();
  594. }
  595. else
  596. hr = S_OK; // n.b. S_OK not hr (don't insist on IID_IPS)
  597. return hr;
  598. }
  599. HRESULT PersistStreamSave(IStream *pstm, BOOL fClearDirty, IUnknown *punk)
  600. {
  601. HRESULT hr = E_FAIL;
  602. if (punk)
  603. {
  604. hr = S_OK;// n.b. S_OK not hr (don't insist on IID_IPS)
  605. IPersistStream *pps;
  606. if (SUCCEEDED(punk->QueryInterface(IID_PPV_ARG(IPersistStream, &pps))))
  607. {
  608. hr = pps->Save(pstm, fClearDirty);
  609. pps->Release();
  610. }
  611. }
  612. return hr;
  613. }
  614. HRESULT IUnknown_SimulateDrop(IUnknown* punk, IDataObject* pdtobj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
  615. {
  616. HRESULT hr = E_FAIL;
  617. if (punk)
  618. {
  619. IDropTarget* pdt;
  620. hr = punk->QueryInterface(IID_PPV_ARG(IDropTarget, &pdt));
  621. if (SUCCEEDED(hr))
  622. {
  623. hr = pdt->DragEnter(pdtobj, grfKeyState, pt, pdwEffect);
  624. if (*pdwEffect)
  625. {
  626. hr = pdt->Drop(pdtobj, grfKeyState, pt, pdwEffect);
  627. }
  628. else
  629. {
  630. pdt->DragLeave();
  631. }
  632. pdt->Release();
  633. }
  634. }
  635. return hr;
  636. }
  637. LRESULT BandSite_OnMarshallBS(WPARAM wParam, LPARAM lParam)
  638. {
  639. GUID *riid = (GUID *) wParam;
  640. IStream *pstm = NULL;
  641. // paired w/ matching Unmarshal in shdocvw (TM_MARSHALBS)
  642. HRESULT hr = CoMarshalInterThreadInterfaceInStream(*riid, c_tray._ptbs, &pstm);
  643. ASSERT(SUCCEEDED(hr));
  644. return (LRESULT) pstm;
  645. }
  646. IStream *GetDesktopViewStream(DWORD grfMode, LPCTSTR pszName)
  647. {
  648. HKEY hkStreams;
  649. ASSERT(g_hkeyExplorer);
  650. if (RegCreateKey(g_hkeyExplorer, TEXT("Streams"), &hkStreams) == ERROR_SUCCESS)
  651. {
  652. IStream *pstm = OpenRegStream(hkStreams, TEXT("Desktop"), pszName, grfMode);
  653. RegCloseKey(hkStreams);
  654. return pstm;
  655. }
  656. return NULL;
  657. }
  658. BOOL Reg_GetString(HKEY hkey, LPCTSTR pszSubKey, LPCTSTR pszValue, LPTSTR psz, DWORD cb)
  659. {
  660. BOOL fRet = FALSE;
  661. if (!g_fCleanBoot)
  662. {
  663. fRet = ERROR_SUCCESS == SHGetValue(hkey, pszSubKey, pszValue, NULL, psz, &cb);
  664. }
  665. return fRet;
  666. }
  667. void BandSite_Load()
  668. {
  669. CTrayBandSite* ptbs = IUnknownToCTrayBandSite(c_tray._ptbs);
  670. HRESULT hr = E_FAIL;
  671. // 1st, try the WinXP presisted state
  672. IStream *pstm = GetDesktopViewStream(STGM_READ, c_szTaskbarWinXP);
  673. if (pstm)
  674. {
  675. hr = PersistStreamLoad(pstm, (IBandSite*)ptbs);
  676. pstm->Release();
  677. }
  678. if (FAILED(hr))
  679. {
  680. BandSite_RemoveAllBands((IBandSite*)ptbs);
  681. // 2nd, try the Win2K persisted state
  682. IStream *pstm = GetDesktopViewStream(STGM_READ, c_szTaskbar);
  683. if (pstm)
  684. {
  685. hr = PersistStreamLoad(pstm, (IBandSite*)ptbs);
  686. pstm->Release();
  687. }
  688. // 3rd, if there is none (or if version mismatch or other failure),
  689. // try settings from setup
  690. if (FAILED(hr))
  691. {
  692. BandSite_RemoveAllBands((IBandSite*)ptbs);
  693. LPTSTR pszValue;
  694. if (IsOS(OS_PERSONAL) || IsOS(OS_PROFESSIONAL) || SHRestricted(REST_CLASSICSHELL))
  695. {
  696. // use the no-quick-launch stream
  697. pszValue = TEXT("Default Taskbar (Personal)");
  698. }
  699. else
  700. {
  701. pszValue = TEXT("Default Taskbar");
  702. }
  703. // n.b. HKLM not HKCU
  704. // like GetDesktopViewStream but for HKLM
  705. pstm = OpenRegStream(HKEY_LOCAL_MACHINE,
  706. REGSTR_PATH_EXPLORER TEXT("\\Streams\\Desktop"),
  707. pszValue, STGM_READ);
  708. if (pstm)
  709. {
  710. hr = PersistStreamLoad(pstm, (IBandSite *)ptbs);
  711. pstm->Release();
  712. }
  713. }
  714. }
  715. // o.w., throw up our hands and force some hard-coded defaults
  716. // this is needed for a) unexpected failures; b) debug bootstrap;
  717. int iCount = 0;
  718. DWORD dwBandID;
  719. if (FAILED(hr) || FAILED(BandSite_FindBand(ptbs, CLSID_TaskBand, CLSID_NULL, NULL, &iCount, &dwBandID)))
  720. {
  721. //
  722. // note that for the CheckBands case, we're assuming that
  723. // a) AddBands adds only the missing guys (for now there's
  724. // only 1 [TaskBand] so we're ok); and b) AddBands doesn't
  725. // create dups if only some are missing (again for now there's
  726. // only 1 so no pblm)
  727. ptbs->_AddRequiredBands();
  728. }
  729. hr = BandSite_FindBand(ptbs, CLSID_TaskBand, CLSID_NULL, NULL, &iCount, &dwBandID);
  730. while ((iCount > 1) && SUCCEEDED(hr))
  731. {
  732. ptbs->RemoveBand(dwBandID);
  733. hr = BandSite_FindBand(ptbs, CLSID_TaskBand, CLSID_NULL, NULL, &iCount, &dwBandID);
  734. }
  735. // And one more: this is needed for the TipBand deskband for the TabletPC.
  736. iCount = 0;
  737. if (FAILED(hr) || FAILED(BandSite_FindBand(ptbs, CLSID_TipBand, CLSID_NULL, NULL, &iCount, &dwBandID)))
  738. {
  739. IDeskBand* pdb;
  740. HRESULT hr = CoCreateInstance(CLSID_TipBand, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IDeskBand, &pdb));
  741. if (SUCCEEDED(hr))
  742. {
  743. hr = ptbs->AddBand(pdb);
  744. pdb->Release();
  745. }
  746. }
  747. hr = BandSite_FindBand(ptbs, CLSID_TipBand, CLSID_NULL, NULL, &iCount, &dwBandID);
  748. while ((iCount > 1) && SUCCEEDED(hr))
  749. {
  750. ptbs->RemoveBand(dwBandID);
  751. hr = BandSite_FindBand(ptbs, CLSID_TipBand, CLSID_NULL, NULL, &iCount, &dwBandID);
  752. }
  753. ptbs->SetLoaded(TRUE);
  754. }
  755. HRESULT CTrayBandSiteService_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk)
  756. {
  757. if (punkOuter)
  758. return CLASS_E_NOAGGREGATION;
  759. if (c_tray._ptbs)
  760. {
  761. *ppunk = c_tray._ptbs;
  762. c_tray._ptbs->AddRef();
  763. return S_OK;
  764. }
  765. return E_OUTOFMEMORY;
  766. }