Leaked source code of windows server 2003
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.

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