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.

3371 lines
96 KiB

  1. #include "priv.h"
  2. #include <varutil.h>
  3. #include "sccls.h"
  4. #include "iface.h"
  5. #include "itbar.h"
  6. #include "itbdrop.h"
  7. #include "bands.h"
  8. #include "isfband.h"
  9. #include "menubar.h"
  10. #include "resource.h"
  11. #include "menuisf.h"
  12. #include "dpastuff.h"
  13. #include "shlwapi.h"
  14. #include "cobjsafe.h"
  15. #include <iimgctx.h>
  16. #include "uemapp.h"
  17. #include "mnfolder.h"
  18. #include "channel.h"
  19. #include "browmenu.h"
  20. #define DM_VERBOSE 0 // misc verbose traces
  21. #define DM_PERSIST 0
  22. #define TF_BANDDD TF_BAND
  23. #define DM_RENAME 0
  24. #define DM_MISC 0 // miscellany
  25. #define SZ_PROPERTIESA "properties"
  26. #define SZ_PROPERTIES TEXT(SZ_PROPERTIESA)
  27. #define SZ_REGKEY_ADVFOLDER TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced")
  28. // {F47162A0-C18F-11d0-A3A5-00C04FD706EC}
  29. static const GUID TOID_ExtractImage = { 0xf47162a0, 0xc18f, 0x11d0, { 0xa3, 0xa5, 0x0, 0xc0, 0x4f, 0xd7, 0x6, 0xec } };
  30. #define SUPERCLASS CToolBand
  31. HRESULT FakeGetUIObjectOf( IShellFolder *psf, LPCITEMIDLIST pidl, UINT * prgfFlags, REFIID riid, void **ppvObj );
  32. extern UINT g_idFSNotify;
  33. HRESULT CExtractImageTask_Create( CLogoBase *plb,
  34. LPEXTRACTIMAGE pExtract,
  35. LPCWSTR pszCache,
  36. DWORD dwItem,
  37. int iIcon,
  38. DWORD dwFlags,
  39. LPRUNNABLETASK * ppTask );
  40. class CExtractImageTask : public IRunnableTask
  41. {
  42. public:
  43. STDMETHOD ( QueryInterface ) ( REFIID riid, void **ppvObj );
  44. STDMETHOD_( ULONG, AddRef ) ();
  45. STDMETHOD_( ULONG, Release ) ();
  46. STDMETHOD (Run)( void );
  47. STDMETHOD (Kill)( BOOL fWait );
  48. STDMETHOD (Suspend)( );
  49. STDMETHOD (Resume)( );
  50. STDMETHOD_( ULONG, IsRunning )( void );
  51. protected:
  52. CExtractImageTask( HRESULT * pHr,
  53. CLogoBase *plb,
  54. IExtractImage * pImage,
  55. LPCWSTR pszCache,
  56. DWORD dwItem,
  57. int iIcon,
  58. DWORD dwFlags );
  59. ~CExtractImageTask();
  60. HRESULT InternalResume();
  61. friend HRESULT CExtractImageTask_Create( CLogoBase* plb,
  62. LPEXTRACTIMAGE pExtract,
  63. LPCWSTR pszCache,
  64. DWORD dwItem,
  65. int iIcon,
  66. DWORD dwFlags,
  67. LPRUNNABLETASK * ppTask );
  68. LONG m_cRef;
  69. LONG m_lState;
  70. LPEXTRACTIMAGE m_pExtract;
  71. LPRUNNABLETASK m_pTask;
  72. WCHAR m_szPath[MAX_PATH];
  73. DWORD m_dwFlags;
  74. DWORD m_dwItem;
  75. CLogoBase* m_plb;
  76. HBITMAP m_hBmp;
  77. int m_iIcon;
  78. };
  79. //=================================================================
  80. // Implementation of CISFBand
  81. //=================================================================
  82. CISFBand::CISFBand() : CToolbarBand()
  83. {
  84. _fCanFocus = TRUE;
  85. _eUemLog = UEMIND_NIL;
  86. _dwPriv = -1;
  87. _fHasOrder = TRUE; // ISFBand always has an order...
  88. _fAllowDropdown = BOOLIFY(SHRegGetBoolUSValue(SZ_REGKEY_ADVFOLDER, TEXT("CascadeFolderBands"),
  89. FALSE,
  90. FALSE));
  91. // Should we enable logging of arbirary events?
  92. // _pguidUEMGroup = &UEMIID_SHELL;
  93. ASSERT(_pguidUEMGroup == NULL);
  94. // Assert that this class is ZERO INITed.
  95. ASSERT(!_pbp);
  96. ASSERT(FALSE == _fCreatedBandProxy);
  97. }
  98. CISFBand::~CISFBand()
  99. {
  100. if(_pbp && _fCreatedBandProxy)
  101. _pbp->SetSite(NULL);
  102. ATOMICRELEASE(_pbp);
  103. }
  104. HRESULT CISFBand_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  105. {
  106. // aggregation checking is handled in class factory
  107. HRESULT hres;
  108. CISFBand* pObj;
  109. hres = E_OUTOFMEMORY;
  110. pObj = new CISFBand();
  111. if (pObj)
  112. {
  113. *ppunk = SAFECAST(pObj, IShellFolderBand*);
  114. hres = S_OK;
  115. }
  116. return hres;
  117. }
  118. /*----------------------------------------------------------
  119. Purpose: See CISFBand::Init for an explanation on the parameters.
  120. */
  121. CISFBand* CISFBand_CreateEx(IShellFolder* psf, LPCITEMIDLIST pidl)
  122. {
  123. CISFBand * p = NULL;
  124. if (psf || pidl)
  125. {
  126. p = new CISFBand();
  127. if (p)
  128. {
  129. IShellFolderBand * psfband = SAFECAST(p, IShellFolderBand *);
  130. if (psfband && FAILED(psfband->InitializeSFB(psf, pidl)))
  131. {
  132. delete p;
  133. p = NULL;
  134. }
  135. }
  136. }
  137. return p;
  138. }
  139. #ifdef DEBUG
  140. #define _AddRef(psz) { ++_cRef; TraceMsg(TF_SHDREF, "CDocObjectView(%x)::QI(%s) is AddRefing _cRef=%d", this, psz, _cRef); }
  141. #else
  142. #define _AddRef(psz) ++_cRef
  143. #endif
  144. HRESULT CISFBand::QueryInterface(REFIID riid, void **ppvObj)
  145. {
  146. static const QITAB qit[] = {
  147. QITABENT(CISFBand, IShellFolderBand),
  148. QITABENT(CISFBand, IFolderBandPriv),
  149. { 0 },
  150. };
  151. HRESULT hres = QISearch(this, qit, riid, ppvObj);
  152. if (FAILED(hres))
  153. hres = CToolBand::QueryInterface(riid, ppvObj);
  154. if (FAILED(hres))
  155. hres = CSFToolbar::QueryInterface(riid, ppvObj);
  156. if (S_OK != hres)
  157. {
  158. // HACKHACK: this is yucko!
  159. if (IsEqualIID(riid, CLSID_ISFBand))
  160. {
  161. *ppvObj = (void*)this;
  162. _AddRef(TEXT("CLSID_ISFBand"));
  163. return S_OK;
  164. }
  165. }
  166. return hres;
  167. }
  168. #if 0
  169. LPITEMIDLIST PidlFromFolderAndSubPath(int iFolder, TCHAR *pszSubPath)
  170. {
  171. LPITEMIDLIST pidl = NULL;
  172. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, iFolder, &pidl))) {
  173. if (pszSubPath) {
  174. TCHAR szPath[MAX_PATH];
  175. SHGetPathFromIDList(pidl, szPath);
  176. PathCombine(szPath, szPath, pszSubPath);
  177. ILFree(pidl);
  178. pidl = ILCreateFromPath(szPath);
  179. }
  180. }
  181. return pidl;
  182. }
  183. #endif
  184. //*** ILIsParentCSIDL -- like ILIsParent, but accepts a CSIDL_* for pidl1
  185. // NOTES
  186. // TODO move to shlwapi (if/when idlist.c moves there)?
  187. //
  188. STDAPI_(BOOL) ILIsParentCSIDL(int csidl1, LPCITEMIDLIST pidl2, BOOL fImmediate)
  189. {
  190. LPITEMIDLIST pidlSpec;
  191. BOOL fRet = FALSE;
  192. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, csidl1, &pidlSpec))) {
  193. fRet = ILIsParent(pidlSpec, pidl2, fImmediate);
  194. ILFree(pidlSpec);
  195. }
  196. return fRet;
  197. }
  198. /*----------------------------------------------------------
  199. Purpose: IShellFolderBand::InitializeSFB
  200. - supply IShellFolder with no PIDL if you want to view some
  201. ISF (either already instantiated from the filesystem or
  202. some non-filesystem ISF) that you do NOT want to receive
  203. notifies from (either from SHChangeNotify nor from
  204. IShellChangeNotify)
  205. - supply a PIDL with no IShellFolder for a full-blown band
  206. looking at a shell namespace (rooted on desktop) item.
  207. */
  208. HRESULT CISFBand::InitializeSFB(IShellFolder *psf, LPCITEMIDLIST pidl)
  209. {
  210. HRESULT hres = S_OK;
  211. // Did they try to add the Recycle Bin? If so we need to reject it
  212. // for consistance reasons. We also reject the Temp. Internet Files
  213. // for security reasons.
  214. if (pidl && (ILIsParentCSIDL(CSIDL_BITBUCKET, pidl, FALSE) ||
  215. ILIsParentCSIDL(CSIDL_INTERNET_CACHE, pidl, FALSE)))
  216. {
  217. // this will eventually show up as IDS_CANTISFBAND
  218. TraceMsg(DM_TRACE, "cib.isfb: recycle => E_INVALIDARG");
  219. hres = E_INVALIDARG;
  220. }
  221. if (SUCCEEDED(hres))
  222. hres = CSFToolbar::SetShellFolder(psf, pidl);
  223. if (SUCCEEDED(hres))
  224. _AfterLoad();
  225. return hres;
  226. }
  227. /*----------------------------------------------------------
  228. Purpose: IShellFolderBand::SetBandInfoSFB
  229. */
  230. HRESULT CISFBand::SetBandInfoSFB(BANDINFOSFB * pbi)
  231. {
  232. ASSERT(pbi);
  233. if (!pbi)
  234. return E_POINTER;
  235. if ((pbi->dwMask & ISFB_MASK_INVALID) ||
  236. (pbi->dwMask & ISFB_MASK_VIEWMODE) && (pbi->wViewMode & ~3))
  237. return E_INVALIDARG;
  238. // We don't handle ISFB_MASK_SHELLFOLDER and ISFB_MASK_IDLIST
  239. // in Set because there's a lot of work to resync pidl, psf, and
  240. // notifcations in the toolbar. If somebody wants to do it,
  241. // more power to ya. :)
  242. if (pbi->dwMask & (ISFB_MASK_SHELLFOLDER | ISFB_MASK_IDLIST))
  243. return E_INVALIDARG;
  244. if (pbi->dwMask & ISFB_MASK_STATE)
  245. {
  246. if (pbi->dwStateMask & ISFB_STATE_DEBOSSED)
  247. _fDebossed = BOOLIFY(pbi->dwState & ISFB_STATE_DEBOSSED);
  248. if (pbi->dwStateMask & ISFB_STATE_ALLOWRENAME)
  249. _fAllowRename = BOOLIFY(pbi->dwState & ISFB_STATE_ALLOWRENAME);
  250. if (pbi->dwStateMask & ISFB_STATE_NOSHOWTEXT)
  251. _fNoShowText = BOOLIFY(pbi->dwState & ISFB_STATE_NOSHOWTEXT);
  252. if (pbi->dwStateMask & ISFB_STATE_CHANNELBAR)
  253. _fChannels = BOOLIFY(pbi->dwState & ISFB_STATE_CHANNELBAR);
  254. /* ISFB_STATE_NOTITLE: removed 970619, use cbs::SetBandState */
  255. if (pbi->dwStateMask & ISFB_STATE_QLINKSMODE)
  256. _fLinksMode = BOOLIFY(pbi->dwState & ISFB_STATE_QLINKSMODE);
  257. if (pbi->dwStateMask & ISFB_STATE_FULLOPEN)
  258. _fFullOpen = BOOLIFY(pbi->dwState & ISFB_STATE_FULLOPEN);
  259. if (pbi->dwStateMask & ISFB_STATE_NONAMESORT)
  260. _fNoNameSort = BOOLIFY(pbi->dwState & ISFB_STATE_NONAMESORT);
  261. if (pbi->dwStateMask & ISFB_STATE_BTNMINSIZE)
  262. _fBtnMinSize = BOOLIFY(pbi->dwState & ISFB_STATE_BTNMINSIZE);
  263. }
  264. if (pbi->dwMask & ISFB_MASK_BKCOLOR)
  265. {
  266. _crBkgnd = pbi->crBkgnd;
  267. _fHaveBkColor = TRUE;
  268. if (EVAL(_hwndTB))
  269. SHSetWindowBits(_hwndTB, GWL_STYLE, TBSTYLE_CUSTOMERASE, TBSTYLE_CUSTOMERASE);
  270. ASSERT(_hwnd);
  271. if (_hwndPager)
  272. {
  273. TraceMsg(TF_BAND, "cib.sbisfb: Pager_SetBkColor(_hwnd=%x crBkgnd=%x)", _hwnd, _crBkgnd);
  274. Pager_SetBkColor(_hwnd, _crBkgnd);
  275. }
  276. }
  277. // BUGBUG (kkahl): We don't support changing these once TB is created
  278. if (pbi->dwMask & ISFB_MASK_COLORS)
  279. {
  280. _crBtnLt = pbi->crBtnLt;
  281. _crBtnDk = pbi->crBtnDk;
  282. _fHaveColors = TRUE;
  283. }
  284. if (pbi->dwMask & ISFB_MASK_VIEWMODE)
  285. {
  286. _uIconSize = (pbi->wViewMode & 3); // stored in a 2-bit field currently...
  287. // only force no recalc if one of the recalcable fields was set
  288. _fNoRecalcDefaults = TRUE;
  289. }
  290. // If the bandsite queried us before, let it know the info may have changed
  291. if (_fInitialized)
  292. _BandInfoChanged();
  293. return S_OK;
  294. }
  295. /*----------------------------------------------------------
  296. Purpose: IShellFolderBand::GetBandInfoSFB
  297. */
  298. HRESULT CISFBand::GetBandInfoSFB(BANDINFOSFB * pbi)
  299. {
  300. ASSERT(pbi);
  301. if (!pbi)
  302. return E_POINTER;
  303. if (pbi->dwMask & ISFB_MASK_STATE)
  304. {
  305. pbi->dwState = 0;
  306. pbi->dwStateMask = ISFB_STATE_ALL;
  307. if (_fDebossed)
  308. pbi->dwState |= ISFB_STATE_DEBOSSED;
  309. if (_fAllowRename)
  310. pbi->dwState |= ISFB_STATE_ALLOWRENAME;
  311. if (_fNoShowText)
  312. pbi->dwState |= ISFB_STATE_NOSHOWTEXT;
  313. if (_fLinksMode)
  314. pbi->dwState |= ISFB_STATE_QLINKSMODE;
  315. if (_fFullOpen)
  316. pbi->dwState |= ISFB_STATE_FULLOPEN;
  317. if (_fNoNameSort)
  318. pbi->dwState |= ISFB_STATE_NONAMESORT;
  319. if (_fBtnMinSize)
  320. pbi->dwState |= ISFB_STATE_BTNMINSIZE;
  321. }
  322. if (pbi->dwMask & ISFB_MASK_BKCOLOR)
  323. {
  324. pbi->crBkgnd = (_fHaveBkColor) ? _crBkgnd : CLR_DEFAULT;
  325. }
  326. if (pbi->dwMask & ISFB_MASK_COLORS)
  327. {
  328. if (_fHaveColors)
  329. {
  330. pbi->crBtnLt = _crBtnLt;
  331. pbi->crBtnDk = _crBtnDk;
  332. }
  333. else
  334. {
  335. pbi->crBtnLt = CLR_DEFAULT;
  336. pbi->crBtnDk = CLR_DEFAULT;
  337. }
  338. }
  339. if (pbi->dwMask & ISFB_MASK_VIEWMODE)
  340. {
  341. pbi->wViewMode = _uIconSize;
  342. }
  343. if (pbi->dwMask & ISFB_MASK_SHELLFOLDER)
  344. {
  345. pbi->psf = _psf;
  346. if (pbi->psf)
  347. pbi->psf->AddRef();
  348. }
  349. if (pbi->dwMask & ISFB_MASK_IDLIST)
  350. {
  351. if (_pidl)
  352. pbi->pidl = ILClone(_pidl);
  353. else
  354. pbi->pidl = NULL;
  355. }
  356. return S_OK;
  357. }
  358. // *** IInputObject methods ***
  359. HRESULT CISFBand::TranslateAcceleratorIO(LPMSG lpMsg)
  360. {
  361. if (SendMessage(_hwnd, TB_TRANSLATEACCELERATOR, 0, (LPARAM)lpMsg))
  362. return S_OK;
  363. return SUPERCLASS::TranslateAcceleratorIO(lpMsg);
  364. }
  365. void CISFBand::_SetCacheMenuPopup(IMenuPopup* pmp)
  366. {
  367. if (!SHIsSameObject(pmp, _pmpCache)) {
  368. _ReleaseMenuPopup(&_pmpCache);
  369. _pmpCache = pmp;
  370. if (_pmpCache)
  371. _pmpCache->AddRef();
  372. }
  373. }
  374. void CISFBand::_ReleaseMenuPopup(IMenuPopup** ppmp)
  375. {
  376. IUnknown_SetSite(*ppmp, NULL);
  377. ATOMICRELEASE(*ppmp);
  378. }
  379. /*----------------------------------------------------------
  380. Purpose: Releases the held menu popup.
  381. */
  382. void CISFBand::_ReleaseMenu()
  383. {
  384. if (!SHIsSameObject(_pmp, _pmpCache)) {
  385. TraceMsg(TF_MENUBAND, "Releasing pmp %#lx", _pmp);
  386. _ReleaseMenuPopup(&_pmp);
  387. } else
  388. ATOMICRELEASE(_pmp);
  389. }
  390. //***
  391. // ENTRY/EXIT
  392. // S_OK desktop browser
  393. // S_FALSE other browser (explorer, OC, etc.)
  394. // E_xxx not a browser at all (e.g. band asking tray)
  395. HRESULT IsDesktopBrowser(IUnknown *punkSite)
  396. {
  397. HRESULT hr;
  398. IServiceProvider *psp;
  399. IUnknown *punk;
  400. hr = E_FAIL;
  401. if (SUCCEEDED(IUnknown_QueryService(punkSite, SID_STopLevelBrowser, IID_IServiceProvider, (void**)&psp))) {
  402. hr = S_FALSE;
  403. if (SUCCEEDED(psp->QueryInterface(SID_SShellDesktop, (void**)&punk))) {
  404. hr = S_OK;
  405. punk->Release();
  406. }
  407. psp->Release();
  408. }
  409. TraceMsg(DM_VERBOSE, "idb: ret hrDesk=%x (0=dt 1=sh e=!brow)", hr);
  410. return hr;
  411. }
  412. /*----------------------------------------------------------
  413. Purpose: IDockingWindow::SetSite method.
  414. */
  415. HRESULT CISFBand::SetSite(IUnknown* punkSite)
  416. {
  417. _ReleaseMenu();
  418. SUPERCLASS::SetSite(punkSite);
  419. if (_punkSite)
  420. {
  421. if (!_hwndTB)
  422. _CreateToolbar(_hwndParent);
  423. IUnknown_SetOwner(_psf, SAFECAST(this, IDeskBand*));
  424. _Initialize(); // BUGBUG always or just on 1st SetSite?
  425. }
  426. else
  427. IUnknown_SetOwner(_psf, NULL);
  428. // BUGBUG: the below is bogus - no need to throw away and recreate.
  429. // First destroy the band proxy
  430. // Call SetSite(NULL) only if you own
  431. // if not, it's the parent from whom you got it via QS who will call SetSite(NULL)
  432. if(_pbp && _fCreatedBandProxy)
  433. _pbp->SetSite(NULL);
  434. ATOMICRELEASE(_pbp);
  435. _fCreatedBandProxy = FALSE;
  436. // Need a bandproxy
  437. QueryService_SID_IBandProxy(punkSite, IID_IBandProxy, &_pbp, NULL);
  438. if(!_pbp)
  439. {
  440. // We need to create it ourselves since our parent couldn't help
  441. ASSERT(FALSE == _fCreatedBandProxy);
  442. HRESULT hres;
  443. hres = CreateIBandProxyAndSetSite(punkSite, IID_IBandProxy, &_pbp, NULL);
  444. if(_pbp)
  445. {
  446. ASSERT(S_OK == hres);
  447. _fCreatedBandProxy = TRUE;
  448. }
  449. }
  450. ASSERT(_pbp);
  451. return S_OK;
  452. }
  453. void CISFBand::_Initialize()
  454. {
  455. _fDesktop = (IsDesktopBrowser(_punkSite) == S_OK);
  456. return;
  457. }
  458. /*----------------------------------------------------------
  459. Purpose: IDockingWindow::CloseDW method.
  460. */
  461. HRESULT CISFBand::CloseDW(DWORD dw)
  462. {
  463. _fClosing = TRUE;
  464. // close down the task scheduler ...
  465. if ( _pTaskScheduler )
  466. ATOMICRELEASE( _pTaskScheduler );
  467. _UnregisterToolbar();
  468. EmptyToolbar();
  469. IUnknown_SetOwner(_psf, NULL);
  470. _SetCacheMenuPopup(NULL);
  471. // should get freed in EmptyToolbar();
  472. ASSERT(!_hdpa);
  473. return SUPERCLASS::CloseDW(dw);
  474. }
  475. /*----------------------------------------------------------
  476. Purpose: IDockingWindow::ShowDW method
  477. */
  478. HRESULT CISFBand::ShowDW(BOOL fShow)
  479. {
  480. HRESULT hres = S_OK;
  481. SUPERCLASS::ShowDW(fShow);
  482. if (fShow)
  483. {
  484. _fShow = TRUE;
  485. if (_fDirty)
  486. {
  487. _FillToolbar();
  488. }
  489. if (!_fDelayInit)
  490. {
  491. _RegisterToolbar();
  492. }
  493. }
  494. else
  495. {
  496. _fShow = FALSE;
  497. }
  498. return hres;
  499. }
  500. void CISFBand::_StopDelayPainting()
  501. {
  502. if (_fDelayPainting) {
  503. _fDelayPainting = FALSE;
  504. // May be called by background thread
  505. // Use PostMessage instead of SendMessage to avoid deadlock
  506. PostMessage(_hwndTB, WM_SETREDRAW, TRUE, 0);
  507. if (_hwndPager)
  508. PostMessage(_hwnd, PGM_RECALCSIZE, 0L, 0L);
  509. }
  510. }
  511. HWND CISFBand::_CreatePager(HWND hwndParent)
  512. {
  513. // don't create a pager for isfbands
  514. return hwndParent;
  515. }
  516. void CISFBand::_CreateToolbar(HWND hwndParent)
  517. {
  518. if (_fHaveBkColor)
  519. _dwStyle |= TBSTYLE_CUSTOMERASE;
  520. CSFToolbar::_CreateToolbar(hwndParent);
  521. if ( _fHaveBkColor )
  522. ToolBar_SetInsertMarkColor(_hwndTB, GetSysColor( COLOR_BTNFACE ));
  523. ASSERT(_hwndTB);
  524. SendMessage(_hwndTB, TB_SETEXTENDEDSTYLE, TBSTYLE_EX_DRAWDDARROWS, TBSTYLE_EX_DRAWDDARROWS);
  525. if(_fChannels)
  526. {
  527. SHSetWindowBits(_hwndTB, GWL_EXSTYLE, dwExStyleRTLMirrorWnd, 0);
  528. }
  529. _hwnd = _hwndPager ? _hwndPager : _hwndTB;
  530. if (_fHaveColors)
  531. {
  532. COLORSCHEME cs;
  533. cs.dwSize = SIZEOF(cs);
  534. cs.clrBtnHighlight = _crBtnLt;
  535. cs.clrBtnShadow = _crBtnDk;
  536. SendMessage(_hwndTB, TB_SETCOLORSCHEME, 0, (LPARAM) &cs);
  537. }
  538. }
  539. int CISFBand::_GetBitmap(int iCommandID, PIBDATA pibdata, BOOL fUseCache)
  540. {
  541. int iBitmap;
  542. if ( _uIconSize == ISFBVIEWMODE_LOGOS )
  543. {
  544. LPRUNNABLETASK pTask = NULL;
  545. DWORD dwPriority = 0;
  546. // fetch the logo instead...
  547. ASSERT(!_fDelayPainting);
  548. // Warning - cannot hold ptask in a member variable - it will be a circular reference
  549. iBitmap = GetLogoIndex( iCommandID, pibdata->GetPidl(), &pTask, &dwPriority, NULL );
  550. if (pTask)
  551. {
  552. AddTaskToQueue(pTask, dwPriority, (DWORD)iCommandID);
  553. ATOMICRELEASE(pTask);
  554. }
  555. }
  556. else
  557. iBitmap = CSFToolbar::_GetBitmap(iCommandID, pibdata, fUseCache);
  558. return iBitmap;
  559. }
  560. void CISFBand::_SetDirty(BOOL fDirty)
  561. {
  562. CSFToolbar::_SetDirty(fDirty);
  563. if (fDirty)
  564. IUnknown_Exec(_punkSite, &CGID_PrivCITCommands, CITIDM_SET_DIRTYBIT, TRUE, NULL, NULL);
  565. }
  566. BOOL CISFBand::_UpdateIconSize(UINT uIconSize, BOOL fUpdateButtons)
  567. {
  568. BOOL fChanged = (_uIconSize != uIconSize);
  569. _uIconSize = uIconSize;
  570. HIMAGELIST himl = NULL;
  571. if ( uIconSize == ISFBVIEWMODE_LOGOS )
  572. {
  573. if ( SUCCEEDED( InitLogoView()))
  574. {
  575. himl = GetLogoHIML();
  576. }
  577. if ( himl )
  578. {
  579. SendMessage(_hwndTB, TB_SETIMAGELIST, 0, (LPARAM)himl);
  580. _UpdateButtons();
  581. }
  582. }
  583. if ( !himl )
  584. fChanged |= CSFToolbar::_UpdateIconSize(uIconSize,fUpdateButtons);
  585. return fChanged;
  586. }
  587. void CISFBand::_UpdateVerticalMode(BOOL fVertical)
  588. {
  589. _fVertical = (fVertical != 0);
  590. TraceMsg(TF_BAND, "ISFBand::_UpdateVerticalMode going %hs", _fVertical ? "VERTICAL" : "HORIZONTAL");
  591. ASSERT(_hwnd);
  592. if (_hwndPager) {
  593. SHSetWindowBits(_hwnd, GWL_STYLE, PGS_HORZ|PGS_VERT,
  594. _fVertical ? PGS_VERT : PGS_HORZ);
  595. }
  596. if (_hwndTB)
  597. {
  598. SHSetWindowBits(_hwndTB, GWL_STYLE, TBSTYLE_WRAPABLE | CCS_VERT,
  599. TBSTYLE_WRAPABLE | (_fVertical ? CCS_VERT : 0));
  600. }
  601. }
  602. HRESULT IUnknown_QueryBand(IUnknown *punk, DWORD dwBandID, IDeskBand** ppstb, DWORD* pdwState, LPWSTR pszName, int cchName)
  603. {
  604. HRESULT hr;
  605. IBandSite *pbs;
  606. hr = punk->QueryInterface(IID_IBandSite, (void**)&pbs);
  607. if (SUCCEEDED(hr)) {
  608. hr = pbs->QueryBand(dwBandID, ppstb, pdwState, pszName, cchName);
  609. pbs->Release();
  610. }
  611. return hr;
  612. }
  613. #define CISFBAND_GETBUTTONSIZE() (_hwndTB ? (LONG)SendMessage(_hwndTB, TB_GETBUTTONSIZE, 0, 0L) : MAKELONG(16, 16))
  614. //
  615. // _GetIdealSize
  616. //
  617. // calculates ideal height and width for band and passes back in
  618. // psize, if psize isn't NULL; return value is band's 'ideal length'
  619. // (ideal height if vertical, else ideal width)
  620. //
  621. int CISFBand::_GetIdealSize(PSIZE psize)
  622. {
  623. SIZE size;
  624. LONG lButtonSize = CISFBAND_GETBUTTONSIZE();
  625. RECT rc = {0};
  626. if (_hwndTB)
  627. GetClientRect(_hwndTB, &rc);
  628. if (_fVertical)
  629. {
  630. // set width to be max of toolbar width and toolbar button width
  631. size.cx = max(RECTWIDTH(rc), LOWORD(lButtonSize));
  632. // have toolbar calculate height given that width
  633. SendMessage(_hwndTB, TB_GETIDEALSIZE, TRUE, (LPARAM)&size);
  634. }
  635. else
  636. {
  637. // set height to be max of toolbar width and toolbar button width
  638. size.cy = max(RECTHEIGHT(rc), HIWORD(lButtonSize));
  639. // have toolbar calculate width given that height
  640. SendMessage(_hwndTB, TB_GETIDEALSIZE, FALSE, (LPARAM)&size);
  641. }
  642. // BUGBUG: I'm ripping out this check as it causes nt5 bug #225449 (disappearing chevron).
  643. // _fDirty == TRUE doesn't mean "we're still waiting to call _FillToolbar", it just means
  644. // "we need to persist out this order stream". The bit gets set after a drag-and-drop
  645. // reordering, but we don't call a matching _FillToolbar in that case.
  646. #if 0
  647. if (_fDirty)
  648. {
  649. // until the TB is populated, we get back bogus data from the
  650. // above. so use -1 until we actually have a correct answer.
  651. size.cx = size.cy = -1;
  652. }
  653. #endif
  654. if (psize)
  655. *psize = size;
  656. return _fVertical ? size.cy : size.cx;
  657. }
  658. /*----------------------------------------------------------
  659. Purpose: IDeskBand::GetBandInfo method
  660. */
  661. HRESULT CISFBand::GetBandInfo(DWORD dwBandID, DWORD fViewMode,
  662. DESKBANDINFO* pdbi)
  663. {
  664. HRESULT hr = S_OK;
  665. _dwBandID = dwBandID;
  666. // We don't know the default icon size until GetBandInfo is called.
  667. // After we set the default, we pay attention to the context menu.
  668. //
  669. if (!_fNoRecalcDefaults)
  670. {
  671. _uIconSize = (fViewMode & (DBIF_VIEWMODE_FLOATING |DBIF_VIEWMODE_VERTICAL)) ? ISFBVIEWMODE_LARGEICONS : ISFBVIEWMODE_SMALLICONS;
  672. _fNoRecalcDefaults = TRUE;
  673. }
  674. if (!_fInitialized) {
  675. _fInitialized = TRUE;
  676. _UpdateIconSize(_uIconSize, FALSE);
  677. _UpdateShowText(_fNoShowText);
  678. }
  679. // we treat floating the same as vertical
  680. _UpdateVerticalMode(fViewMode & (DBIF_VIEWMODE_FLOATING |DBIF_VIEWMODE_VERTICAL));
  681. LONG lButtonSize = CISFBAND_GETBUTTONSIZE();
  682. pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT | DBIMF_USECHEVRON;
  683. if (_fDebossed)
  684. pdbi->dwModeFlags |= DBIMF_DEBOSSED;
  685. pdbi->ptMinSize.x = 0;
  686. pdbi->ptMaxSize.y = 32000; // random
  687. pdbi->ptIntegral.y = 1;
  688. pdbi->ptIntegral.x = 1;
  689. if (!_fFullOpen)
  690. _iIdealLength = _GetIdealSize((PSIZE)&pdbi->ptActual);
  691. // CalcMinWidthHeight {
  692. // BUGBUG need pager msg for cx/cy scroll
  693. #define g_cxScrollbar (GetSystemMetrics(SM_CXVSCROLL) * 3 / 4)
  694. #define g_cyScrollbar (GetSystemMetrics(SM_CYVSCROLL) * 3 / 4)
  695. #define CX_TBBUTTON_MAX (16 + CX_FILENAME_AVG) // button + name
  696. #define CY_TBBUTTON_MAX (16) // button
  697. int csBut, csButMin, clBut, clButMin, clScroll;
  698. // set up short/long aliases
  699. if (_fVertical) {
  700. csBut = LOWORD(lButtonSize);
  701. if (_fBtnMinSize)
  702. csButMin = min(csBut, CX_TBBUTTON_MAX);
  703. else
  704. csButMin = 0; // people like to shrink things way down, so let 'em
  705. clBut = HIWORD(lButtonSize);
  706. clButMin = clBut;
  707. //ASSERT(min(clBut, CY_TBBUTTON_MAX) == clButMin); // fails!
  708. clScroll = g_cyScrollbar;
  709. }
  710. else {
  711. csBut = HIWORD(lButtonSize);
  712. csButMin = csBut;
  713. //ASSERT(min(csBut, CY_TBBUTTON_MAX) == csButMin); // fails!
  714. clBut = LOWORD(lButtonSize);
  715. clButMin = min(clBut, CX_TBBUTTON_MAX);
  716. clScroll = g_cxScrollbar;
  717. // nt5:176448: integral for horz
  718. //pdbi->ptIntegral.y = csBut; this is the cause for 287082 and 341592
  719. }
  720. // n.b. virt pdbi->pt.x,y is really phys y,x (i.e. phys long,short)
  721. pdbi->ptMinSize.x = 0;
  722. pdbi->ptMinSize.y = csButMin;
  723. DWORD dwState = BSSF_NOTITLE;
  724. IUnknown_QueryBand(_punkSite, dwBandID, NULL, &dwState, NULL, 0);
  725. if (dwState & BSSF_NOTITLE) { // _fNoTitle
  726. int i, cBut, clTmp;
  727. // cbut= text notext
  728. // horz 1 4
  729. // vert 1 1
  730. cBut = 1;
  731. if (!_fVertical && _fNoShowText) {
  732. // special-case for QLaunch so see several buttons
  733. cBut = 4; // for both QLaunch and arbitrary ISF band
  734. }
  735. pdbi->ptMinSize.x = cBut * clButMin;
  736. if (_hwndPager) {
  737. // tack on extra space for pager arrows
  738. pdbi->ptMinSize.x += 2 * clScroll;
  739. }
  740. i = (int)SendMessage(_hwndTB, TB_BUTTONCOUNT, 0, 0);
  741. if (i <= cBut) {
  742. clTmp = i * clBut;
  743. if (clTmp < pdbi->ptMinSize.x) {
  744. // scrollbars take as much space as button would
  745. // so just do the button
  746. pdbi->ptMinSize.x = clTmp;
  747. }
  748. }
  749. }
  750. // }
  751. #if 0 // BUGBUG don't we need this?
  752. if (_fHaveBkColor) {
  753. pdbi->crBkgnd = _crBkgnd;
  754. pdbi->dwModeFlags |= DBIMF_BKCOLOR;
  755. }
  756. #endif
  757. hr = _GetTitleW(pdbi->wszTitle, ARRAYSIZE(pdbi->wszTitle));
  758. if (FAILED(hr))
  759. {
  760. // we don't support title
  761. #ifdef DEBUG
  762. if (pdbi->dwMask & DBIM_TITLE)
  763. TraceMsg(DM_VERBOSE, "cisfb.gbi: patch ~DBIM_TITLE");
  764. #endif
  765. pdbi->dwMask &= ~DBIM_TITLE;
  766. }
  767. return hr;
  768. }
  769. LRESULT CISFBand::_OnCustomDraw(NMCUSTOMDRAW* pnmcd)
  770. {
  771. NMTBCUSTOMDRAW * ptbcd = (NMTBCUSTOMDRAW *)pnmcd;
  772. LRESULT lres = CDRF_DODEFAULT;
  773. switch (pnmcd->dwDrawStage)
  774. {
  775. case CDDS_PREPAINT:
  776. // if there is a palette, then quietly select it into the DC ...
  777. if ( _hpalHalftone && _uIconSize == ISFBVIEWMODE_LOGOS )
  778. {
  779. ASSERT( pnmcd->hdc );
  780. _hpalOld = SelectPalette( pnmcd->hdc, _hpalHalftone, TRUE );
  781. // LINTASSERT(_hpalOld || !_hpalOld); // 0 semi-ok for SelectPalette
  782. RealizePalette( pnmcd->hdc );
  783. }
  784. // make sure we get the postpaint as well so we can de-select the palette...
  785. lres = CDRF_NOTIFYPOSTPAINT;
  786. break;
  787. case CDDS_POSTPAINT:
  788. // if there is a palette, then quietly select it into the DC ...
  789. if ( _hpalHalftone && _uIconSize == ISFBVIEWMODE_LOGOS )
  790. {
  791. ASSERT( pnmcd->hdc );
  792. (void) SelectPalette( pnmcd->hdc, _hpalOld, TRUE );
  793. // we don't need a realize here, we can keep the other palette realzied, we
  794. // re select the old palette above, otherwise we bleed the resource....
  795. // RealizePalette( pnmcd->hdc );
  796. }
  797. break;
  798. case CDDS_PREERASE:
  799. if (_fHaveBkColor)
  800. {
  801. RECT rcClient;
  802. GetClientRect(_hwndTB, &rcClient);
  803. SHFillRectClr(pnmcd->hdc, &rcClient, _crBkgnd);
  804. lres = CDRF_SKIPDEFAULT;
  805. }
  806. break;
  807. }
  808. return lres;
  809. }
  810. void CISFBand::_OnDragBegin(int iItem, DWORD dwPreferedEffect)
  811. {
  812. LPCITEMIDLIST pidl = _IDToPidl(iItem, &_iDragSource);
  813. ToolBar_MarkButton(_hwndTB, iItem, TRUE);
  814. DragDrop(_hwnd, _psf, pidl, dwPreferedEffect, NULL);
  815. ToolBar_MarkButton(_hwndTB, iItem, FALSE);
  816. _iDragSource = -1;
  817. }
  818. LRESULT CISFBand::_OnHotItemChange(NMTBHOTITEM * pnm)
  819. {
  820. LPNMTBHOTITEM lpnmhi = (LPNMTBHOTITEM)pnm;
  821. LRESULT lres = 0;
  822. if (_hwndPager && (lpnmhi->dwFlags & HICF_ARROWKEYS))
  823. {
  824. int iOldPos, iNewPos;
  825. RECT rc, rcPager;
  826. int heightPager;
  827. int iSelected = lpnmhi->idNew;
  828. iOldPos = (int)SendMessage(_hwnd, PGM_GETPOS, (WPARAM)0, (LPARAM)0);
  829. iNewPos = iOldPos;
  830. SendMessage(_hwndTB, TB_GETITEMRECT, (WPARAM)iSelected, (LPARAM)&rc);
  831. if (rc.top < iOldPos)
  832. {
  833. iNewPos =rc.top;
  834. }
  835. GetClientRect(_hwnd, &rcPager);
  836. heightPager = RECTHEIGHT(rcPager);
  837. if (rc.top >= iOldPos + heightPager)
  838. {
  839. iNewPos += (rc.bottom - (iOldPos + heightPager)) ;
  840. }
  841. if (iNewPos != iOldPos)
  842. SendMessage(_hwnd, PGM_SETPOS, (WPARAM)0, (LPARAM)iNewPos);
  843. }
  844. else
  845. {
  846. lres = CToolbarBand::_OnHotItemChange(pnm);
  847. }
  848. return lres;
  849. }
  850. LRESULT CISFBand::_OnNotify(LPNMHDR pnm)
  851. {
  852. LRESULT lres = 0;
  853. switch (pnm->code)
  854. {
  855. case TBN_DROPDOWN:
  856. {
  857. LPNMTOOLBAR pnmtb = (LPNMTOOLBAR)pnm;
  858. lres = TBDDRET_DEFAULT;
  859. _DropdownItem(_IDToPidl(pnmtb->iItem), pnmtb->iItem);
  860. }
  861. break;
  862. default:
  863. lres = CSFToolbar::_OnNotify(pnm);
  864. }
  865. return lres;
  866. }
  867. HRESULT CISFBand::_TBStyleForPidl(LPCITEMIDLIST pidl,
  868. DWORD * pdwTBStyle, DWORD* pdwTBState, DWORD * pdwMIFFlags, int* piIcon)
  869. {
  870. HRESULT hres = CSFToolbar::_TBStyleForPidl(pidl, pdwTBStyle, pdwTBState, pdwMIFFlags, piIcon);
  871. if (_fAllowDropdown &&
  872. !_fCascadeFolder &&
  873. ((_GetAttributesOfPidl(pidl, SFGAO_FOLDER) & SFGAO_FOLDER) ||
  874. IsBrowsableShellExt(pidl)))
  875. {
  876. *pdwTBStyle &= ~BTNS_BUTTON;
  877. *pdwTBStyle |= BTNS_DROPDOWN;
  878. }
  879. return hres;
  880. }
  881. LRESULT CISFBand::_OnContextMenu(WPARAM wParam, LPARAM lParam)
  882. {
  883. LRESULT lres;
  884. lres = CSFToolbar::_OnContextMenu(wParam, lParam);
  885. // todo: csidl?
  886. TraceMsg(DM_MISC, "cib._ocm: _dwPriv=%d", _dwPriv);
  887. UEMFireEvent(&UEMIID_SHELL, UEME_INSTRBROWSER, UEMF_INSTRUMENT, UIBW_UICONTEXT, (_dwPriv == CSIDL_APPDATA || _dwPriv == CSIDL_FAVORITES) ? UIBL_CTXTQCUTITEM : UIBL_CTXTISFITEM);
  888. return lres;
  889. }
  890. LRESULT CISFBand::_DefWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  891. {
  892. switch (uMsg) {
  893. case WM_SIZE:
  894. // forward to toolbar
  895. SendMessage(_hwndTB, TB_AUTOSIZE, wParam, lParam);
  896. if (_GetIdealSize(NULL) != _iIdealLength) {
  897. // our ideal size has changed since the last time bandsite
  898. // asked; so tell bandsite ask us for our bandinfo again
  899. _BandInfoChanged();
  900. }
  901. return 0;
  902. }
  903. return CSFToolbar::_DefWindowProc(hwnd, uMsg, wParam, lParam);
  904. }
  905. /*----------------------------------------------------------
  906. Purpose: Set the given IMenuPopup as the submenu to expand. Returns
  907. S_FALSE if the menu was modal, S_OK if it was modeless, or
  908. failure.
  909. */
  910. HRESULT CISFBand::_SetSubMenuPopup(IMenuPopup* pmp, UINT uiCmd, LPCITEMIDLIST pidl, DWORD dwFlagsMPPF)
  911. {
  912. HRESULT hres = E_FAIL;
  913. _ReleaseMenu();
  914. _pmp = pmp;
  915. if (pmp) {
  916. pmp->AddRef();
  917. RECT rc;
  918. POINT pt;
  919. SendMessage(_hwndTB, TB_GETRECT, uiCmd, (LPARAM)&rc);
  920. MapWindowPoints(_hwndTB, HWND_DESKTOP, (POINT*)&rc, 2);
  921. // Align the sub menu appropriately
  922. if (_fVertical) {
  923. pt.x = rc.right;
  924. pt.y = rc.top;
  925. } else {
  926. pt.x = rc.left;
  927. pt.y = rc.bottom;
  928. }
  929. //
  930. // Use a reflect point for the sub-menu to start
  931. // if the window is RTL mirrored. [samera]
  932. //
  933. if (IS_WINDOW_RTL_MIRRORED(_hwndTB)) {
  934. pt.x = (_fVertical) ? rc.left : rc.right;
  935. }
  936. // Tell the sub menu deskbar who we are, so it can
  937. // inform us later when the user navigates out of
  938. // its scope.
  939. IUnknown_SetSite(_pmp, SAFECAST(this, IDeskBand*));
  940. // This must be called after SetSite is done above
  941. _SendInitMenuPopup(pmp, pidl);
  942. // Show the menubar
  943. hres = _pmp->Popup((POINTL*)&pt, (RECTL*)&rc, dwFlagsMPPF);
  944. }
  945. return hres;
  946. }
  947. void CISFBand::_SendInitMenuPopup(IMenuPopup * pmp, LPCITEMIDLIST pidl)
  948. {
  949. }
  950. IMenuPopup* ISFBandCreateMenuPopup(IUnknown *punk, IShellFolder* psf, LPCITEMIDLIST pidl, BANDINFOSFB * pbi, BOOL bMenuBand)
  951. {
  952. return ISFBandCreateMenuPopup2(punk, NULL, psf, pidl, pbi, bMenuBand);
  953. }
  954. IMenuPopup* ISFBandCreateMenuPopup2(IUnknown *punk, IMenuBand* pmb, IShellFolder* psf, LPCITEMIDLIST pidl, BANDINFOSFB * pbi, BOOL bMenuBand)
  955. {
  956. IMenuPopup* pmpParent = NULL;
  957. VARIANTARG v = {0};
  958. BOOL fUseCache = FALSE;
  959. if (punk && pidl) {
  960. fUseCache = TRUE;
  961. IUnknown_Exec(punk, &CGID_ISFBand, ISFBID_CACHEPOPUP, 0, NULL, &v);
  962. if (v.vt == VT_UNKNOWN && v.punkVal)
  963. v.punkVal->QueryInterface(IID_IMenuPopup, (void **)&pmpParent);
  964. }
  965. IMenuPopup * pmp = CreateMenuPopup2(pmpParent, pmb, psf, pidl, pbi, bMenuBand);
  966. if (fUseCache) {
  967. // cache it now
  968. // clear from the variant above to release v.punkVal of pmpParent
  969. VariantClear(&v);
  970. if (pmp) {
  971. VariantInit(&v);
  972. v.vt = VT_UNKNOWN;
  973. v.punkVal = pmp;
  974. pmp->AddRef();
  975. IUnknown_Exec(punk, &CGID_ISFBand, ISFBID_CACHEPOPUP, 0, &v, NULL);
  976. VariantClear(&v);
  977. }
  978. }
  979. ATOMICRELEASE(pmpParent);
  980. return pmp;
  981. }
  982. IMenuPopup * CISFBand::_CreateMenuPopup(
  983. IShellFolder * psfChild,
  984. LPCITEMIDLIST pidlFull,
  985. BANDINFOSFB * pbi)
  986. {
  987. return ISFBandCreateMenuPopup(SAFECAST(this, IOleCommandTarget*), psfChild, pidlFull, pbi, FALSE);
  988. }
  989. HRESULT CISFBand::_DropdownItem(LPCITEMIDLIST pidl, UINT idCmd)
  990. {
  991. HRESULT hres = E_FAIL;
  992. if (_pidl && _psf)
  993. {
  994. LPITEMIDLIST pidlFull = ILCombine(_pidl, pidl);
  995. if (pidlFull)
  996. {
  997. IShellFolder* psf;
  998. if (SUCCEEDED(_psf->BindToObject(pidl, NULL, IID_IShellFolder, (void **)&psf)))
  999. {
  1000. RECT rc;
  1001. SendMessage(_hwndTB, TB_GETRECT, idCmd, (LPARAM)&rc);
  1002. MapWindowPoints(_hwndTB, HWND_DESKTOP, (POINT*)&rc, 2);
  1003. ITrackShellMenu* ptsm;
  1004. if (SUCCEEDED(CoCreateInstance(CLSID_TrackShellMenu, NULL, CLSCTX_INPROC_SERVER,
  1005. IID_ITrackShellMenu, (void**)&ptsm)))
  1006. {
  1007. CFavoritesCallback *pfcb = new CFavoritesCallback();
  1008. if(pfcb) {
  1009. ptsm->Initialize(pfcb, 0, 0, SMINIT_TOPLEVEL | SMINIT_VERTICAL|SMINIT_NOSETSITE);
  1010. pfcb->SetSite(_punkSite);
  1011. }
  1012. else
  1013. ptsm->Initialize(NULL, 0, 0, SMINIT_TOPLEVEL | SMINIT_VERTICAL);
  1014. if (SUCCEEDED(ptsm->SetShellFolder(psf, pidlFull, NULL, SMSET_TOP | SMSET_USEBKICONEXTRACTION)))
  1015. {
  1016. POINTL pt = {rc.left, rc.right};
  1017. hres = ptsm->Popup(_hwndTB, &pt, (RECTL*)&rc, MPPF_BOTTOM);
  1018. }
  1019. if(pfcb)
  1020. pfcb->Release();
  1021. ptsm->Release();
  1022. }
  1023. psf->Release();
  1024. }
  1025. ILFree(pidlFull);
  1026. }
  1027. }
  1028. return hres;
  1029. }
  1030. /*----------------------------------------------------------
  1031. Purpose: Try treating the pidl as a cascading menu item.
  1032. Returns: non-zero if succeeded
  1033. */
  1034. LRESULT CISFBand::_TryCascadingItem(LPCITEMIDLIST pidl, UINT uiCmd)
  1035. {
  1036. LRESULT lRet = 0;
  1037. // Do we cascade to another submenu?
  1038. if ((GetKeyState(VK_CONTROL) < 0) || _fCascadeFolder)
  1039. {
  1040. // Is the item a browsable folder?
  1041. if ((_GetAttributesOfPidl(pidl, SFGAO_FOLDER) & SFGAO_FOLDER) ||
  1042. IsBrowsableShellExt(pidl))
  1043. {
  1044. // Yes; cascade the browsable folder as a submenu
  1045. lRet = (S_OK == _DropdownItem(pidl, uiCmd));
  1046. }
  1047. }
  1048. return lRet;
  1049. }
  1050. /*----------------------------------------------------------
  1051. Purpose: Try just invoking the pidl
  1052. Returns: non-zero if succeeded
  1053. */
  1054. LRESULT CISFBand::_TrySimpleInvoke(LPCITEMIDLIST pidl)
  1055. {
  1056. LRESULT lRet = 0;
  1057. if (S_OK == _pbp->IsConnected()) // Force IE
  1058. {
  1059. LPITEMIDLIST pidlDest;
  1060. if (SUCCEEDED(SHGetNavigateTarget(_psf, pidl, &pidlDest, NULL)) && pidlDest &&
  1061. ILIsWeb(pidlDest))
  1062. {
  1063. TCHAR szPath[MAX_PATH];
  1064. // We want to ensure that we first give NavFrameWithFile a chance
  1065. // since this will do the right thing if the PIDL points to a
  1066. // shortcut.
  1067. // If the PIDL is a shortcut, NavFrameWithFile will restore any
  1068. // persistence information stored in the shortcut
  1069. // if that fails - we take the default code path that simply
  1070. // uses the PIDL
  1071. lRet = SUCCEEDED(GetPathForItem(_psf, pidl, szPath, NULL)) &&
  1072. SUCCEEDED(NavFrameWithFile(szPath, (IServiceProvider *)this));
  1073. if (!lRet)
  1074. {
  1075. if (EVAL(_pbp) && (SUCCEEDED(_pbp->NavigateToPIDL(pidlDest))))
  1076. lRet = 1;
  1077. }
  1078. ILFree(pidlDest);
  1079. }
  1080. }
  1081. if (!lRet)
  1082. {
  1083. IContextMenu *pcm = (LPCONTEXTMENU)_GetUIObjectOfPidl(pidl, IID_IContextMenu);
  1084. if (pcm)
  1085. {
  1086. LPCSTR pVerb = NULL;
  1087. UINT fFlags = 0;
  1088. // If ALT double click, accelerator for "Properties..."
  1089. if (GetKeyState(VK_MENU) < 0)
  1090. {
  1091. pVerb = SZ_PROPERTIESA;
  1092. }
  1093. //
  1094. // SHIFT+dblclick does a Explore by default
  1095. //
  1096. if (GetKeyState(VK_SHIFT) < 0)
  1097. {
  1098. fFlags |= CMF_EXPLORE;
  1099. }
  1100. IContextMenu_Invoke(pcm, _hwndTB, pVerb, fFlags);
  1101. pcm->Release();
  1102. }
  1103. }
  1104. return lRet;
  1105. }
  1106. /*----------------------------------------------------------
  1107. Purpose: Helper function to call the menubar site's IMenuPopup::OnSelect
  1108. method.
  1109. */
  1110. HRESULT CISFBand::_SiteOnSelect(DWORD dwType)
  1111. {
  1112. IMenuPopup * pmp;
  1113. HRESULT hres = IUnknown_QueryService(_punkSite, SID_SMenuPopup, IID_IMenuPopup, (void **)&pmp);
  1114. if (SUCCEEDED(hres))
  1115. {
  1116. pmp->OnSelect(dwType);
  1117. pmp->Release();
  1118. }
  1119. return hres;
  1120. }
  1121. LRESULT CISFBand::_OnCommand(WPARAM wParam, LPARAM lParam)
  1122. {
  1123. UINT uiCmd = GET_WM_COMMAND_ID(wParam, lParam);
  1124. LRESULT lres = 0;
  1125. TraceMsg(TF_BAND, "_OnCommand 0x%x", uiCmd);
  1126. LPCITEMIDLIST pidl = _IDToPidl(uiCmd);
  1127. if (pidl)
  1128. {
  1129. if (_eUemLog != UEMIND_NIL)
  1130. {
  1131. // FEATURE_UASSIST should be grp,uiCmd
  1132. UEMFireEvent(&UEMIID_SHELL, UEME_UIQCUT, UEMF_XEVENT, -1, (LPARAM)-1);
  1133. }
  1134. // Only do this if we are the quick links in the browser. The derived class will set this
  1135. if (_pguidUEMGroup)
  1136. {
  1137. LPITEMIDLIST pidlFull = ILCombine(_pidl, pidl);
  1138. if (pidlFull)
  1139. {
  1140. UEMFireEvent(_pguidUEMGroup, UEME_RUNPIDL, UEMF_XEVENT, (WPARAM)_psf, (LPARAM)pidl);
  1141. SHSendChangeMenuNotify(NULL, SHCNEE_PROMOTEDITEM, 0, pidlFull);
  1142. ILFree(pidlFull);
  1143. }
  1144. }
  1145. lres = _TryCascadingItem(pidl, uiCmd);
  1146. if (!lres && _fChannels)
  1147. lres = _TryChannelSurfing(pidl);
  1148. if (!lres)
  1149. lres = _TrySimpleInvoke(pidl);
  1150. }
  1151. else
  1152. {
  1153. MessageBeep(MB_OK);
  1154. }
  1155. return(lres);
  1156. }
  1157. // *** IPersistStream
  1158. //
  1159. HRESULT CISFBand::GetClassID(CLSID *pClassID)
  1160. {
  1161. *pClassID = CLSID_ISFBand;
  1162. return S_OK;
  1163. }
  1164. //
  1165. // This might be a directory inside CSIDL_APPDATA that was created on
  1166. // a Win9x machine. Win9x doesn't do the special folder signature info,
  1167. // so when it shows up on NT, it's just a boring directory that now points
  1168. // to the wrong place.
  1169. //
  1170. // So if we get a bad directory, see if it's one of these corrupted
  1171. // Win9x pidls and if so, try to reconstitute the original CSIDL_APPDATA
  1172. // by searching for "Application Data".
  1173. //
  1174. void CISFBand::_FixupAppDataDirectory()
  1175. {
  1176. TCHAR szDirPath[MAX_PATH];
  1177. // We use PathFileExists to check for existence because it turns off
  1178. // hard error boxes if the target is not available (e.g., floppy not
  1179. // in drive)
  1180. if (SHGetPathFromIDList(_pidl, szDirPath) &&
  1181. !PathFileExists(szDirPath))
  1182. {
  1183. static TCHAR szBSAppData[] = TEXT("\\Application Data");
  1184. LPTSTR pszAppData;
  1185. // For every instance of "Application Data", try to graft it
  1186. // into the real CSIDL_APPDATA. If it works, run with it.
  1187. for (pszAppData = szDirPath;
  1188. pszAppData = StrStrI(pszAppData, szBSAppData);
  1189. pszAppData++)
  1190. {
  1191. // Found a candidate. The thing after "\\Application Data"
  1192. // had better be another backslash (in which case we step
  1193. // over it) or the end of the string (in which case we don't).
  1194. TCHAR szPathBuffer[MAX_PATH];
  1195. LPTSTR pszTail = pszAppData + ARRAYSIZE(szBSAppData) - 1;
  1196. // If we did our math right, we should be right after the
  1197. // "a" at the end of "Application Data".
  1198. ASSERT(pszTail[-1] == TEXT('a'));
  1199. if (pszTail[0] == TEXT('\\'))
  1200. pszTail++; // Step over separator
  1201. else if (pszTail[0] == TEXT('\0'))
  1202. { } // at end of string; stay there
  1203. else
  1204. continue; // we were faked out; keep looking
  1205. if (SHGetSpecialFolderPath(NULL, szPathBuffer, CSIDL_APPDATA, FALSE))
  1206. {
  1207. PathCombine(szPathBuffer, szPathBuffer, pszTail);
  1208. if (PathFileExists(szPathBuffer))
  1209. {
  1210. LPITEMIDLIST pidlReal;
  1211. pidlReal = ILCreateFromPath(szPathBuffer);
  1212. if (pidlReal)
  1213. {
  1214. ILFree(_pidl);
  1215. _pidl = pidlReal;
  1216. }
  1217. ASSERT(_pidl);
  1218. break; // found it; stop looking
  1219. }
  1220. }
  1221. }
  1222. }
  1223. }
  1224. typedef struct tagBANDISFSTREAM {
  1225. WORD wVersion; // version of this structure
  1226. WORD cbSize; // size of this structure
  1227. DWORD dwFlags; // BANDISF_ flags
  1228. DWORD dwPriv; // special folder identifier
  1229. WORD wViewMode; // small/large/logo
  1230. WORD wUnused; // For DWORD alignment
  1231. COLORREF crBkgnd; // band background color
  1232. COLORREF crBtnLt; // band button hilite color
  1233. COLORREF crBtnDk; // band button lolite color
  1234. } BANDISFSTREAM, * PBANDISFSTREAM;
  1235. #define BANDISF_VERSION 0x22
  1236. #define BANDISF_MASK_PSF 0x00000001 // TRUE if _psf is saved
  1237. #define BANDISF_BOOL_NOSHOWTEXT 0x00000002 // TRUE if _fNoShowText
  1238. #define BANDISF_BOOL_LARGEICON 0x00000004 // last used in version 0x20
  1239. #define BANDISF_MASK_PIDLASLINK 0x00000008 // TRUE if _pidl is saved as a link
  1240. #define BANDISF_UNUSED10 0x00000010 // (obsolete) was BOOL_NOTITLE
  1241. #define BANDISF_BOOL_CHANNELS 0x00000020 // TRUE if in channel mode
  1242. #define BANDISF_BOOL_ALLOWRENAME 0x00000040 // TRUE if _psf context menu should be enabled
  1243. #define BANDISF_BOOL_DEBOSSED 0x00000080 // TRUE if band should have embossed background
  1244. #define BANDISF_MASK_ORDERLIST 0x00000100 // TRUE if an order list is saved
  1245. #define BANDISF_BOOL_BKCOLOR 0x00000200 // TRUE if bk color is persisted
  1246. #define BANDISF_BOOL_FULLOPEN 0x00000400 // TRUE if band should maximize when opened
  1247. #define BANDISF_BOOL_NONAMESORT 0x00000800 // TRUE if band should _not_ sort icons by name
  1248. #define BANDISF_BOOL_BTNMINSIZE 0x00001000 // TRUE if band should report min thickness of button
  1249. #define BANDISF_BOOL_COLORS 0x00002000 // TRUE if colors are persisted
  1250. #define BANDISF_VALIDBITS 0x00003FFF
  1251. HRESULT CISFBand::Load(IStream *pstm)
  1252. {
  1253. HRESULT hres;
  1254. DWORD cbRead;
  1255. BANDISFSTREAM bisfs = {0};
  1256. // figure out what we need to load
  1257. //
  1258. // read first DWORD only (old stream format started with ONE dword)
  1259. hres = pstm->Read(&bisfs, SIZEOF(DWORD), &cbRead);
  1260. if (SUCCEEDED(hres))
  1261. {
  1262. if (bisfs.cbSize == 0)
  1263. {
  1264. // upgrade case, IE4 beta1 shipped this way
  1265. //
  1266. bisfs.dwFlags = *((LPDWORD)&bisfs);
  1267. bisfs.cbSize = SIZEOF(bisfs);
  1268. bisfs.wVersion = BANDISF_VERSION;
  1269. bisfs.dwPriv = -1;
  1270. bisfs.wViewMode = (bisfs.dwFlags & BANDISF_BOOL_LARGEICON) ? ISFBVIEWMODE_LARGEICONS : ISFBVIEWMODE_SMALLICONS;
  1271. }
  1272. else
  1273. {
  1274. // read rest of stream
  1275. //
  1276. DWORD dw = (DWORD)bisfs.cbSize;
  1277. if (dw > SIZEOF(bisfs))
  1278. dw = SIZEOF(bisfs);
  1279. dw -= SIZEOF(DWORD);
  1280. hres = pstm->Read(&(bisfs.dwFlags), dw, &cbRead);
  1281. if (FAILED(hres))
  1282. return(hres);
  1283. }
  1284. // HEY, DON'T BE LAME ANY MORE. When you next touch this code,
  1285. // I suggest you figure out what sizes of this structure have
  1286. // been actually shipped and only upgrade those. Also use
  1287. // the offsetof macro so you don't have to keep calculating these
  1288. // things...
  1289. // old upgrade, I don't know what state is persisted at setup time!
  1290. //
  1291. if (bisfs.cbSize == SIZEOF(bisfs) - 3*SIZEOF(COLORREF) - SIZEOF(DWORD) - SIZEOF(DWORD))
  1292. {
  1293. bisfs.dwPriv = -1;
  1294. bisfs.cbSize += SIZEOF(DWORD);
  1295. }
  1296. // most recent upgrade, this is NOT persisted in registry at setup time!!!
  1297. //
  1298. if (bisfs.cbSize == SIZEOF(bisfs) - 3*SIZEOF(COLORREF) - SIZEOF(DWORD))
  1299. {
  1300. bisfs.wViewMode = (bisfs.dwFlags & BANDISF_BOOL_LARGEICON) ? ISFBVIEWMODE_LARGEICONS : ISFBVIEWMODE_SMALLICONS;
  1301. bisfs.cbSize = SIZEOF(bisfs);
  1302. }
  1303. // upgrade from version 0x21 + crBkgnd only to 0x22
  1304. //
  1305. if (bisfs.cbSize == SIZEOF(bisfs) - 2*SIZEOF(COLORREF))
  1306. {
  1307. bisfs.cbSize = SIZEOF(bisfs);
  1308. }
  1309. // upgrade from version 0x21 to 0x22
  1310. //
  1311. if (bisfs.cbSize == SIZEOF(bisfs) - 3*SIZEOF(COLORREF))
  1312. {
  1313. bisfs.cbSize = SIZEOF(bisfs);
  1314. }
  1315. if (!EVAL(bisfs.cbSize >= SIZEOF(bisfs)))
  1316. {
  1317. return(E_FAIL);
  1318. }
  1319. ASSERT(!(bisfs.dwFlags & ~BANDISF_VALIDBITS));
  1320. if (bisfs.dwFlags & BANDISF_BOOL_NOSHOWTEXT)
  1321. _fNoShowText = TRUE;
  1322. if (bisfs.dwFlags & BANDISF_BOOL_ALLOWRENAME)
  1323. _fAllowRename = TRUE;
  1324. if (bisfs.dwFlags & BANDISF_BOOL_DEBOSSED)
  1325. _fDebossed = TRUE;
  1326. if (bisfs.dwFlags & BANDISF_BOOL_FULLOPEN)
  1327. _fFullOpen = TRUE;
  1328. if (bisfs.dwFlags & BANDISF_BOOL_NONAMESORT)
  1329. _fNoNameSort = TRUE;
  1330. if (bisfs.dwFlags & BANDISF_BOOL_BTNMINSIZE)
  1331. _fBtnMinSize = TRUE;
  1332. if (bisfs.dwFlags & BANDISF_BOOL_BKCOLOR)
  1333. {
  1334. _crBkgnd = bisfs.crBkgnd;
  1335. _fHaveBkColor = TRUE;
  1336. }
  1337. if (bisfs.dwFlags & BANDISF_BOOL_COLORS)
  1338. {
  1339. _crBtnLt = bisfs.crBtnLt;
  1340. _crBtnDk = bisfs.crBtnDk;
  1341. _fHaveColors = TRUE;
  1342. }
  1343. _dwPriv = bisfs.dwPriv;
  1344. #if 1 // BUGBUG FEATURE_UASSIST hack this should be persisted not recalc'ed
  1345. #define UEMIsLogCsidl(dwPrivID) ((dwPrivID) == CSIDL_APPDATA)
  1346. if (UEMIsLogCsidl(_dwPriv)) {
  1347. _eUemLog = UEMIND_SHELL;
  1348. }
  1349. #endif
  1350. _uIconSize = bisfs.wViewMode;
  1351. _fNoRecalcDefaults = TRUE;
  1352. if (bisfs.dwFlags & BANDISF_MASK_PIDLASLINK)
  1353. {
  1354. ASSERT(NULL==_pidl);
  1355. hres = LoadPidlAsLink(_punkSite, pstm, &_pidl);
  1356. // If we hit hits, LoadPidlAsLink() read a chuck of our data. - BryanSt
  1357. ASSERT(SUCCEEDED(hres));
  1358. // DEBUG_CODE(TCHAR szDbgBuffer[MAX_PATH];)
  1359. // TraceMsg(TF_BAND|TF_GENERAL, "CISFBand::Load() _pidl=>%s<", Dbg_PidlStr(_pidl, szDbgBuffer, SIZECHARS(szDbgBuffer)));
  1360. _FixupAppDataDirectory();
  1361. }
  1362. if (SUCCEEDED(hres) && (bisfs.dwFlags & BANDISF_MASK_PSF))
  1363. {
  1364. ASSERT(NULL == _psf);
  1365. hres = OleLoadFromStream(pstm, IID_IShellFolder, (void **)&_psf);
  1366. }
  1367. // map this to working info
  1368. //
  1369. if (SUCCEEDED(hres))
  1370. _AfterLoad();
  1371. // we need _psf before we can read the order list.
  1372. if (SUCCEEDED(hres) && (bisfs.dwFlags & BANDISF_MASK_ORDERLIST))
  1373. {
  1374. hres = OrderList_LoadFromStream(pstm, &_hdpaOrder, _psf);
  1375. if (SUCCEEDED(hres))
  1376. {
  1377. // _fDropped "persists" along with the orderlist - if this flag
  1378. // is set, we assume we have a non-default ordering
  1379. _fDropped = TRUE;
  1380. }
  1381. }
  1382. }
  1383. return hres;
  1384. }
  1385. HRESULT SaveIsfToStream(IShellFolder *psf, IStream *pstm)
  1386. {
  1387. IPersistStream* pps;
  1388. HRESULT hres = psf->QueryInterface(IID_PPV_ARG(IPersistStream, &pps));
  1389. if (SUCCEEDED(hres))
  1390. {
  1391. hres = OleSaveToStream(pps, pstm);
  1392. pps->Release();
  1393. }
  1394. return hres;
  1395. }
  1396. HRESULT CISFBand::Save(IStream *pstm, BOOL fClearDirty)
  1397. {
  1398. HRESULT hres;
  1399. BANDISFSTREAM bisfs = {0};
  1400. // figure out what we will save
  1401. //
  1402. if (_pidl)
  1403. bisfs.dwFlags |= BANDISF_MASK_PIDLASLINK;
  1404. // BUGBUG(lamadio): This case is busted. None of the IShellFolders implement IPersistStream (at least as far as
  1405. // TJ and I can see). Qhen quick links initializes, it will set the pidlQuickLinks as the _pidl. So, in the
  1406. // After load, _fPSFBandDesktop gets set to TRUE. Why? I don't know. Well, then we never attempt to persist the
  1407. // IShellFolder and we will never fail the save. We should remove this case so we don't run into this again.
  1408. if (_psf && !_fPSFBandDesktop)
  1409. bisfs.dwFlags |= BANDISF_MASK_PSF;
  1410. if (_fDropped && (_hdpa || _hdpaOrder)) // only if a drop occurred do we have non-default ordering
  1411. bisfs.dwFlags |= BANDISF_MASK_ORDERLIST;
  1412. if (_fNoShowText)
  1413. bisfs.dwFlags |= BANDISF_BOOL_NOSHOWTEXT;
  1414. if (_fAllowRename)
  1415. bisfs.dwFlags |= BANDISF_BOOL_ALLOWRENAME;
  1416. if (_fDebossed)
  1417. bisfs.dwFlags |= BANDISF_BOOL_DEBOSSED;
  1418. if (_fFullOpen)
  1419. bisfs.dwFlags |= BANDISF_BOOL_FULLOPEN;
  1420. if (_fNoNameSort)
  1421. bisfs.dwFlags |= BANDISF_BOOL_NONAMESORT;
  1422. if (_fBtnMinSize)
  1423. bisfs.dwFlags |= BANDISF_BOOL_BTNMINSIZE;
  1424. if (_fHaveBkColor)
  1425. {
  1426. bisfs.dwFlags |= BANDISF_BOOL_BKCOLOR;
  1427. bisfs.crBkgnd = _crBkgnd;
  1428. }
  1429. if (_fHaveColors)
  1430. {
  1431. bisfs.dwFlags |= BANDISF_BOOL_COLORS;
  1432. bisfs.crBtnLt = _crBtnLt;
  1433. bisfs.crBtnDk = _crBtnDk;
  1434. }
  1435. bisfs.cbSize = SIZEOF(bisfs);
  1436. bisfs.wVersion = BANDISF_VERSION;
  1437. bisfs.dwPriv = _dwPriv;
  1438. bisfs.wViewMode = _uIconSize;
  1439. // now save it
  1440. //
  1441. hres = pstm->Write(&bisfs, SIZEOF(bisfs), NULL);
  1442. if (SUCCEEDED(hres) && bisfs.dwFlags & BANDISF_MASK_PIDLASLINK)
  1443. {
  1444. hres = SavePidlAsLink(_punkSite, pstm, _pidl);
  1445. // BUGBUG: We need to save a terminator.
  1446. }
  1447. if (SUCCEEDED(hres) && bisfs.dwFlags & BANDISF_MASK_PSF)
  1448. {
  1449. hres = SaveIsfToStream(_psf, pstm);
  1450. }
  1451. if (SUCCEEDED(hres) && (bisfs.dwFlags & BANDISF_MASK_ORDERLIST))
  1452. {
  1453. hres = OrderList_SaveToStream(pstm, (_hdpa ? _hdpa : _hdpaOrder), _psf);
  1454. }
  1455. return(hres);
  1456. }
  1457. #if 0
  1458. // IPersistPropertyBag implementation
  1459. //
  1460. HRESULT CISFBand::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
  1461. {
  1462. ASSERT(0); // obsolete!
  1463. _fCascadeFolder = PropBag_ReadInt4(pPropBag, L"Cascade", FALSE);
  1464. // n.b. old "Title" property nuked
  1465. _uIconSize = (PropBag_ReadInt4(pPropBag, L"Large", TRUE) ? ISFBVIEWMODE_LARGEICONS : ISFBVIEWMODE_SMALLICONS);
  1466. _fNoShowText = PropBag_ReadInt4(pPropBag, L"Text", TRUE);
  1467. return(S_OK);
  1468. }
  1469. HRESULT CISFBand::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
  1470. {
  1471. return(E_NOTIMPL);
  1472. }
  1473. HRESULT CISFBand::InitNew()
  1474. {
  1475. ASSERT(0); // obsolete!
  1476. return(E_NOTIMPL);
  1477. }
  1478. #endif
  1479. // IContextMenu implementation
  1480. //
  1481. HRESULT CISFBand::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
  1482. {
  1483. BOOL fChanged = FALSE;
  1484. int idCmd = -1;
  1485. UINT uNewMode = 0;
  1486. if (!HIWORD(lpici->lpVerb))
  1487. idCmd = LOWORD(lpici->lpVerb);
  1488. switch (idCmd)
  1489. {
  1490. case ISFBIDM_LARGE:
  1491. uNewMode = ISFBVIEWMODE_LARGEICONS;
  1492. goto newViewMode;
  1493. case ISFBIDM_SMALL:
  1494. uNewMode = ISFBVIEWMODE_SMALLICONS;
  1495. newViewMode:
  1496. if (uNewMode != _uIconSize)
  1497. {
  1498. BOOL fRefresh = FALSE;
  1499. if (uNewMode == ISFBVIEWMODE_LOGOS || _uIconSize == ISFBVIEWMODE_LOGOS)
  1500. {
  1501. // invalidate all before switching the imagelist...
  1502. _RememberOrder();
  1503. EmptyToolbar();
  1504. fRefresh = TRUE;
  1505. }
  1506. // we Logo view has now left the building...
  1507. if ( uNewMode != ISFBVIEWMODE_LOGOS && _uIconSize == ISFBVIEWMODE_LOGOS )
  1508. {
  1509. ExitLogoView();
  1510. }
  1511. fChanged = _UpdateIconSize(uNewMode, TRUE);
  1512. if ( fRefresh )
  1513. {
  1514. _FillToolbar();
  1515. }
  1516. if (fChanged)
  1517. _BandInfoChanged();
  1518. }
  1519. // fall thru
  1520. default:
  1521. return CSFToolbar::InvokeCommand(lpici);
  1522. }
  1523. return(S_OK);
  1524. }
  1525. // *** IOleCommandTarget methods ***
  1526. STDMETHODIMP CISFBand::QueryStatus(const GUID *pguidCmdGroup,
  1527. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  1528. {
  1529. HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
  1530. if (pguidCmdGroup == NULL)
  1531. {
  1532. // nothing
  1533. }
  1534. else if (IsEqualGUID(CGID_ISFBand, *pguidCmdGroup))
  1535. {
  1536. for (UINT i = 0; i < cCmds; i++)
  1537. {
  1538. switch (rgCmds[i].cmdID)
  1539. {
  1540. case ISFBID_CACHEPOPUP:
  1541. case ISFBID_ISITEMVISIBLE:
  1542. case ISFBID_PRIVATEID:
  1543. rgCmds[i].cmdf |= OLECMDF_SUPPORTED;
  1544. break;
  1545. }
  1546. }
  1547. hr = S_OK;
  1548. }
  1549. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  1550. {
  1551. for (UINT i = 0; i < cCmds; i++)
  1552. {
  1553. switch (rgCmds[i].cmdID)
  1554. {
  1555. case SHDVID_UEMLOG:
  1556. rgCmds[i].cmdf |= OLECMDF_SUPPORTED;
  1557. break;
  1558. }
  1559. }
  1560. hr = S_OK;
  1561. }
  1562. return hr;
  1563. }
  1564. HRESULT CISFBand::_IsPidlVisible(LPITEMIDLIST pidl)
  1565. {
  1566. int i;
  1567. if (_GetButtonFromPidl(pidl, NULL, &i)) {
  1568. RECT rc;
  1569. GetClientRect(_hwndTB, &rc);
  1570. if (SHIsButtonObscured(_hwndTB, &rc, i))
  1571. return S_FALSE;
  1572. else
  1573. return S_OK;
  1574. }
  1575. return E_FAIL;
  1576. }
  1577. HRESULT CISFBand::_OrderListFromIStream(VARIANT* pvarargIn)
  1578. {
  1579. HRESULT hres = E_FAIL;
  1580. if (pvarargIn->vt == VT_UNKNOWN)
  1581. {
  1582. IStream* pstm;
  1583. if (SUCCEEDED(pvarargIn->punkVal->QueryInterface(IID_IStream, (void**)&pstm)))
  1584. {
  1585. OrderList_Destroy(&_hdpaOrder);
  1586. hres = OrderList_LoadFromStream(pstm, &_hdpaOrder, _psf);
  1587. if (SUCCEEDED(hres))
  1588. {
  1589. _SetDirty(TRUE);
  1590. if (_fShow)
  1591. {
  1592. _FillToolbar();
  1593. }
  1594. }
  1595. pstm->Release();
  1596. }
  1597. }
  1598. return hres;
  1599. }
  1600. HRESULT CISFBand::_IStreamFromOrderList(VARIANT* pvarargOut)
  1601. {
  1602. HRESULT hres = E_OUTOFMEMORY;
  1603. ASSERT(pvarargOut != NULL);
  1604. IStream* pstm = SHCreateMemStream(NULL, 0);
  1605. if (pstm)
  1606. {
  1607. hres = OrderList_SaveToStream(pstm, _hdpa, _psf);
  1608. if (SUCCEEDED(hres))
  1609. {
  1610. pvarargOut->vt = VT_UNKNOWN;
  1611. pvarargOut->punkVal = pstm;
  1612. pvarargOut->punkVal->AddRef();
  1613. }
  1614. pstm->Release();
  1615. }
  1616. return hres;
  1617. }
  1618. STDMETHODIMP CISFBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
  1619. DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  1620. {
  1621. if (pguidCmdGroup == NULL)
  1622. {
  1623. // nothing
  1624. }
  1625. else if (IsEqualGUID(CGID_ISFBand, *pguidCmdGroup))
  1626. {
  1627. switch (nCmdID)
  1628. {
  1629. case ISFBID_CACHEPOPUP:
  1630. if (pvarargIn && pvarargIn->vt == VT_UNKNOWN)
  1631. {
  1632. IMenuPopup* pmp = NULL;
  1633. if (pvarargIn->punkVal)
  1634. pvarargIn->punkVal->QueryInterface(IID_IMenuPopup, (void **)&pmp);
  1635. _SetCacheMenuPopup(pmp);
  1636. ATOMICRELEASE(pmp);
  1637. }
  1638. if (pvarargOut)
  1639. {
  1640. pvarargOut->vt = VT_UNKNOWN;
  1641. pvarargOut->punkVal = _pmpCache;
  1642. if (_pmpCache)
  1643. _pmpCache->AddRef();
  1644. }
  1645. return S_OK;
  1646. case ISFBID_ISITEMVISIBLE:
  1647. {
  1648. HRESULT hr = E_INVALIDARG;
  1649. if (pvarargIn && pvarargIn->vt == VT_INT_PTR)
  1650. hr = _IsPidlVisible((LPITEMIDLIST)pvarargIn->byref);
  1651. return hr;
  1652. }
  1653. case ISFBID_PRIVATEID:
  1654. // hack hack for BSMenu to differentiate between specially created
  1655. // isfbands. see bsmenu's _FindBand
  1656. // if pvarargOut is set, we give back the id we have stored.
  1657. if (pvarargOut)
  1658. {
  1659. pvarargOut->vt = VT_I4;
  1660. pvarargOut->lVal = _dwPriv;
  1661. }
  1662. // if pvarargIn is set, then we take and keep this id.
  1663. if (pvarargIn && pvarargIn->vt == VT_I4)
  1664. _dwPriv = pvarargIn->lVal;
  1665. return S_OK;
  1666. case ISFBID_GETORDERSTREAM:
  1667. return _IStreamFromOrderList(pvarargOut);
  1668. case ISFBID_SETORDERSTREAM:
  1669. return _OrderListFromIStream(pvarargIn);
  1670. }
  1671. }
  1672. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  1673. {
  1674. switch (nCmdID)
  1675. {
  1676. case SHDVID_UEMLOG:
  1677. ASSERT(pvarargOut == NULL);
  1678. // if pvarargIn is set, then we take and keep this id.
  1679. if (pvarargIn && pvarargIn->vt == VT_I4)
  1680. {
  1681. _eUemLog = pvarargIn->lVal;
  1682. ASSERT(_eUemLog == UEMIND_SHELL || _eUemLog == UEMIND_BROWSER);
  1683. }
  1684. return S_OK;
  1685. }
  1686. }
  1687. else if (IsEqualGUID(CGID_DeskBand, *pguidCmdGroup))
  1688. {
  1689. switch (nCmdID)
  1690. {
  1691. case DBID_DELAYINIT:
  1692. _fDelayInit = TRUE;
  1693. break;
  1694. case DBID_FINISHINIT:
  1695. _fDelayInit = FALSE;
  1696. _RegisterToolbar();
  1697. break;
  1698. }
  1699. return S_OK;
  1700. }
  1701. return OLECMDERR_E_NOTSUPPORTED;
  1702. }
  1703. IShellFolder * CISFBand::GetSF()
  1704. {
  1705. ASSERT( _psf );
  1706. return _psf;
  1707. }
  1708. HWND CISFBand::GetHWND()
  1709. {
  1710. return _hwndTB;
  1711. }
  1712. REFTASKOWNERID CISFBand::GetTOID()
  1713. {
  1714. return TOID_ExtractImage;
  1715. }
  1716. HRESULT CISFBand::OnTranslatedChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  1717. {
  1718. if (lEvent == SHCNE_RMDIR && _IsEqualID(pidl1))
  1719. {
  1720. HRESULT hres = E_FAIL;
  1721. IBandSite *pbandSite;
  1722. if (_punkSite)
  1723. {
  1724. hres = _punkSite->QueryInterface(IID_IBandSite, (void **)&pbandSite);
  1725. if (EVAL(SUCCEEDED(hres)))
  1726. {
  1727. pbandSite->RemoveBand(_dwBandID);
  1728. pbandSite->Release();
  1729. }
  1730. }
  1731. return hres;
  1732. }
  1733. else
  1734. {
  1735. return CSFToolbar::OnTranslatedChange(lEvent, pidl1, pidl2);
  1736. }
  1737. }
  1738. HRESULT CISFBand::UpdateLogoCallback( DWORD dwItem, int iIcon, HBITMAP hImage, LPCWSTR pszCache, BOOL fCache )
  1739. {
  1740. int iItem = (int)dwItem;
  1741. HRESULT hr;
  1742. UINT uImage;
  1743. // catch if we are closing...
  1744. if ( _fClosing )
  1745. return NOERROR;
  1746. IMAGECACHEINFO rgInfo;
  1747. rgInfo.dwMask = ICIFLAG_NAME | ICIFLAG_LARGE | ICIFLAG_BITMAP | ICIFLAG_NOUSAGE;
  1748. rgInfo.cbSize = sizeof( rgInfo );
  1749. rgInfo.pszName = pszCache;
  1750. rgInfo.hBitmapLarge = hImage;
  1751. ASSERT(_pLogoCache);
  1752. if (_pLogoCache)
  1753. hr = _pLogoCache->AddImage( &rgInfo, &uImage );
  1754. else
  1755. hr = E_FAIL;
  1756. // catch if we are closing...
  1757. if ( _fClosing )
  1758. return NOERROR;
  1759. if ( SUCCEEDED( hr ))
  1760. {
  1761. // remember the icon to logo mapping....
  1762. AddIndicesToLogoList( iIcon, uImage );
  1763. // catch we are closing before we try and doa bloc
  1764. PostMessage( _hwndTB, TB_CHANGEBITMAP, iItem, uImage );
  1765. }
  1766. // stop delay painting when the last extract image task calls back
  1767. if (_fDelayPainting) {
  1768. if (_pTaskScheduler && _pTaskScheduler->CountTasks(TOID_NULL) == 1) {
  1769. _StopDelayPainting();
  1770. }
  1771. }
  1772. return hr;
  1773. }
  1774. // }
  1775. HRESULT CISFBand::_GetTitleW(LPWSTR pwszTitle, DWORD cchSize)
  1776. {
  1777. HRESULT hr = E_FAIL;
  1778. TraceMsg(TF_BAND, "Calling baseclass CISFBand::_GetTitleW");
  1779. if (!EVAL(pwszTitle))
  1780. return E_INVALIDARG;
  1781. *pwszTitle = 0;
  1782. if (_pidl)
  1783. {
  1784. hr = SHGetNameAndFlagsW(_pidl, SHGDN_NORMAL, pwszTitle, cchSize, NULL);
  1785. }
  1786. else if (_psf && !_fPSFBandDesktop)
  1787. {
  1788. #ifdef BUSTED
  1789. // BUGBUG (scotth): We cannot call GetDisplayNameOf with NULL pidl.
  1790. // We must change this code so _pidl is always
  1791. // valid, and key off a flag to determine whether
  1792. // to receive notifies. Remove this code once
  1793. // that is done.
  1794. STRRET strret;
  1795. if (SUCCEEDED(_psf->GetDisplayNameOf(NULL, SHGDN_NORMAL, &strret)))
  1796. StrRetToBufW(&strret, NULL, pwszTitle, cchSize);
  1797. #endif
  1798. }
  1799. return hr;
  1800. }
  1801. STDAPI NavigateToPIDL(IWebBrowser2* pwb, LPCITEMIDLIST pidl);
  1802. HRESULT FakeGetNavigateTarget(IShellFolder *psf, LPCITEMIDLIST pidl, LPITEMIDLIST *ppidl);
  1803. LRESULT CISFBand::_TryChannelSurfing(LPCITEMIDLIST pidl)
  1804. {
  1805. LRESULT lRet = 0;
  1806. ASSERT(_fChannels);
  1807. LPITEMIDLIST pidlTarget;
  1808. HRESULT hr = SHGetNavigateTarget(_psf, pidl, &pidlTarget, NULL);
  1809. // channel category folders hack.
  1810. if (FAILED(hr))
  1811. hr = FakeGetNavigateTarget(_psf, pidl, &pidlTarget);
  1812. if (SUCCEEDED(hr))
  1813. {
  1814. IWebBrowser2* pwb;
  1815. // n.b. careful! only one of GCB and C_OB up the refcnt
  1816. _GetChannelBrowser(&pwb);
  1817. if (SUCCEEDED(Channels_OpenBrowser(&pwb, pwb != NULL)))
  1818. {
  1819. lRet = 1; // success at this point
  1820. if (SUCCEEDED(NavigateToPIDL(pwb, pidlTarget)))
  1821. {
  1822. LPITEMIDLIST pidlFull = ILCombine(_pidl, pidl);
  1823. if (pidlFull)
  1824. {
  1825. VARIANT varURLpidl, flags;
  1826. flags.vt = VT_I4;
  1827. flags.lVal = navBrowserBar;
  1828. if (SUCCEEDED(InitVariantFromIDList(&varURLpidl, pidlFull)))
  1829. {
  1830. pwb->Navigate2(&varURLpidl, &flags, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  1831. VariantClear(&varURLpidl);
  1832. }
  1833. ILFree(pidlFull);
  1834. }
  1835. }
  1836. }
  1837. if (pwb)
  1838. pwb->Release();
  1839. ILFree(pidlTarget);
  1840. }
  1841. return lRet;
  1842. }
  1843. //*** _GetChannelBrowser -- find appropriate browser for surfing
  1844. // DESCRIPTION
  1845. // for the DTBrowser case, we fail (pwb=NULL, hr=S_FALSE) so that our
  1846. // caller will create a new SHBrowser (which can be put into theater mode).
  1847. // for the SHBrowser case, we find the top-level browser (so we'll navigate
  1848. // in-place).
  1849. HRESULT CISFBand::_GetChannelBrowser(IWebBrowser2 **ppwb)
  1850. {
  1851. HRESULT hr;
  1852. IServiceProvider *psp;
  1853. *ppwb = NULL; // assume failure
  1854. if (_fDesktop) {
  1855. ASSERT(*ppwb == NULL);
  1856. hr = S_FALSE;
  1857. }
  1858. else {
  1859. hr = IUnknown_QueryService(_punkSite, SID_STopLevelBrowser, IID_IServiceProvider, (void**)&psp);
  1860. ASSERT(SUCCEEDED(hr));
  1861. if (SUCCEEDED(hr)) {
  1862. hr = psp->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void **)ppwb);
  1863. ASSERT(SUCCEEDED(hr));
  1864. psp->Release();
  1865. }
  1866. }
  1867. return hr;
  1868. }
  1869. HRESULT IUnknown_SetBandInfoSFB(IUnknown *punkBand, BANDINFOSFB *pbi)
  1870. {
  1871. HRESULT hr = E_FAIL;
  1872. IShellFolderBand *pisfBand;
  1873. if (punkBand) {
  1874. hr = punkBand->QueryInterface(IID_IShellFolderBand, (void **)&pisfBand);
  1875. if (EVAL(SUCCEEDED(hr))) {
  1876. hr = pisfBand->SetBandInfoSFB(pbi);
  1877. pisfBand->Release();
  1878. }
  1879. }
  1880. return hr;
  1881. }
  1882. ///////////////////////////////////////////////////////////////////////////////////////////
  1883. ///////////////////////////CExtractImageTask///////////////////////////////////////////////
  1884. ///////////////////////////////////////////////////////////////////////////////////////////
  1885. // Warning
  1886. //
  1887. // The CLogoBase class cannot have a ref on the returned task
  1888. // since that would be a circular reference
  1889. //
  1890. // Warning
  1891. HRESULT CExtractImageTask_Create( CLogoBase *plb,
  1892. LPEXTRACTIMAGE pExtract,
  1893. LPCWSTR pszCache,
  1894. DWORD dwItem,
  1895. int iIcon,
  1896. DWORD dwFlags,
  1897. LPRUNNABLETASK * ppTask )
  1898. {
  1899. if ( !ppTask || !plb || !pExtract )
  1900. {
  1901. return E_INVALIDARG;
  1902. }
  1903. HRESULT hr = NOERROR;
  1904. CExtractImageTask * pNewTask = new CExtractImageTask( &hr,
  1905. plb,
  1906. pExtract,
  1907. pszCache,
  1908. dwItem,
  1909. iIcon,
  1910. dwFlags );
  1911. if ( !pNewTask )
  1912. {
  1913. return E_OUTOFMEMORY;
  1914. }
  1915. if ( FAILED( hr ))
  1916. {
  1917. pNewTask->Release();
  1918. return hr;
  1919. }
  1920. *ppTask = SAFECAST( pNewTask, IRunnableTask *);
  1921. return NOERROR;
  1922. }
  1923. /////////////////////////////////////////////////////////////////////////////////////////////////////
  1924. CExtractImageTask::CExtractImageTask( HRESULT * pHr, CLogoBase *plb, IExtractImage * pImage,
  1925. LPCWSTR pszCache, DWORD dwItem, int iIcon, DWORD dwFlags )
  1926. {
  1927. m_lState = IRTIR_TASK_NOT_RUNNING;
  1928. m_plb = plb;
  1929. m_plb->AddRef();
  1930. // cannot assume the band will kill us before it dies....
  1931. // hence we hold a reference
  1932. StrCpyNW(m_szPath, pszCache, ARRAYSIZE(m_szPath));
  1933. m_pExtract = pImage;
  1934. pImage->AddRef();
  1935. m_cRef = 1;
  1936. // use the upper bit of the flags to determine if we should always call....
  1937. m_dwFlags = dwFlags;
  1938. m_dwItem = dwItem;
  1939. m_iIcon = iIcon;
  1940. // Since the task moves from thread to thread,
  1941. // don't charge this thread for the objects we're using
  1942. }
  1943. /////////////////////////////////////////////////////////////////////////////////////////////////////
  1944. CExtractImageTask::~CExtractImageTask()
  1945. {
  1946. ATOMICRELEASE( m_pExtract );
  1947. ATOMICRELEASE( m_pTask );
  1948. if ( m_hBmp && !( m_dwFlags & EITF_SAVEBITMAP ))
  1949. {
  1950. DeleteObject( m_hBmp );
  1951. }
  1952. if(m_plb)
  1953. m_plb->Release();
  1954. }
  1955. //////////////////////////////////////////////////////////////////////////////////////////
  1956. STDMETHODIMP CExtractImageTask::QueryInterface( REFIID riid, void **ppvObj )
  1957. {
  1958. if ( !ppvObj )
  1959. {
  1960. return E_INVALIDARG;
  1961. }
  1962. if ( IsEqualIID( riid, IID_IUnknown ))
  1963. {
  1964. *ppvObj = SAFECAST( this, IUnknown *);
  1965. }
  1966. else if ( IsEqualIID( riid, IID_IRunnableTask ))
  1967. {
  1968. *ppvObj = SAFECAST( this, IRunnableTask *);
  1969. }
  1970. else
  1971. {
  1972. return E_NOINTERFACE;
  1973. }
  1974. AddRef();
  1975. return NOERROR;
  1976. }
  1977. //////////////////////////////////////////////////////////////////////////////////////////
  1978. STDMETHODIMP_ (ULONG) CExtractImageTask::AddRef()
  1979. {
  1980. return InterlockedIncrement( &m_cRef );
  1981. }
  1982. //////////////////////////////////////////////////////////////////////////////////////////
  1983. STDMETHODIMP_ (ULONG) CExtractImageTask::Release()
  1984. {
  1985. ASSERT( 0 != m_cRef );
  1986. ULONG cRef = InterlockedDecrement( &m_cRef );
  1987. if ( 0 == cRef )
  1988. {
  1989. delete this;
  1990. }
  1991. return cRef;
  1992. }
  1993. //////////////////////////////////////////////////////////////////////////////////////////
  1994. STDMETHODIMP CExtractImageTask::Run ( void )
  1995. {
  1996. HRESULT hr = E_FAIL;
  1997. if ( m_lState == IRTIR_TASK_RUNNING )
  1998. {
  1999. hr = S_FALSE;
  2000. }
  2001. else if ( m_lState == IRTIR_TASK_PENDING )
  2002. {
  2003. hr = E_FAIL;
  2004. }
  2005. else if ( m_lState == IRTIR_TASK_NOT_RUNNING )
  2006. {
  2007. LONG lRes = InterlockedExchange( & m_lState, IRTIR_TASK_RUNNING);
  2008. if ( lRes == IRTIR_TASK_PENDING )
  2009. {
  2010. m_lState = IRTIR_TASK_FINISHED;
  2011. return NOERROR;
  2012. }
  2013. // see if it supports IRunnableTask
  2014. m_pExtract->QueryInterface( IID_IRunnableTask, (void **) & m_pTask );
  2015. #ifdef UNIX
  2016. //Hey Guys : IE4.01 has an error - it returns the wrong VTABLE
  2017. //when this QI is done. We know how our VTABLEs are laid out
  2018. #else
  2019. // IE4.01 has an error - it returns the wrong VTABLE
  2020. // when this QI is done.
  2021. if((LPVOID)m_pTask == (LPVOID)m_pExtract)
  2022. {
  2023. m_pTask = m_pTask + 2; // This vtable is two ptrs away and is in fstree.cpp in shell32 in IE4.01
  2024. }
  2025. #endif
  2026. if ( m_lState == IRTIR_TASK_RUNNING )
  2027. {
  2028. // start the extractor....
  2029. hr = m_pExtract->Extract( &m_hBmp );
  2030. }
  2031. if (( SUCCEEDED( hr ) || ( hr != E_PENDING && (m_dwFlags & EITF_ALWAYSCALL))) && m_lState == IRTIR_TASK_RUNNING )
  2032. {
  2033. hr = InternalResume();
  2034. }
  2035. if ( m_lState != IRTIR_TASK_SUSPENDED || hr != E_PENDING )
  2036. {
  2037. m_lState = IRTIR_TASK_FINISHED;
  2038. }
  2039. }
  2040. return hr;
  2041. }
  2042. /////////////////////////////////////////////////////////////////////////////////////////////////////
  2043. STDMETHODIMP CExtractImageTask::Kill ( BOOL fWait )
  2044. {
  2045. if ( m_lState != IRTIR_TASK_RUNNING )
  2046. {
  2047. return S_FALSE;
  2048. }
  2049. LONG lRes = InterlockedExchange( &m_lState, IRTIR_TASK_PENDING );
  2050. if ( lRes == IRTIR_TASK_FINISHED )
  2051. {
  2052. m_lState = lRes;
  2053. return NOERROR;
  2054. }
  2055. // does it support IRunnableTask ? Can we kill it ?
  2056. HRESULT hr = E_NOTIMPL;
  2057. if ( m_pTask != NULL )
  2058. {
  2059. hr = m_pTask->Kill( FALSE );
  2060. }
  2061. return hr;
  2062. }
  2063. ///////////////////////////////////////////////////////////////////////////////////////
  2064. STDMETHODIMP CExtractImageTask::Suspend( void )
  2065. {
  2066. if ( !m_pTask )
  2067. {
  2068. return E_NOTIMPL;
  2069. }
  2070. if ( m_lState != IRTIR_TASK_RUNNING )
  2071. {
  2072. return E_FAIL;
  2073. }
  2074. LONG lRes = InterlockedExchange( &m_lState, IRTIR_TASK_SUSPENDED );
  2075. HRESULT hr = m_pTask->Suspend();
  2076. if ( SUCCEEDED( hr ))
  2077. {
  2078. lRes = (LONG) m_pTask->IsRunning();
  2079. if ( lRes == IRTIR_TASK_SUSPENDED )
  2080. {
  2081. m_lState = lRes;
  2082. }
  2083. }
  2084. else
  2085. {
  2086. m_lState = lRes;
  2087. }
  2088. return hr;
  2089. }
  2090. ////////////////////////////////////////////////////////////////////////////////////////
  2091. STDMETHODIMP CExtractImageTask::Resume( void )
  2092. {
  2093. if ( !m_pTask )
  2094. {
  2095. return E_NOTIMPL;
  2096. }
  2097. if ( m_lState != IRTIR_TASK_SUSPENDED )
  2098. {
  2099. return E_FAIL;
  2100. }
  2101. m_lState = IRTIR_TASK_RUNNING;
  2102. HRESULT hr = m_pTask->Resume();
  2103. if ( SUCCEEDED( hr ) || ( hr != E_PENDING && ( m_dwFlags & EITF_ALWAYSCALL )))
  2104. {
  2105. hr = InternalResume();
  2106. }
  2107. return hr;
  2108. }
  2109. /////////////////////////////////////////////////////////////////////////////////////////////////////
  2110. HRESULT CExtractImageTask::InternalResume()
  2111. {
  2112. HRESULT hr = NOERROR;
  2113. if ( m_dwFlags & EITF_ALWAYSCALL || m_hBmp )
  2114. {
  2115. // call the update function
  2116. hr = m_plb->UpdateLogoCallback( m_dwItem, m_iIcon, m_hBmp, m_szPath, TRUE );
  2117. }
  2118. m_lState = IRTIR_TASK_FINISHED;
  2119. return hr;
  2120. }
  2121. /////////////////////////////////////////////////////////////////////////////////////////////////////
  2122. STDMETHODIMP_( ULONG ) CExtractImageTask:: IsRunning ( void )
  2123. {
  2124. return m_lState;
  2125. }
  2126. ////////////////////////////////////////////////////////////////////////////////////////////////////
  2127. //////////////////////////////CLogoBase/////////////////////////////////////////////////////////////
  2128. ////////////////////////////////////////////////////////////////////////////////////////////////////
  2129. // static data...
  2130. IImageCache * CLogoBase::s_pSharedWideLogoCache = NULL;
  2131. long CLogoBase::s_lSharedWideLogosRef = 0;
  2132. HDSA CLogoBase::s_hdsaWideLogoIndices = NULL;
  2133. CRITICAL_SECTION CLogoBase::s_csSharedLogos = {0};
  2134. extern "C" void CLogoBase_Initialize( void )
  2135. {
  2136. CLogoBase::_Initialize();
  2137. }
  2138. extern "C" void CLogoBase_Cleanup( void )
  2139. {
  2140. CLogoBase::_Cleanup( );
  2141. }
  2142. void CLogoBase::_Initialize( void )
  2143. {
  2144. InitializeCriticalSection( &s_csSharedLogos );
  2145. }
  2146. void CLogoBase::_Cleanup( void )
  2147. {
  2148. DeleteCriticalSection( & s_csSharedLogos );
  2149. }
  2150. CLogoBase::CLogoBase( BOOL fWide )
  2151. {
  2152. // are we paletized, then use the global halftone palette ....
  2153. HDC hdcTmp = GetDC( NULL );
  2154. if (hdcTmp)
  2155. {
  2156. if (GetDeviceCaps( hdcTmp, RASTERCAPS) & RC_PALETTE)
  2157. {
  2158. ASSERT( g_hpalHalftone );
  2159. _hpalHalftone = g_hpalHalftone;
  2160. }
  2161. ReleaseDC( NULL, hdcTmp );
  2162. }
  2163. _fWide = fWide;
  2164. }
  2165. CLogoBase::~CLogoBase()
  2166. {
  2167. if (_pLogoCache || _pTaskScheduler)
  2168. {
  2169. ExitLogoView();
  2170. }
  2171. // NOTE: no palette release because we are using the global Halftone palette......
  2172. }
  2173. HRESULT CLogoBase::AddRefLogoCache( void )
  2174. {
  2175. if ( _fWide )
  2176. {
  2177. EnterCriticalSection( &s_csSharedLogos );
  2178. if ( !s_lSharedWideLogosRef )
  2179. {
  2180. if ( !s_hdsaWideLogoIndices )
  2181. {
  2182. s_hdsaWideLogoIndices = DSA_Create( sizeof( LogoIndex ), 5 );
  2183. if ( !s_hdsaWideLogoIndices )
  2184. {
  2185. LeaveCriticalSection( &s_csSharedLogos );
  2186. return E_OUTOFMEMORY;
  2187. }
  2188. }
  2189. ASSERT( s_hdsaWideLogoIndices );
  2190. ASSERT( !s_pSharedWideLogoCache );
  2191. // BUGBUG for now CoCreate one per view
  2192. HRESULT hr = CoCreateInstance( CLSID_ImageListCache,
  2193. NULL,
  2194. CLSCTX_INPROC_SERVER,
  2195. IID_IImageCache,
  2196. (void **) & s_pSharedWideLogoCache );
  2197. if ( FAILED( hr ))
  2198. {
  2199. LeaveCriticalSection( &s_csSharedLogos );
  2200. return hr;
  2201. }
  2202. }
  2203. ASSERT( s_pSharedWideLogoCache );
  2204. // bump up the ref and get a pointer to it...
  2205. s_lSharedWideLogosRef ++;
  2206. _pLogoCache = s_pSharedWideLogoCache;
  2207. _pLogoCache->AddRef();
  2208. _hdsaLogoIndices = s_hdsaWideLogoIndices;
  2209. LeaveCriticalSection( &s_csSharedLogos );
  2210. return NOERROR;
  2211. }
  2212. else
  2213. {
  2214. // non wide logo version we don't share because w eonly expect there ever to be one...
  2215. _hdsaLogoIndices = DSA_Create( sizeof( LogoIndex ), 5 );
  2216. if ( !_hdsaLogoIndices )
  2217. {
  2218. return E_OUTOFMEMORY;
  2219. }
  2220. // BUGBUG for now CoCreate one per view
  2221. return CoCreateInstance( CLSID_ImageListCache,
  2222. NULL,
  2223. CLSCTX_INPROC_SERVER,
  2224. IID_IImageCache,
  2225. (void **) & _pLogoCache );
  2226. }
  2227. }
  2228. HRESULT CLogoBase::ReleaseLogoCache( void )
  2229. {
  2230. if ( !_pLogoCache )
  2231. {
  2232. return S_FALSE;
  2233. }
  2234. ATOMICRELEASE(_pLogoCache);
  2235. if ( _fWide )
  2236. {
  2237. EnterCriticalSection( &s_csSharedLogos );
  2238. ASSERT( s_lSharedWideLogosRef > 0 );
  2239. s_lSharedWideLogosRef --;
  2240. if ( ! s_lSharedWideLogosRef )
  2241. {
  2242. // let go of the final ref.....
  2243. ATOMICRELEASE(s_pSharedWideLogoCache);
  2244. ASSERT( s_hdsaWideLogoIndices );
  2245. DSA_Destroy( s_hdsaWideLogoIndices );
  2246. s_hdsaWideLogoIndices = NULL;
  2247. }
  2248. LeaveCriticalSection( &s_csSharedLogos );
  2249. }
  2250. else
  2251. {
  2252. // free the HDSA
  2253. DSA_Destroy( _hdsaLogoIndices );
  2254. _hdsaLogoIndices = NULL;
  2255. }
  2256. return NOERROR;
  2257. }
  2258. HRESULT CLogoBase::InitLogoView( void )
  2259. {
  2260. HRESULT hr = AddRefLogoCache();
  2261. if (SUCCEEDED(hr))
  2262. {
  2263. hr = CoCreateInstance(CLSID_ShellTaskScheduler,
  2264. NULL,
  2265. CLSCTX_INPROC_SERVER,
  2266. IID_IShellTaskScheduler,
  2267. (void **) &_pTaskScheduler);
  2268. if (FAILED(hr))
  2269. {
  2270. ATOMICRELEASE(_pLogoCache);
  2271. }
  2272. else
  2273. {
  2274. _rgLogoSize.cx = ( _fWide ) ? LOGO_WIDE_WIDTH : LOGO_WIDTH ;
  2275. _rgLogoSize.cy = LOGO_HEIGHT;
  2276. IMAGECACHEINITINFO rgInfo;
  2277. rgInfo.cbSize = sizeof( rgInfo );
  2278. rgInfo.dwMask = ICIIFLAG_LARGE;
  2279. rgInfo.iStart = 0;
  2280. rgInfo.iGrow = 5;
  2281. // the color depth is currently the screen resolution...
  2282. int iColorRes = SHGetCurColorRes();
  2283. _dwClrDepth = (DWORD) iColorRes;
  2284. switch (iColorRes)
  2285. {
  2286. case 16 : rgInfo.dwFlags = ILC_COLOR16;
  2287. break;
  2288. case 24 :
  2289. case 32 : rgInfo.dwFlags = ILC_COLOR24;
  2290. break;
  2291. default : rgInfo.dwFlags = ILC_COLOR8;
  2292. }
  2293. rgInfo.rgSizeLarge = _rgLogoSize;
  2294. if (_pLogoCache)
  2295. hr = _pLogoCache->GetImageList(&rgInfo);
  2296. else
  2297. hr = E_UNEXPECTED;
  2298. if (FAILED(hr))
  2299. {
  2300. ATOMICRELEASE(_pLogoCache);
  2301. ATOMICRELEASE(_pTaskScheduler);
  2302. }
  2303. else
  2304. {
  2305. _himlLogos = rgInfo.himlLarge;
  2306. // GetImageList() will return S_FALSE if it was already created...
  2307. if ((hr == S_OK) && (iColorRes <= 8))
  2308. {
  2309. // init the color table so that it matches The "special halftone palette"
  2310. HPALETTE hpal = SHCreateShellPalette(NULL);
  2311. PALETTEENTRY rgColours[256];
  2312. RGBQUAD rgDIBColours[256];
  2313. ASSERT( hpal );
  2314. int nColours = GetPaletteEntries(hpal, 0, ARRAYSIZE(rgColours), rgColours);
  2315. // SHGetShellPalette should always return a 256 colour palette
  2316. ASSERT(nColours == ARRAYSIZE(rgColours));
  2317. // translate from the LOGPALETTE structure to the RGBQUAD structure ...
  2318. for (int iColour = 0; iColour < nColours; iColour ++)
  2319. {
  2320. rgDIBColours[iColour].rgbRed = rgColours[iColour].peRed;
  2321. rgDIBColours[iColour].rgbBlue = rgColours[iColour].peBlue;
  2322. rgDIBColours[iColour].rgbGreen = rgColours[iColour].peGreen;
  2323. rgDIBColours[iColour].rgbReserved = 0;
  2324. }
  2325. DeletePalette(hpal);
  2326. ImageList_SetColorTable(_himlLogos, 0, 256, rgDIBColours);
  2327. }
  2328. }
  2329. }
  2330. }
  2331. return hr;
  2332. }
  2333. HRESULT CLogoBase::ExitLogoView( void )
  2334. {
  2335. ATOMICRELEASE( _pTaskScheduler );
  2336. // the task scheduler callbacks can reference
  2337. // the logocache, so make sure you free the
  2338. // logo cache AFTER the task scheduler!
  2339. ReleaseLogoCache();
  2340. return NOERROR;
  2341. }
  2342. int CLogoBase::GetCachedLogoIndex( DWORD dwItem, LPCITEMIDLIST pidl, LPRUNNABLETASK *ppTask, DWORD * pdwPriority, DWORD *pdwFlags )
  2343. {
  2344. DWORD dwPassedFlags = 0;
  2345. if ( pdwFlags )
  2346. {
  2347. dwPassedFlags = *pdwFlags;
  2348. *pdwFlags = 0;
  2349. }
  2350. // No logo cache?
  2351. if (!_pLogoCache)
  2352. return 0;
  2353. ASSERT( pidl );
  2354. // HACK: this is used on browser only mode to tell what sort of logos we need...
  2355. UINT rgfFlags = _fWide;
  2356. LPEXTRACTIMAGE pImage = NULL;
  2357. int iImage = -1;
  2358. HRESULT hr = E_FAIL;
  2359. // IID_IEXtractLogo and IID_IExtractImage are the same interface, by using a new guid
  2360. // it means we can selectively decided what can logo in logo view...
  2361. hr = FakeGetUIObjectOf( GetSF(), pidl, &rgfFlags, IID_IExtractLogo, (void **) &pImage );
  2362. if ( SUCCEEDED( hr ))
  2363. {
  2364. // extract ....
  2365. HBITMAP hImage;
  2366. WCHAR szPath[MAX_PATH];
  2367. DWORD dwFlags = IEIFLAG_ASYNC | IEIFLAG_ASPECT | dwPassedFlags;
  2368. IMAGECACHEINFO rgInfo;
  2369. UINT uIndex;
  2370. BOOL fAsync;
  2371. DWORD dwPriority;
  2372. rgInfo.cbSize = sizeof( rgInfo );
  2373. hr = pImage->GetLocation( szPath, MAX_PATH, &dwPriority, &_rgLogoSize, _dwClrDepth, &dwFlags );
  2374. fAsync = ( hr == E_PENDING );
  2375. if ( SUCCEEDED( hr ) || fAsync )
  2376. {
  2377. // mask off the flags passed to use by the flags returned from the extractor...
  2378. if ( pdwFlags )
  2379. *pdwFlags = dwPassedFlags & dwFlags;
  2380. rgInfo.dwMask = ICIFLAG_NAME;
  2381. rgInfo.pszName = szPath;
  2382. hr = _pLogoCache->FindImage( &rgInfo, &uIndex );
  2383. if ( hr == S_OK )
  2384. {
  2385. ATOMICRELEASE( pImage );
  2386. return (int) uIndex;
  2387. }
  2388. if ( fAsync )
  2389. {
  2390. LPRUNNABLETASK pTaskTmp = NULL;
  2391. ASSERT( _pTaskScheduler );
  2392. // pass the icon index so we can find the right logo later...
  2393. int iIcon = SHMapPIDLToSystemImageListIndex(GetSF(), pidl, NULL);
  2394. hr = CExtractImageTask_Create( this,
  2395. pImage,
  2396. szPath,
  2397. dwItem,
  2398. iIcon,
  2399. 0,
  2400. &pTaskTmp );
  2401. if ( SUCCEEDED( hr ))
  2402. {
  2403. if ( !ppTask )
  2404. {
  2405. hr = AddTaskToQueue( pTaskTmp, dwPriority, dwItem );
  2406. pTaskTmp->Release();
  2407. }
  2408. else
  2409. {
  2410. * ppTask = pTaskTmp;
  2411. ASSERT( pdwPriority );
  2412. *pdwPriority = dwPriority;
  2413. }
  2414. }
  2415. else if ( ppTask )
  2416. {
  2417. *ppTask = NULL;
  2418. }
  2419. // if all this failed, then we will just end up with a default
  2420. // logo. This is only likely to fail in low memory conditions,
  2421. // so that will be fine.
  2422. // if this SUCCEEDED we will drop through to pick up a defualt piccy for now.
  2423. }
  2424. else
  2425. {
  2426. // otherwise extract synchronously.......
  2427. hr = pImage->Extract( &hImage );
  2428. if ( SUCCEEDED( hr ))
  2429. {
  2430. rgInfo.dwMask = ICIFLAG_NAME | ICIFLAG_LARGE | ICIFLAG_BITMAP | ICIFLAG_NOUSAGE;
  2431. rgInfo.hBitmapLarge = hImage;
  2432. hr = _pLogoCache->AddImage( &rgInfo, &uIndex );
  2433. DeleteObject( hImage );
  2434. }
  2435. if ( SUCCEEDED( hr ))
  2436. {
  2437. iImage = (int ) uIndex;
  2438. }
  2439. }
  2440. }
  2441. }
  2442. ATOMICRELEASE( pImage );
  2443. return iImage;
  2444. }
  2445. int CLogoBase::GetLogoIndex( DWORD dwItem, LPCITEMIDLIST pidl, LPRUNNABLETASK *ppTask, DWORD * pdwPriority, DWORD *pdwFlags )
  2446. {
  2447. int iImage = GetCachedLogoIndex(dwItem, pidl, ppTask, pdwPriority, pdwFlags );
  2448. if ( iImage == -1 )
  2449. {
  2450. // always pass FALSE, we want the proper ICON, cdfview no longer hits the
  2451. // wire for the icon so we can safely ask for the correct icon.
  2452. iImage = GetDefaultLogo( pidl, FALSE);
  2453. }
  2454. return iImage;
  2455. }
  2456. HRESULT CLogoBase::AddTaskToQueue( LPRUNNABLETASK pTask, DWORD dwPriority, DWORD dwItem )
  2457. {
  2458. ASSERT( _pTaskScheduler );
  2459. return _pTaskScheduler->AddTask( pTask, GetTOID(), dwItem, dwPriority );
  2460. }
  2461. int CLogoBase::GetDefaultLogo( LPCITEMIDLIST pidl, BOOL fQuick )
  2462. {
  2463. // Get icon to draw from
  2464. int iIndex = -1;
  2465. if ( !fQuick )
  2466. {
  2467. iIndex = SHMapPIDLToSystemImageListIndex(GetSF(), pidl, NULL);
  2468. }
  2469. if (iIndex < 0)
  2470. {
  2471. iIndex = II_DOCNOASSOC;
  2472. }
  2473. WCHAR wszText[MAX_PATH];
  2474. wszText[0] = 0;
  2475. STRRET strret;
  2476. HRESULT hr = GetSF()->GetDisplayNameOf( pidl, SHGDN_NORMAL, &strret );
  2477. if ( SUCCEEDED( hr ))
  2478. {
  2479. StrRetToBufW(&strret, pidl, wszText, ARRAYSIZE(wszText));
  2480. }
  2481. UINT uCacheIndex = (UINT) -1;
  2482. if (_pLogoCache) // We didn't have one in stress.
  2483. {
  2484. IMAGECACHEINFO rgInfo;
  2485. rgInfo.cbSize = sizeof( rgInfo );
  2486. rgInfo.dwMask = ICIFLAG_NAME | ICIFLAG_INDEX;
  2487. rgInfo.pszName = wszText;
  2488. rgInfo.iIndex = iIndex;
  2489. hr = _pLogoCache->FindImage( &rgInfo, &uCacheIndex );
  2490. if ( hr == S_OK )
  2491. {
  2492. return uCacheIndex;
  2493. }
  2494. HBITMAP hDef;
  2495. hr = CreateDefaultLogo( iIndex, _rgLogoSize.cx, _rgLogoSize.cy, wszText, &hDef );
  2496. if ( SUCCEEDED( hr ))
  2497. {
  2498. rgInfo.hBitmapLarge = hDef;
  2499. rgInfo.hMaskLarge = NULL;
  2500. rgInfo.dwMask = ICIFLAG_NAME | ICIFLAG_INDEX | ICIFLAG_BITMAP | ICIFLAG_LARGE;
  2501. hr = _pLogoCache->AddImage( &rgInfo, &uCacheIndex );
  2502. if ( FAILED(hr ))
  2503. {
  2504. uCacheIndex = (UINT) -1;
  2505. }
  2506. else
  2507. {
  2508. // remember the index of the logo
  2509. AddIndicesToLogoList( iIndex, uCacheIndex );
  2510. }
  2511. DeleteObject( hDef );
  2512. }
  2513. }
  2514. return (int) uCacheIndex;
  2515. }
  2516. #define DXFUDGE 4
  2517. #define COLORTEXT RGB(255,255,255)
  2518. #define COLORBK RGB(0,0,0)
  2519. HRESULT CLogoBase::CreateDefaultLogo(int iIcon, int cxLogo, int cyLogo, LPCTSTR pszText, HBITMAP * phBmpLogo)
  2520. {
  2521. HRESULT hr = E_OUTOFMEMORY;
  2522. HBITMAP hbmp = NULL;
  2523. HIMAGELIST himl;
  2524. int cxIcon, cyIcon;
  2525. int x, y, dx, dy;
  2526. // get the small icons....
  2527. Shell_GetImageLists(NULL, &himl);
  2528. ImageList_GetIconSize(himl, &cxIcon, &cyIcon);
  2529. // Calculate position info. We assume logos are wider than they are tall.
  2530. //
  2531. ASSERT(cxLogo >= cyLogo);
  2532. // Put the icon on the left
  2533. x = 2;
  2534. // Center the icon vertically
  2535. if (cyIcon <= cyLogo)
  2536. {
  2537. y = (cyLogo - cyIcon) / 2;
  2538. dy = cyIcon;
  2539. dx = cxIcon;
  2540. }
  2541. else
  2542. {
  2543. y = 0;
  2544. dy = cyLogo;
  2545. // keep shrinkage proportional
  2546. dx = MulDiv(cxIcon, cyIcon, cyLogo);
  2547. }
  2548. // get ready to draw
  2549. HDC hTBDC = GetDC( GetHWND());
  2550. if ( !hTBDC )
  2551. {
  2552. return E_FAIL;
  2553. }
  2554. HDC hdc = CreateCompatibleDC( hTBDC );
  2555. if (hdc)
  2556. {
  2557. RECT rc;
  2558. int dx, dy, x, y;
  2559. SIZE size;
  2560. hbmp = CreateCompatibleBitmap(hTBDC, cxLogo, cyLogo);
  2561. if (hbmp)
  2562. {
  2563. HGDIOBJ hTmp = SelectObject(hdc, hbmp);
  2564. HPALETTE hpalOld;
  2565. HFONT hfont, hfontOld;
  2566. if ( _hpalHalftone )
  2567. {
  2568. hpalOld = SelectPalette( hdc, _hpalHalftone, TRUE );
  2569. // LINTASSERT(hpalOld || !hpalOld); // 0 semi-ok for SelectPalette
  2570. RealizePalette( hdc );
  2571. }
  2572. SetMapMode( hdc, MM_TEXT );
  2573. rc.left = rc.top = 0;
  2574. rc.bottom = cyLogo;
  2575. rc.right = cxLogo;
  2576. SHFillRectClr(hdc, &rc, COLORBK);
  2577. // draw the icon into the memory DC.
  2578. ImageList_GetIconSize(himl, &dx, &dy);
  2579. x = DXFUDGE;
  2580. y = ((cyLogo- dy) >> 1);
  2581. ImageList_Draw( himl, iIcon, hdc, x, y, ILD_TRANSPARENT );
  2582. hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  2583. hfontOld = hfont ? (HFONT)SelectObject(hdc, hfont) : NULL;
  2584. GetTextExtentPoint32(hdc, pszText, lstrlen(pszText), &size);
  2585. x += (dx + DXFUDGE);
  2586. y = ((cyLogo- size.cy) >> 1);
  2587. rc.left = x;
  2588. UINT eto = ETO_CLIPPED;
  2589. SetTextColor(hdc, COLORTEXT);
  2590. SetBkMode(hdc, TRANSPARENT);
  2591. ExtTextOut(hdc, x, y, eto, &rc
  2592. , pszText, lstrlen(pszText), NULL);
  2593. if (hfontOld)
  2594. SelectObject(hdc, hfontOld);
  2595. if (hfont)
  2596. DeleteObject(hfont);
  2597. if ( _hpalHalftone )
  2598. {
  2599. (void) SelectPalette( hdc, hpalOld, TRUE );
  2600. RealizePalette( hdc );
  2601. }
  2602. // remove the final bitmap
  2603. SelectObject( hdc, hTmp );
  2604. hr = S_OK;
  2605. if (FAILED(hr))
  2606. {
  2607. DeleteObject(hbmp);
  2608. hbmp = NULL;
  2609. }
  2610. }
  2611. DeleteDC(hdc);
  2612. }
  2613. ReleaseDC( GetHWND(), hTBDC );
  2614. *phBmpLogo = hbmp;
  2615. return hr;
  2616. }
  2617. HRESULT CLogoBase::FlushLogoCache( )
  2618. {
  2619. HRESULT hr = E_UNEXPECTED;
  2620. if (_pLogoCache)
  2621. {
  2622. // forcibly clear out the logo cache so the items get refetched ...
  2623. _pLogoCache->Flush(TRUE);
  2624. hr = S_OK;
  2625. }
  2626. return hr;
  2627. }
  2628. HRESULT CLogoBase::DitherBitmap( HBITMAP hBmp, HBITMAP * phBmpNew )
  2629. {
  2630. // if ( !phBmpNew )
  2631. // {
  2632. // return E_INVALIDARG;
  2633. // }
  2634. //
  2635. // if ( _dwClrDepth > 8)
  2636. // {
  2637. // *phBmpNew = hBmp;
  2638. // return S_FALSE;
  2639. // }
  2640. //
  2641. // IIntDitherer * pDither;
  2642. // HRESULT hr = CoCreateInstance( CLSID_IntDitherer,
  2643. // NULL,
  2644. // CLSCTX_INPROC_SERVER,
  2645. // IID_IIntDitherer,
  2646. // (void **) & pDither );
  2647. // if ( FAILED( hr ))
  2648. // {
  2649. // return hr;
  2650. // }
  2651. //
  2652. // static BYTE rgb[32768];
  2653. // static BOOL fInit = FALSE;
  2654. //
  2655. // if ( !fInit )
  2656. // {
  2657. // // init the inverse color map table
  2658. // SHGetInverseCMAP( rgb, sizeof( rgb ));
  2659. // fInit = TRUE;
  2660. // }
  2661. //
  2662. // HDC hMemDc = CreateCompatibleDC( NULL );
  2663. // if ( !hMemDc )
  2664. // {
  2665. // pDither->Release();
  2666. // return E_FAIL;
  2667. // }
  2668. //
  2669. // HBITMAP hOld = SelectObject( hdc, hBmp );
  2670. //
  2671. // BITMAPINFO bi;
  2672. //
  2673. // ZeroMemory( &bi, sizeof( bi ));
  2674. // bi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
  2675. // bi.bmiHeader.biBitCount = 0;
  2676. // bi.bmiHeader.biCompression = 0;
  2677. //
  2678. // // get the header information....
  2679. // iRet = GetDIBits( hMemDc, hBmp, 0, 0, NULL, &bi, DIB_RGB_COLORS );
  2680. // if ( iRet != 0 )
  2681. // {
  2682. // LPVOID pBuffer, pBits;
  2683. // int iOffset = 0;
  2684. //
  2685. // if ( bi.bmiHeader.biCompression == BI_BITFIELDS )
  2686. // {
  2687. // iOffset = sizeof( DWORD ) * 3;
  2688. // }
  2689. // else if ( bi.bmiHeader.biBitCount <= 8 )
  2690. // {
  2691. // if ( bi.bmiHeader.biClrUsed )
  2692. // {
  2693. // iOffset = sizeof( RGBQUAD ) * bi.bmiHeader.biClrUsed;
  2694. // }
  2695. // else
  2696. // {
  2697. // iOffset = (1 << bi.bmiHeader.biBitCount) * sizeof( RGBQUAD );
  2698. // }
  2699. // }
  2700. //
  2701. // bi.bmiHeader.biHeight = iHeight;
  2702. //
  2703. // // calc
  2704. // pBuffer = LocalAlloc( LPTR, sizeof( BITMAPINFOHEADER ) +
  2705. // bi.bmiHeader.biSizeImage +
  2706. // iOffset );
  2707. //
  2708. // // calc the size of the colour table so we put the data afterwards...
  2709. // pBits = (( LPBYTE )pBuffer ) + sizeof( BITMAPINFOHEADER ) + iOffset;
  2710. //
  2711. // CopyMemory( pBuffer, &bi, sizeof( BITMAPINFOHEADER ) );
  2712. // iRet = GetDIBits( hMemDc, hBmp, 0, iHeight, pBits,
  2713. // ( LPBITMAPINFO )pBuffer, DIB_RGB_COLORS );
  2714. //
  2715. //
  2716. // // we know we are going to 256 colour bitmap, so create a DIBSECTION as the destination ...
  2717. // pDither->DitherTo8bpp( BYTE * pDestBits, LONG nDestPitch,
  2718. // BYTE * pSrcBits, LONG nSrcPitch, REFGUID bfidSrc,
  2719. // RGBQUAD * prgbDestColors, RGBQUAD * prgbSrcColors,
  2720. // rgb,
  2721. // LONG x, LONG y, LONG cx, LONG cy,
  2722. // -1, -1);
  2723. // }
  2724. // pDither->Release();
  2725. ASSERT( FALSE );
  2726. return E_NOTIMPL;
  2727. }
  2728. int CLogoBase::AddIndicesToLogoList( int iIcon, UINT uIndex )
  2729. {
  2730. int iRet = -1;
  2731. LogoIndex * pIndex;
  2732. LogoIndex rgNew;
  2733. rgNew.iIcon = iIcon;
  2734. rgNew.iLogo = (int) uIndex;
  2735. if ( _fWide )
  2736. {
  2737. EnterCriticalSection( &s_csSharedLogos );
  2738. }
  2739. // scan to see if we have an extact match already in there...
  2740. for ( int n = 0; n < DSA_GetItemCount( _hdsaLogoIndices ); n ++ )
  2741. {
  2742. pIndex = (LogoIndex *) DSA_GetItemPtr( _hdsaLogoIndices, n );
  2743. ASSERT( pIndex );
  2744. if ( pIndex->iLogo == (int) uIndex )
  2745. {
  2746. // set the icon just incase it changed...
  2747. pIndex->iIcon = iIcon;
  2748. iRet = n;
  2749. break;
  2750. }
  2751. }
  2752. if ( iRet == -1 )
  2753. {
  2754. iRet = DSA_AppendItem( _hdsaLogoIndices, &rgNew );
  2755. }
  2756. if ( _fWide )
  2757. {
  2758. LeaveCriticalSection( &s_csSharedLogos );
  2759. }
  2760. return iRet;
  2761. }
  2762. int CLogoBase::FindLogoFromIcon( int iIcon, int * piLastLogo )
  2763. {
  2764. int iRet = -1;
  2765. if ( !piLastLogo )
  2766. {
  2767. return -1;
  2768. }
  2769. LogoIndex * pIndex;
  2770. if ( _fWide )
  2771. {
  2772. EnterCriticalSection( &s_csSharedLogos );
  2773. }
  2774. for ( int n = *piLastLogo + 1; n < DSA_GetItemCount( _hdsaLogoIndices ); n ++ )
  2775. {
  2776. pIndex = (LogoIndex *) DSA_GetItemPtr( _hdsaLogoIndices, n );
  2777. ASSERT( pIndex );
  2778. if ( pIndex->iIcon == iIcon )
  2779. {
  2780. *piLastLogo = n;
  2781. iRet = pIndex->iLogo;
  2782. break;
  2783. }
  2784. }
  2785. if ( _fWide )
  2786. {
  2787. LeaveCriticalSection( &s_csSharedLogos );
  2788. }
  2789. return iRet;
  2790. }
  2791. HRESULT CISFBand_CreateEx(IShellFolder* psf, LPCITEMIDLIST pidl, REFIID riid, void **ppv)
  2792. {
  2793. *ppv = NULL;
  2794. HRESULT hr = E_FAIL;
  2795. if (psf || pidl)
  2796. {
  2797. IShellFolderBand *psfb;
  2798. hr = CoCreateInstance(CLSID_ISFBand, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellFolderBand, &psfb));
  2799. if (SUCCEEDED(hr))
  2800. {
  2801. hr = psfb->InitializeSFB(psf, pidl);
  2802. if (SUCCEEDED(hr))
  2803. {
  2804. hr = psfb->QueryInterface(riid, ppv);
  2805. }
  2806. psfb->Release();
  2807. }
  2808. }
  2809. return hr;
  2810. }