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

1951 lines
49 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // iconhand.cpp
  4. //
  5. // The registered icon handler for cdf files. This handler returns icons for
  6. // .cdf files.
  7. //
  8. // History:
  9. //
  10. // 3/21/97 edwardp Created.
  11. //
  12. ////////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Includes
  15. //
  16. #include "stdinc.h"
  17. #include "resource.h"
  18. #include "cdfidl.h"
  19. #include "xmlutil.h"
  20. #include "persist.h"
  21. #include "iconhand.h"
  22. #include "exticon.h"
  23. #include "cdfview.h"
  24. #include "tooltip.h"
  25. #include "dll.h"
  26. #include "chanapi.h"
  27. #include <mluisupp.h>
  28. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  29. //
  30. // *** MakeXMLErrorURL() ***
  31. //
  32. // Set the error based on the IXMLDocument * passed in
  33. // Upon return CParseError will in an error state no matter what
  34. // although it may not be in the CParseError::ERR_XML state
  35. //
  36. // This function returns the approriate URL to navigate to
  37. // given the current error. Always changes *ppsz, but *ppsz maybe NULL
  38. //
  39. ////////////////////////////////////////////////////////////////////////////////
  40. #define CDFERROR_MAX_FOUND 100 // max char length for xml error found string
  41. #define CDFERROR_MAX_EXPECTED 100 // max char length for xml error expected string
  42. // format string for wsprintf of res:// ... URL
  43. const LPTSTR CDFERROR_URL_FORMAT_TRAILER = TEXT("#%u#%ls#%ls");
  44. // this is the number or extra chars (incl null) that CDFERROR_URL_FORMAT_TRAILER
  45. // may have in comparison to the output buffer of wsprinf
  46. const unsigned int CDFERROR_URL_FORMAT_EXTRA = 6;
  47. // upper char # bound on result of building res URL
  48. const unsigned CDFERROR_MAX_URL_LENGTH =
  49. 6 + // "res://"
  50. MAX_PATH + // path to resource DLL
  51. 1 + // "/"
  52. ARRAYSIZE(SZH_XMLERRORPAGE) + // "xmlerror.htm"
  53. ARRAYSIZE(CDFERROR_URL_FORMAT_TRAILER) +
  54. _INTEGRAL_MAX_BITS +
  55. CDFERROR_MAX_EXPECTED +
  56. CDFERROR_MAX_FOUND;
  57. // upper char # bound on result of InternetCanonicalizeUrl
  58. // with result from wsprintf with CDFERROR_URL_FORMAT
  59. // for each funky char in the found and expected substrs, might be encoded as "%xx"
  60. const unsigned CDFERROR_MAX_URL_LENGTH_ENCODED =
  61. CDFERROR_MAX_URL_LENGTH + 2*(CDFERROR_MAX_EXPECTED + CDFERROR_MAX_FOUND);
  62. HRESULT MakeXMLErrorURL( LPTSTR pszRet, DWORD dwRetLen, IXMLDocument *pXMLDoc )
  63. {
  64. IXMLError *pXMLError = NULL;
  65. XML_ERROR xmle = { 0 };
  66. HRESULT hr;
  67. ASSERT(pXMLDoc);
  68. hr =
  69. ( pXMLDoc ? pXMLDoc->QueryInterface(IID_IXMLError, (void **)&pXMLError) :
  70. E_INVALIDARG );
  71. if ( SUCCEEDED(hr) )
  72. {
  73. ASSERT(pXMLError);
  74. hr = pXMLError->GetErrorInfo(&xmle);
  75. if ( SUCCEEDED(hr) )
  76. {
  77. TCHAR szTemp[CDFERROR_MAX_URL_LENGTH];
  78. WCHAR szExpected[CDFERROR_MAX_EXPECTED];
  79. WCHAR szFound[CDFERROR_MAX_FOUND];
  80. StrCpyNW( szExpected, xmle._pszExpected, ARRAYSIZE(szExpected) );
  81. StrCpyNW( szFound, xmle._pszFound, ARRAYSIZE(szFound) );
  82. // fill in the "res://<path>\cdfvwlc.dll" part of the res URL
  83. hr = MLBuildResURLWrap(TEXT("cdfvwlc.dll"),
  84. g_hinst,
  85. ML_CROSSCODEPAGE,
  86. SZH_XMLERRORPAGE,
  87. szTemp,
  88. ARRAYSIZE(szTemp),
  89. TEXT("cdfview.dll"));
  90. if (SUCCEEDED(hr))
  91. {
  92. int nCharsWritten;
  93. int count;
  94. nCharsWritten = lstrlen(szTemp);
  95. count = wnsprintf(szTemp+nCharsWritten, ARRAYSIZE(szTemp)-nCharsWritten,
  96. CDFERROR_URL_FORMAT_TRAILER, xmle._nLine, szExpected, szFound );
  97. if ( count + CDFERROR_URL_FORMAT_EXTRA < ARRAYSIZE(CDFERROR_URL_FORMAT_TRAILER) )
  98. {
  99. // not all the chars were successfully written
  100. hr = E_FAIL;
  101. }
  102. else
  103. if ( !InternetCanonicalizeUrl( szTemp, pszRet, &dwRetLen, 0 ) )
  104. hr = E_FAIL;
  105. TraceMsg(TF_CDFPARSE, "Parse error string created: %s", pszRet );
  106. }
  107. SysFreeString(xmle._pszFound);
  108. SysFreeString(xmle._pszExpected);
  109. SysFreeString(xmle._pchBuf);
  110. }
  111. else
  112. {
  113. TraceMsg(TF_CDFPARSE, "Could not get IXMLError error info" );
  114. }
  115. pXMLError->Release();
  116. }
  117. else
  118. {
  119. TraceMsg(TF_CDFPARSE, "Could not get IXMLError" );
  120. }
  121. return hr;
  122. }
  123. //
  124. // Constructor and destructor.
  125. //
  126. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  127. //
  128. // *** CIconHandler::CIconHandler ***
  129. //
  130. // Constructor.
  131. //
  132. ////////////////////////////////////////////////////////////////////////////////
  133. CIconHandler::CIconHandler (
  134. void
  135. )
  136. : m_cRef(1)
  137. {
  138. ASSERT(NULL == m_pIExtractIcon);
  139. ASSERT(NULL == m_bstrImageURL);
  140. ASSERT(NULL == m_bstrImageWideURL);
  141. ASSERT(NULL == m_pszErrURL);
  142. TraceMsg(TF_OBJECTS, "+ handler object");
  143. DllAddRef();
  144. return;
  145. }
  146. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  147. //
  148. // *** CIconHandler::~CIconHandler ***
  149. //
  150. // Destructor.
  151. //
  152. ////////////////////////////////////////////////////////////////////////////////
  153. CIconHandler::~CIconHandler (
  154. void
  155. )
  156. {
  157. ASSERT(0 == m_cRef);
  158. if (m_pIExtractIcon)
  159. m_pIExtractIcon->Release();
  160. if (m_bstrImageURL)
  161. SysFreeString(m_bstrImageURL);
  162. if (m_bstrImageWideURL)
  163. SysFreeString(m_bstrImageWideURL);
  164. if (m_pcdfidl)
  165. CDFIDL_Free(m_pcdfidl);
  166. if (m_pszErrURL)
  167. delete[] m_pszErrURL;
  168. //
  169. // Matching Release for the constructor Addref.
  170. //
  171. TraceMsg(TF_OBJECTS, "- handler object");
  172. DllRelease();
  173. return;
  174. }
  175. //
  176. // IUnknown methods.
  177. //
  178. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  179. //
  180. // *** CIconHandler::QueryInterface ***
  181. //
  182. // CIconHandler QI.
  183. //
  184. ////////////////////////////////////////////////////////////////////////////////
  185. STDMETHODIMP
  186. CIconHandler::QueryInterface (
  187. REFIID riid,
  188. void **ppv
  189. )
  190. {
  191. ASSERT(ppv);
  192. HRESULT hr;
  193. *ppv = NULL;
  194. if (IID_IUnknown == riid || IID_IExtractIcon == riid)
  195. {
  196. *ppv = (IExtractIcon*)this;
  197. }
  198. #ifdef UNICODE
  199. else if (IID_IExtractIconA == riid)
  200. {
  201. *ppv = (IExtractIconA*)this;
  202. }
  203. #endif
  204. else if (IID_IPersistFile == riid || IID_IPersist == riid)
  205. {
  206. *ppv = (IPersistFile*)this;
  207. }
  208. else if (IID_IPersistFolder == riid)
  209. {
  210. *ppv = (IPersistFolder*)this;
  211. }
  212. else if (IID_IExtractImage == riid || IID_IExtractLogo == riid)
  213. {
  214. *ppv = (IExtractImage*)this;
  215. }
  216. else if (IID_IRunnableTask == riid)
  217. {
  218. *ppv = (IRunnableTask*)this;
  219. }
  220. if (*ppv)
  221. {
  222. ((IUnknown*)*ppv)->AddRef();
  223. hr = S_OK;
  224. }
  225. //
  226. // REVIEW: QI on the following two objects doesn't come here.
  227. //
  228. else if (IID_IShellLink == riid
  229. #ifdef UNICODE
  230. || IID_IShellLinkA == riid
  231. #endif
  232. )
  233. {
  234. if (!m_bCdfParsed)
  235. ParseCdfShellLink();
  236. if (m_pcdfidl)
  237. {
  238. hr = QueryInternetShortcut(m_pcdfidl, riid, ppv);
  239. }
  240. else
  241. {
  242. if ( m_pszErrURL && *m_pszErrURL)
  243. {
  244. hr = QueryInternetShortcut(m_pszErrURL, riid, ppv);
  245. }
  246. else
  247. {
  248. hr = E_FAIL;
  249. }
  250. }
  251. }
  252. else if (IID_IQueryInfo == riid)
  253. {
  254. hr = ParseCdfInfoTip(ppv);
  255. }
  256. else
  257. {
  258. hr = E_NOINTERFACE;
  259. }
  260. ASSERT((SUCCEEDED(hr) && *ppv) || (FAILED(hr) && NULL == *ppv));
  261. return hr;
  262. }
  263. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  264. //
  265. // *** CIconHandler::AddRef ***
  266. //
  267. // CExtractIcon AddRef.
  268. //
  269. ////////////////////////////////////////////////////////////////////////////////
  270. STDMETHODIMP_(ULONG)
  271. CIconHandler::AddRef (
  272. void
  273. )
  274. {
  275. ASSERT(m_cRef != 0);
  276. ASSERT(m_cRef < (ULONG)-1);
  277. return ++m_cRef;
  278. }
  279. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  280. //
  281. // *** CIconHandler::Release ***
  282. //
  283. // CIconHandler Release.
  284. //
  285. ////////////////////////////////////////////////////////////////////////////////
  286. STDMETHODIMP_(ULONG)
  287. CIconHandler::Release (
  288. void
  289. )
  290. {
  291. ASSERT (m_cRef != 0);
  292. ULONG cRef = --m_cRef;
  293. if (0 == cRef)
  294. delete this;
  295. return cRef;
  296. }
  297. //
  298. // IExtractIcon methods.
  299. //
  300. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  301. //
  302. // *** CIconHandler::GetIconLocation ***
  303. //
  304. //
  305. // Description:
  306. // Returns a name index pair for the icon associated with this cdf item.
  307. //
  308. // Parameters:
  309. // [In] uFlags - GIL_FORSHELL, GIL_OPENICON.
  310. // [Out] szIconFile - The address of the buffer that receives the associated
  311. // icon name. It can be a filename, but doesn't have to
  312. // be.
  313. // [In] cchMax - Size of the buffer that receives the icon location.
  314. // [Out] piIndex - A pointer that receives the icon's index.
  315. // [Out] pwFlags - A pointer the receives flags about the icon.
  316. //
  317. // Return:
  318. // S_OK if an was found.
  319. // S_FALSE if the shell should supply a default icon.
  320. //
  321. // Comments:
  322. //
  323. //
  324. ////////////////////////////////////////////////////////////////////////////////
  325. STDMETHODIMP
  326. CIconHandler::GetIconLocation(
  327. UINT uFlags,
  328. LPTSTR szIconFile,
  329. UINT cchMax,
  330. int *piIndex,
  331. UINT *pwFlags
  332. )
  333. {
  334. ASSERT(szIconFile);
  335. ASSERT(piIndex);
  336. ASSERT(pwFlags);
  337. HRESULT hr;
  338. TraceMsg(TF_CDFICON, "<IN > CIconHandler::GetIconLocation (Icon) tid:0x%x",
  339. GetCurrentThreadId());
  340. if (uFlags & GIL_ASYNC)
  341. {
  342. hr = E_PENDING;
  343. }
  344. else
  345. {
  346. hr = E_FAIL;
  347. if ( IsDefaultChannel())
  348. {
  349. m_bstrImageURL = CPersist::ReadFromIni( TSTR_INI_ICON );
  350. if ( m_bstrImageURL )
  351. {
  352. ASSERT( !m_pIExtractIcon );
  353. m_pIExtractIcon = (IExtractIcon*)new CExtractIcon( m_bstrImageURL );
  354. }
  355. }
  356. if (!m_pIExtractIcon && !m_bCdfParsed)
  357. ParseCdfIcon();
  358. if (m_pIExtractIcon)
  359. {
  360. hr = m_pIExtractIcon->GetIconLocation(uFlags, szIconFile, cchMax,
  361. piIndex, pwFlags);
  362. }
  363. if (FAILED(hr) ||
  364. (StrEql(szIconFile, g_szModuleName) &&
  365. -IDI_CHANNEL == *piIndex) )
  366. {
  367. //
  368. // Try and get the icon out of the desktop.ini file.
  369. //
  370. m_bstrImageURL = CPersist::ReadFromIni(TSTR_INI_ICON);
  371. if (m_bstrImageURL)
  372. {
  373. BOOL bRemovePrefix =
  374. (0 == StrCmpNIW(L"file://", m_bstrImageURL, 7));
  375. if (SHUnicodeToTChar(
  376. bRemovePrefix ? m_bstrImageURL + 7 : m_bstrImageURL,
  377. szIconFile, cchMax))
  378. {
  379. LPTSTR pszExt = PathFindExtension(szIconFile);
  380. if (*pszExt != TEXT('.') ||
  381. 0 != StrCmpI(pszExt, TSTR_ICO_EXT))
  382. {
  383. *piIndex = INDEX_IMAGE;
  384. MungePath(szIconFile);
  385. }
  386. else
  387. {
  388. *piIndex = 0;
  389. *pwFlags = 0;
  390. }
  391. hr = S_OK;
  392. }
  393. }
  394. }
  395. if (FAILED(hr))
  396. {
  397. //
  398. // Try to return the default channel icon.
  399. //
  400. *pwFlags = 0;
  401. StrCpyN(szIconFile, g_szModuleName, cchMax);
  402. if (*szIconFile)
  403. {
  404. *piIndex = -IDI_CHANNEL;
  405. hr = S_OK;
  406. }
  407. else
  408. {
  409. *piIndex = 0;
  410. hr = S_FALSE; // The shell will use a default icon.
  411. }
  412. }
  413. //
  414. // If this a generated icon and it should contain a gleam prepend
  415. // the string with a 'G'.
  416. //
  417. if (S_OK == hr && m_fDrawGleam)
  418. {
  419. TCHAR* pszBuffer = new TCHAR[cchMax];
  420. if (m_pIExtractIcon)
  421. {
  422. CExtractIcon *pExtract = (CExtractIcon *)m_pIExtractIcon;
  423. pExtract->SetGleam(m_fDrawGleam);
  424. }
  425. if (pszBuffer)
  426. {
  427. StrCpyN(pszBuffer, szIconFile, cchMax);
  428. *szIconFile = TEXT('G');
  429. cchMax--;
  430. StrCpyN(szIconFile+1, pszBuffer, cchMax);
  431. delete [] pszBuffer;
  432. }
  433. }
  434. *pwFlags = (m_fDrawGleam || INDEX_IMAGE == *piIndex) ? GIL_NOTFILENAME :
  435. 0;
  436. if (m_fDrawGleam)
  437. *piIndex += GLEAM_OFFSET;
  438. TraceMsg(TF_GLEAM, "%c Icon Location %s,%d", m_fDrawGleam ? '+' : '-',
  439. SUCCEEDED(hr) ? szIconFile : TEXT("FAILED"), *piIndex);
  440. ASSERT((S_OK == hr && *szIconFile) ||
  441. (S_FALSE == hr && 0 == *szIconFile));
  442. }
  443. TraceMsg(TF_CDFICON, "<OUT> CIconHandler::GetIconLocation (Icon) %s",
  444. szIconFile);
  445. return hr;
  446. }
  447. #ifdef UNICODE
  448. STDMETHODIMP
  449. CIconHandler::GetIconLocation(
  450. UINT uFlags,
  451. LPSTR szIconFile,
  452. UINT cchMax,
  453. int *piIndex,
  454. UINT *pwFlags
  455. )
  456. {
  457. ASSERT(szIconFile);
  458. ASSERT(piIndex);
  459. ASSERT(pwFlags);
  460. HRESULT hr;
  461. TraceMsg(TF_CDFICON, "<IN > CIconHandler::GetIconLocationA (Icon) tid:0x%x",
  462. GetCurrentThreadId());
  463. WCHAR* pszIconFileW = new WCHAR[cchMax];
  464. if (pszIconFileW == NULL)
  465. return ERROR_OUTOFMEMORY;
  466. hr = GetIconLocation(uFlags, pszIconFileW, cchMax, piIndex, pwFlags);
  467. if (SUCCEEDED(hr))
  468. SHUnicodeToAnsi(pszIconFileW, szIconFile, cchMax);
  469. delete [] pszIconFileW;
  470. return hr;
  471. }
  472. #endif
  473. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  474. //
  475. // *** CIconHandler::Extract ***
  476. //
  477. //
  478. // Description:
  479. // Return an icon given the name index pair returned from GetIconLocation.
  480. //
  481. // Parameters:
  482. // [In] pszFile - A pointer to the name associated with the requested
  483. // icon.
  484. // [In] nIconIndex - An index associated with the requested icon.
  485. // [Out] phiconLarge - Pointer to the variable that receives the handle of
  486. // the large icon.
  487. // [Out] phiconSmall - Pointer to the variable that receives the handle of
  488. // the small icon.
  489. // [Out] nIconSize - Value specifying the size, in pixels, of the icon
  490. // required. The LOWORD and HIWORD specify the size of
  491. // the large and small icons, respectively.
  492. //
  493. // Return:
  494. // S_OK if the icon was extracted.
  495. // S_FALSE if the shell should extract the icon assuming the name is a
  496. // filename and the index is the icon index.
  497. //
  498. // Comments:
  499. // The shell may cache the icon returned from this function.
  500. //
  501. ////////////////////////////////////////////////////////////////////////////////
  502. STDMETHODIMP
  503. CIconHandler::Extract(
  504. LPCTSTR pszFile,
  505. UINT nIconIndex,
  506. HICON *phiconLarge,
  507. HICON *phiconSmall,
  508. UINT nIconSize
  509. )
  510. {
  511. HRESULT hr;
  512. TraceMsg(TF_CDFICON, "<IN > CIconHandler::Extract (Icon) tid:0x%x",
  513. GetCurrentThreadId());
  514. DWORD dwType;
  515. DWORD dwVal; // Bits per pixel
  516. DWORD cbVal = sizeof(DWORD);
  517. if ((SHGetValue(HKEY_CURRENT_USER, c_szHICKey, c_szHICVal, &dwType, &dwVal,
  518. &cbVal) != ERROR_SUCCESS)
  519. ||
  520. (REG_DWORD != dwType))
  521. {
  522. dwVal = 0;
  523. }
  524. // Convert bits per pixel to # colors
  525. m_dwClrDepth = (dwVal == 16) ? 256 : 16;
  526. if (m_fDrawGleam)
  527. nIconIndex -= GLEAM_OFFSET;
  528. if (m_pIExtractIcon)
  529. {
  530. hr = m_pIExtractIcon->Extract(pszFile, nIconIndex, phiconLarge,
  531. phiconSmall, nIconSize);
  532. //
  533. // If an icon couldn't be extracted, try and display the default icon.
  534. //
  535. if (FAILED(hr))
  536. {
  537. hr = Priv_SHDefExtractIcon(g_szModuleName, -IDI_CHANNEL, 0,
  538. phiconLarge, phiconSmall, nIconSize);
  539. }
  540. }
  541. else
  542. {
  543. hr = S_FALSE;
  544. }
  545. TraceMsg(TF_GLEAM, "%c Icon Extract %s %s", m_fDrawGleam ? '+' : '-',
  546. pszFile, (S_OK == hr) ? TEXT("SUCCEEDED") : TEXT("FAILED"));
  547. TraceMsg(TF_CDFICON, "<OUT> CIconHandler::Extract (Icon) tid:0x%x",
  548. GetCurrentThreadId());
  549. return hr;
  550. }
  551. #ifdef UNICODE
  552. STDMETHODIMP
  553. CIconHandler::Extract(
  554. LPCSTR pszFile,
  555. UINT nIconIndex,
  556. HICON *phiconLarge,
  557. HICON *phiconSmall,
  558. UINT nIconSize
  559. )
  560. {
  561. HRESULT hr;
  562. TraceMsg(TF_CDFICON, "<IN > CIconHandler::ExtractA (Icon) tid:0x%x",
  563. GetCurrentThreadId());
  564. int cch = lstrlenA(pszFile) + 1;
  565. WCHAR* pszFileW = new WCHAR[cch];
  566. if (pszFileW == NULL)
  567. return ERROR_OUTOFMEMORY;
  568. SHAnsiToUnicode(pszFile, pszFileW, cch);
  569. hr = Extract(pszFileW, nIconIndex, phiconLarge, phiconSmall, nIconSize);
  570. delete [] pszFileW;
  571. return hr;
  572. }
  573. #endif
  574. //
  575. // IExtractImage methods.
  576. //
  577. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  578. //
  579. // *** CIconHandler::GetLocation ***
  580. //
  581. //
  582. // Description:
  583. // Returns a string to associate with this files image.
  584. //
  585. // Parameters:
  586. // [Out] pszPathBuffer - A buffer that receives this items string.
  587. // [In] cch - The size of the buffer.
  588. // [Out] pdwPriority - The priority of this item's image.
  589. // [In/Out] pdwFlags - Flags associated with this call.
  590. //
  591. // Return:
  592. // S_OK if a string is returned.
  593. // E_FAIL otherwise.
  594. //
  595. // Comments:
  596. // IExtractImage uses the returned value to share images accross multiple
  597. // items. If three items in the same directory return "Default" all three
  598. // would use the same image.
  599. //
  600. ////////////////////////////////////////////////////////////////////////////////
  601. STDMETHODIMP
  602. CIconHandler::GetLocation(
  603. LPWSTR pszPathBuffer,
  604. DWORD cch,
  605. DWORD* pdwPriority,
  606. const SIZE * prgSize,
  607. DWORD dwRecClrDepth,
  608. DWORD* pdwFlags
  609. )
  610. {
  611. LPWSTR pstrURL = NULL;
  612. ASSERT(pszPathBuffer || 0 == cch);
  613. ASSERT(pdwFlags);
  614. HRESULT hr = E_FAIL;
  615. TraceMsg(TF_CDFLOGO, "<IN > CIconHandler::GetIconLocation (Logo) tid:0x%x",
  616. GetCurrentThreadId());
  617. if ( !prgSize )
  618. {
  619. return E_INVALIDARG;
  620. }
  621. m_rgSize = *prgSize;
  622. m_dwClrDepth = dwRecClrDepth;
  623. if ( IsDefaultChannel() && !UseWideLogo(prgSize->cx))
  624. {
  625. // avoid having to partse the CDF if possible by
  626. // pulling the entry from the desktop.ini file...
  627. pstrURL = m_bstrImageURL = CPersist::ReadFromIni(TSTR_INI_LOGO);
  628. }
  629. if (pstrURL == NULL && !m_bCdfParsed)
  630. ParseCdfImage(&m_bstrImageURL, &m_bstrImageWideURL);
  631. pstrURL = (UseWideLogo(prgSize->cx) && m_bstrImageWideURL) ?
  632. m_bstrImageWideURL :
  633. m_bstrImageURL;
  634. if (pstrURL)
  635. {
  636. ASSERT(0 != *m_bstrImageURL);
  637. if (m_fDrawGleam && cch > 0)
  638. {
  639. *pszPathBuffer++ = L'G';
  640. cch--;
  641. }
  642. if (StrCpyNW(pszPathBuffer, pstrURL, cch))
  643. {
  644. hr = S_OK;
  645. }
  646. else
  647. {
  648. if (m_bstrImageURL)
  649. {
  650. SysFreeString(m_bstrImageURL);
  651. m_bstrImageURL = NULL;
  652. }
  653. if (m_bstrImageWideURL)
  654. {
  655. SysFreeString(m_bstrImageWideURL);
  656. m_bstrImageWideURL = NULL;
  657. }
  658. }
  659. }
  660. if (FAILED(hr))
  661. {
  662. m_bstrImageURL = CPersist::ReadFromIni(TSTR_INI_LOGO);
  663. m_bstrImageWideURL = CPersist::ReadFromIni(TSTR_INI_WIDELOGO);
  664. pstrURL = (UseWideLogo(prgSize->cx) && m_bstrImageWideURL) ?
  665. m_bstrImageWideURL :
  666. m_bstrImageURL;
  667. if (pstrURL)
  668. {
  669. if (m_fDrawGleam && cch > 0)
  670. {
  671. *pszPathBuffer++ = L'G';
  672. cch--;
  673. }
  674. if (StrCpyNW(pszPathBuffer, pstrURL, cch))
  675. hr = S_OK;
  676. }
  677. }
  678. BOOL bAsync = *pdwFlags & IEIFLAG_ASYNC;
  679. //
  680. // REVIEW: Long URLs truncated in pszPathBuffer.
  681. //
  682. //TSTRToWideChar(m_szPath, pszPathBuffer, cch);
  683. if (pdwPriority)
  684. *pdwPriority = ITSAT_DEFAULT_PRIORITY; //0x10000; // Low priority since this could hit the net.
  685. *pdwFlags = m_fDrawGleam ? IEIFLAG_GLEAM : 0;
  686. TraceMsg(TF_GLEAM, "%c Logo Location %S", m_fDrawGleam ? '+' : '-',
  687. SUCCEEDED(hr) ? pszPathBuffer : L"FAILED");
  688. //
  689. // REVIEW: Proper IEIFLAG_ASYNC handling.
  690. //
  691. TraceMsg(TF_CDFLOGO, "<OUT> CIconHandler::GetIconLocation (Logo) tid:0x%x",
  692. GetCurrentThreadId());
  693. return (SUCCEEDED(hr) && bAsync) ? E_PENDING : hr;
  694. }
  695. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  696. //
  697. // *** CIconHandler::Extract ***
  698. //
  699. //
  700. // Description:
  701. // Returns a hbitmap for use as a logo for this cdf file.
  702. //
  703. // Parameters:
  704. // [Out] phBmp - The returned bitmap.
  705. //
  706. // Return:
  707. // S_OK if an image was extracted.
  708. // E_FAIL if an image couldn't be extracted.
  709. //
  710. // Comments:
  711. // The returned bitmap is stretched to pSize.
  712. //
  713. ////////////////////////////////////////////////////////////////////////////////
  714. STDMETHODIMP
  715. CIconHandler::Extract(
  716. HBITMAP * phBmp
  717. )
  718. {
  719. ASSERT(phBmp);
  720. HRESULT hr = E_FAIL;
  721. TraceMsg(TF_CDFLOGO, "<IN > CIconHandler::Extract (Logo) tid:0x%x",
  722. GetCurrentThreadId());
  723. if (m_bstrImageURL)
  724. {
  725. hr = ExtractCustomImage(&m_rgSize, phBmp);
  726. }
  727. // Let the extractor build a default logo.
  728. //if (FAILED(hr))
  729. // hr = ExtractDefaultImage(pSize, phBmp);
  730. TraceMsg(TF_CDFLOGO, "<OUT> CIconHandler::Extract (Logo) tid:0x%x",
  731. GetCurrentThreadId());
  732. return hr;
  733. }
  734. //
  735. // Helper functions.
  736. //
  737. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  738. //
  739. // *** CIconHandler::IsDefaultChannel***
  740. //
  741. //
  742. // Description:
  743. // Checks to see if the channel we are dealing with is a default one.
  744. //
  745. // Parameters:
  746. // None.
  747. //
  748. // Return:
  749. // TRUE if it is a default channel.
  750. // FALSE otherwise.
  751. //
  752. // Comments:
  753. // This is used in an attempt to avoid parsing the CDF if the only
  754. // information we need is already in the desktop.ini file.
  755. //
  756. ////////////////////////////////////////////////////////////////////////////////
  757. BOOL CIconHandler::IsDefaultChannel()
  758. {
  759. BOOL fDefault = FALSE;
  760. // get the desktop.ini path and see if it points to the systemdir\web
  761. BSTR pstrURL = CPersist::ReadFromIni( TSTR_INI_URL );
  762. if ( pstrURL )
  763. {
  764. fDefault = Channel_CheckURLMapping( pstrURL );
  765. SysFreeString( pstrURL );
  766. }
  767. return fDefault;
  768. }
  769. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  770. //
  771. // *** CIconHandler::ParseCdfIcon ***
  772. //
  773. //
  774. // Description:
  775. // Parses the cdf file associated with this folder.
  776. //
  777. // Parameters:
  778. // None.
  779. //
  780. // Return:
  781. // S_OK if the cdf file was found and successfully parsed.
  782. // E_FAIL otherwise.
  783. //
  784. // Comments:
  785. // This parse function gets the root channel item and uses it to create
  786. // a CExtractIcon object. The CExtractIcon object is later called to get
  787. // the icon location and extract the icon.
  788. //
  789. ////////////////////////////////////////////////////////////////////////////////
  790. HRESULT
  791. CIconHandler::ParseCdfIcon(
  792. void
  793. )
  794. {
  795. HRESULT hr;
  796. //
  797. // Parse the file and get back the root channel element.
  798. //
  799. IXMLDocument* pIXMLDocument = NULL;
  800. TraceMsg(TF_CDFICON, "Extracting icon URL for %s",
  801. PathFindFileName(m_szPath));
  802. TraceMsg(TF_CDFPARSE, "Extracting icon URL for %s",
  803. PathFindFileName(m_szPath));
  804. hr = CPersist::ParseCdf(NULL, &pIXMLDocument, PARSE_LOCAL);
  805. if (SUCCEEDED(hr))
  806. {
  807. ASSERT(pIXMLDocument);
  808. m_fDrawGleam = CPersist::IsUnreadCdf();
  809. IXMLElement* pIXMLElement;
  810. LONG nIndex;
  811. hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
  812. if (SUCCEEDED(hr))
  813. {
  814. ASSERT(pIXMLElement);
  815. PCDFITEMIDLIST pcdfidl = CDFIDL_CreateFromXMLElement(pIXMLElement,
  816. nIndex);
  817. if (pcdfidl)
  818. {
  819. //
  820. // Create a CExtractIcon object for the root channel.
  821. //
  822. m_pIExtractIcon = (IExtractIcon*)new CExtractIcon(pcdfidl,
  823. pIXMLElement);
  824. hr = m_pIExtractIcon ? S_OK : E_OUTOFMEMORY;
  825. CDFIDL_Free(pcdfidl);
  826. }
  827. pIXMLElement->Release();
  828. }
  829. }
  830. if (pIXMLDocument)
  831. pIXMLDocument->Release();
  832. return hr;
  833. }
  834. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  835. //
  836. // *** CIconHandler::ParseCdfImage ***
  837. //
  838. //
  839. // Description:
  840. // Parses the cdf file associated with this folder.
  841. //
  842. // Parameters:
  843. // [In] pbstrURL - A pointer that receives the URL for the image associated
  844. // with the root channel.
  845. //
  846. // Return:
  847. // S_OK if the URL was found.
  848. // E_FAIL if the URL wasn't found.
  849. //
  850. // Comments:
  851. // This function parses the cdf file and returns an URL to the image
  852. // associated with this cdf file.
  853. //
  854. ////////////////////////////////////////////////////////////////////////////////
  855. HRESULT
  856. CIconHandler::ParseCdfImage(
  857. BSTR* pbstrURL,
  858. BSTR* pbstrWURL
  859. )
  860. {
  861. ASSERT(pbstrURL);
  862. HRESULT hr;
  863. *pbstrURL = NULL;
  864. IXMLDocument* pIXMLDocument = NULL;
  865. //
  866. // Parse the file.
  867. //
  868. TraceMsg(TF_CDFPARSE, "Extracting logo URL for %s",
  869. PathFindFileName(m_szPath));
  870. TraceMsg(TF_CDFLOGO, "Extracting logo URL for %s",
  871. PathFindFileName(m_szPath));
  872. hr = CPersist::ParseCdf(NULL, &pIXMLDocument, PARSE_LOCAL);
  873. if (SUCCEEDED(hr))
  874. {
  875. ASSERT(pIXMLDocument);
  876. m_fDrawGleam = CPersist::IsUnreadCdf();
  877. //
  878. // Get the first channel element.
  879. //
  880. IXMLElement* pIXMLElement;
  881. LONG nIndex;
  882. hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
  883. if (SUCCEEDED(hr))
  884. {
  885. ASSERT(pIXMLElement);
  886. //
  887. // Get the logo URL of the first channel element.
  888. //
  889. *pbstrURL = XML_GetAttribute(pIXMLElement, XML_LOGO);
  890. hr = *pbstrURL ? S_OK : E_FAIL;
  891. *pbstrWURL = XML_GetAttribute(pIXMLElement, XML_LOGO_WIDE);
  892. pIXMLElement->Release();
  893. }
  894. }
  895. if (pIXMLDocument)
  896. pIXMLDocument->Release();
  897. return hr;
  898. }
  899. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  900. //
  901. // *** Name ***
  902. //
  903. //
  904. // Description:
  905. //
  906. //
  907. // Parameters:
  908. //
  909. //
  910. // Return:
  911. //
  912. //
  913. // Comments:
  914. //
  915. //
  916. ////////////////////////////////////////////////////////////////////////////////
  917. HRESULT
  918. CIconHandler::ParseCdfShellLink(
  919. void
  920. )
  921. {
  922. //
  923. // Parse the file and get back the root channel element.
  924. //
  925. IXMLDocument* pIXMLDocument = NULL;
  926. TraceMsg(TF_CDFPARSE, "Extracting IShellLink for %s",
  927. PathFindFileName(m_szPath));
  928. HRESULT hr = CPersist::ParseCdf(NULL, &pIXMLDocument,
  929. PARSE_LOCAL | PARSE_REMOVEGLEAM);
  930. if (SUCCEEDED(hr))
  931. {
  932. ASSERT(pIXMLDocument);
  933. IXMLElement* pIXMLElement;
  934. LONG nIndex;
  935. hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
  936. if (SUCCEEDED(hr))
  937. {
  938. ASSERT(pIXMLElement);
  939. m_pcdfidl = CDFIDL_CreateFromXMLElement(pIXMLElement,
  940. nIndex);
  941. pIXMLElement->Release();
  942. }
  943. }
  944. else if (OLE_E_NOCACHE == hr)
  945. {
  946. //
  947. // If it wasn't in the cache pass the url of the cdf so it gets reloaded.
  948. //
  949. BSTR bstrURL = CPersist::ReadFromIni(TSTR_INI_URL);
  950. if (bstrURL)
  951. {
  952. if (InternetGetConnectedState(NULL, 0))
  953. {
  954. int cch = StrLenW(bstrURL) + 1;
  955. m_pszErrURL = new TCHAR[cch];
  956. if (m_pszErrURL)
  957. {
  958. if (!SHUnicodeToTChar(bstrURL, m_pszErrURL, cch))
  959. {
  960. delete []m_pszErrURL;
  961. m_pszErrURL = NULL;
  962. }
  963. }
  964. }
  965. else
  966. {
  967. TCHAR szResURL[INTERNET_MAX_URL_LENGTH];
  968. ASSERT(NULL == m_pszErrURL);
  969. if (SUCCEEDED(MLBuildResURLWrap(TEXT("cdfvwlc.dll"),
  970. g_hinst,
  971. ML_CROSSCODEPAGE,
  972. TEXT("cacheerr.htm#"),
  973. szResURL,
  974. ARRAYSIZE(szResURL),
  975. TEXT("cdfview.dll"))))
  976. {
  977. int cchPrefix = StrLen(szResURL);
  978. int cch = StrLenW(bstrURL) + cchPrefix + 1;
  979. m_pszErrURL = new TCHAR[cch];
  980. if (m_pszErrURL &&
  981. (!StrCpy(m_pszErrURL, szResURL) ||
  982. !SHUnicodeToTChar(bstrURL, m_pszErrURL + cchPrefix, cch - cchPrefix)))
  983. {
  984. delete []m_pszErrURL;
  985. m_pszErrURL = NULL;
  986. }
  987. }
  988. }
  989. SysFreeString(bstrURL);
  990. }
  991. }
  992. else
  993. {
  994. DWORD dwSize = sizeof(TCHAR[CDFERROR_MAX_URL_LENGTH_ENCODED]); // count in bytes
  995. if (NULL==m_pszErrURL)
  996. m_pszErrURL = new TCHAR[CDFERROR_MAX_URL_LENGTH_ENCODED];
  997. if (m_pszErrURL)
  998. {
  999. if (pIXMLDocument)
  1000. {
  1001. if ( FAILED(MakeXMLErrorURL(m_pszErrURL, dwSize / sizeof(TCHAR), pIXMLDocument)) )
  1002. {
  1003. delete[] m_pszErrURL;
  1004. m_pszErrURL = NULL;
  1005. }
  1006. }
  1007. }
  1008. }
  1009. if (pIXMLDocument)
  1010. pIXMLDocument->Release();
  1011. return hr;
  1012. }
  1013. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1014. //
  1015. // *** Name ***
  1016. //
  1017. //
  1018. // Description:
  1019. //
  1020. //
  1021. // Parameters:
  1022. //
  1023. //
  1024. // Return:
  1025. //
  1026. //
  1027. // Comments:
  1028. //
  1029. //
  1030. ////////////////////////////////////////////////////////////////////////////////
  1031. HRESULT
  1032. CIconHandler::ParseCdfInfoTip(
  1033. void** ppv
  1034. )
  1035. {
  1036. ASSERT(ppv);
  1037. HRESULT hr;
  1038. //
  1039. // Parse the file and get back the root channel element.
  1040. //
  1041. IXMLDocument* pIXMLDocument = NULL;
  1042. TraceMsg(TF_CDFPARSE, "Extracting IQueryInfo for %s",
  1043. PathFindFileName(m_szPath));
  1044. hr = CPersist::ParseCdf(NULL, &pIXMLDocument, PARSE_LOCAL);
  1045. if (SUCCEEDED(hr))
  1046. {
  1047. ASSERT(pIXMLDocument);
  1048. IXMLElement* pIXMLElement;
  1049. LONG nIndex;
  1050. hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex);
  1051. if (SUCCEEDED(hr))
  1052. {
  1053. ASSERT(pIXMLElement);
  1054. *ppv = (IQueryInfo*)new CQueryInfo(pIXMLElement, XML_IsFolder(pIXMLElement));
  1055. hr = *ppv ? S_OK : E_FAIL;
  1056. pIXMLElement->Release();
  1057. }
  1058. }
  1059. else
  1060. {
  1061. //
  1062. // Even if the cdf isn't in the cache, return a IQueryInfo interface.
  1063. // The caller can stil call GetInfoFlags.
  1064. //
  1065. *ppv = (IQueryInfo*)new CQueryInfo(NULL, FALSE);
  1066. hr = *ppv ? S_OK : E_FAIL;
  1067. }
  1068. if (pIXMLDocument)
  1069. pIXMLDocument->Release();
  1070. return hr;
  1071. }
  1072. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1073. //
  1074. // *** CIconHandler::ExtractCustomImage ***
  1075. //
  1076. //
  1077. // Description:
  1078. // Extract an image from an URL.
  1079. //
  1080. // Parameters:
  1081. // [In] pSize - The requested size of the image.
  1082. // [Out] phBmp - The returned bitmap.
  1083. //
  1084. // Return:
  1085. // S_OK if the bitmap was successfully extracted.
  1086. // E_FAIL otherwise.
  1087. //
  1088. // Comments:
  1089. // The URL of the image is in m_bstrImageURL and was set when the cdf
  1090. // file was parsed.
  1091. //
  1092. ////////////////////////////////////////////////////////////////////////////////
  1093. HRESULT
  1094. CIconHandler::ExtractCustomImage(
  1095. const SIZE* pSize,
  1096. HBITMAP* phBmp
  1097. )
  1098. {
  1099. ASSERT(pSize);
  1100. ASSERT(phBmp);
  1101. HRESULT hr;
  1102. IImgCtx* pIImgCtx;
  1103. hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER,
  1104. IID_IImgCtx, (void**)&pIImgCtx);
  1105. BOOL bCoInit = FALSE;
  1106. if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
  1107. SUCCEEDED(CoInitialize(NULL)))
  1108. {
  1109. bCoInit = TRUE;
  1110. hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER,
  1111. IID_IImgCtx, (void**)&pIImgCtx);
  1112. }
  1113. if (SUCCEEDED(hr))
  1114. {
  1115. ASSERT(pIImgCtx);
  1116. hr = SynchronousDownload(pIImgCtx,
  1117. (UseWideLogo(pSize->cx) && m_bstrImageWideURL) ?
  1118. m_bstrImageWideURL :
  1119. m_bstrImageURL);
  1120. //
  1121. // If the load of the wide logo failed try and use the regular logo.
  1122. //
  1123. if (FAILED(hr) && UseWideLogo(pSize->cx) && m_bstrImageWideURL &&
  1124. m_bstrImageURL)
  1125. {
  1126. hr = SynchronousDownload(pIImgCtx, m_bstrImageURL);
  1127. SysFreeString(m_bstrImageWideURL);
  1128. m_bstrImageWideURL = NULL;
  1129. }
  1130. if (SUCCEEDED(hr))
  1131. {
  1132. hr = GetBitmap(pIImgCtx, pSize, phBmp);
  1133. if (FAILED(hr))
  1134. *phBmp = NULL;
  1135. }
  1136. pIImgCtx->Release();
  1137. }
  1138. if (bCoInit)
  1139. CoUninitialize();
  1140. ASSERT((SUCCEEDED(hr) && *phBmp) || (FAILED(hr) && NULL == *phBmp));
  1141. return hr;
  1142. }
  1143. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1144. //
  1145. // *** CIconHandler::ExtractDefaultImage ***
  1146. //
  1147. //
  1148. // Description:
  1149. // Returns the default channel bitmap.
  1150. //
  1151. // [In] pSize - The requested size of the image.
  1152. // [Out] phBmp - The returned bitmap.
  1153. //
  1154. // Return:
  1155. // S_OK if the bitmap was successfully extracted.
  1156. // E_FAIL otherwise.
  1157. //
  1158. // Comments:
  1159. // If a cdf doesn't specify a logo image or the logo image couldn't be
  1160. // downloaded a default image is used.
  1161. //
  1162. ////////////////////////////////////////////////////////////////////////////////
  1163. /*HRESULT
  1164. CIconHandler::ExtractDefaultImage(
  1165. const SIZE* pSize,
  1166. HBITMAP* phBmp
  1167. )
  1168. {
  1169. ASSERT(pSize);
  1170. ASSERT(phBmp);
  1171. HRESULT hr;
  1172. hr = GetBitmap(NULL, pSize, phBmp);
  1173. if (FAILED(hr))
  1174. *phBmp = NULL;
  1175. ASSERT((SUCCEEDED(hr) && *phBmp) || (FAILED(hr) && NULL == *phBmp));
  1176. return hr;
  1177. }*/
  1178. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1179. //
  1180. // *** CIconHandler::GetBitmap ***
  1181. //
  1182. //
  1183. // Description:
  1184. // Gets the requested bitmap
  1185. //
  1186. // Parameters:
  1187. // [In] pIImgCtx - The ImgCtx of the image. NULL if the default image is
  1188. // to be returned.
  1189. // [In] pSize - The requested size of the image.
  1190. // [Out] phBmp - A pointer that receives the returned image.
  1191. //
  1192. // Return:
  1193. // S_OK if the image was extracted.
  1194. // E_FAIL otherwise.
  1195. //
  1196. // Comments:
  1197. // This function conatins code that is shared by the custom image extractor
  1198. // and the default image extractor. The pIImhCtx parameter is used as a
  1199. // flag indicating which image - default or custom - is to be extracted.
  1200. //
  1201. ////////////////////////////////////////////////////////////////////////////////
  1202. HRESULT
  1203. CIconHandler::GetBitmap(
  1204. IImgCtx* pIImgCtx,
  1205. const SIZE* pSize,
  1206. HBITMAP* phBmp
  1207. )
  1208. {
  1209. ASSERT(pSize);
  1210. ASSERT(phBmp);
  1211. HRESULT hr = E_FAIL;
  1212. //
  1213. // REVIEW: Pallete use for 8bpp DCs?
  1214. //
  1215. HDC hdcScreen = GetDC(NULL);
  1216. if (hdcScreen)
  1217. {
  1218. HDC hdcDst = CreateCompatibleDC(NULL);
  1219. if (hdcDst)
  1220. {
  1221. LPVOID lpBits;
  1222. struct {
  1223. BITMAPINFOHEADER bi;
  1224. DWORD ct[256];
  1225. } dib;
  1226. dib.bi.biSize = sizeof(BITMAPINFOHEADER);
  1227. dib.bi.biWidth = pSize->cx;
  1228. dib.bi.biHeight = pSize->cy;
  1229. dib.bi.biPlanes = 1;
  1230. dib.bi.biBitCount = (WORD) m_dwClrDepth;
  1231. dib.bi.biCompression = BI_RGB;
  1232. dib.bi.biSizeImage = 0;
  1233. dib.bi.biXPelsPerMeter = 0;
  1234. dib.bi.biYPelsPerMeter = 0;
  1235. dib.bi.biClrUsed = ( m_dwClrDepth <= 8 ) ? (1 << m_dwClrDepth) : 0;
  1236. dib.bi.biClrImportant = 0;
  1237. if ( m_dwClrDepth <= 8 )
  1238. {
  1239. HPALETTE hpal = NULL;
  1240. // need to get the right palette....
  1241. hr = pIImgCtx->GetPalette( & hpal );
  1242. if ( SUCCEEDED( hr ) && hpal )
  1243. {
  1244. GetPaletteEntries(hpal, 0, 256, (LPPALETTEENTRY)&dib.ct[0]);
  1245. for (int i = 0; i < (int)dib.bi.biClrUsed; i ++)
  1246. dib.ct[i] = RGB(GetBValue(dib.ct[i]),GetGValue(dib.ct[i]),GetRValue(dib.ct[i]));
  1247. }
  1248. }
  1249. *phBmp = CreateDIBSection(hdcDst, (LPBITMAPINFO)&dib, DIB_RGB_COLORS, &lpBits, NULL, 0);
  1250. HBITMAP hOld = (HBITMAP) SelectObject( hdcDst, *phBmp );
  1251. if (*phBmp && hOld)
  1252. {
  1253. RECT rc;
  1254. rc.top = rc.left = 0;
  1255. rc.bottom = pSize->cy;
  1256. rc.right = pSize->cx;
  1257. // black background...
  1258. HBRUSH hbr = (HBRUSH) GetStockObject( BLACK_BRUSH );
  1259. FillRect( hdcDst, &rc, hbr );
  1260. DeleteObject( hbr );
  1261. if (pIImgCtx)
  1262. {
  1263. hr = StretchBltCustomImage(pIImgCtx, pSize, hdcDst);
  1264. }
  1265. else
  1266. {
  1267. hr = E_FAIL; //StretchBltDefaultImage(pSize, hdcDst);
  1268. }
  1269. SelectObject( hdcDst, hOld );
  1270. }
  1271. DeleteDC(hdcDst);
  1272. }
  1273. ReleaseDC(NULL, hdcScreen);
  1274. }
  1275. ASSERT((SUCCEEDED(hr) && *phBmp) || FAILED(hr));
  1276. return hr;
  1277. }
  1278. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1279. //
  1280. // *** CIconHandler::StretchBltCustomImage ***
  1281. //
  1282. //
  1283. // Description:
  1284. // Stretches the image associated with IImgCtx to the given size and places
  1285. // the result in the given DC.
  1286. //
  1287. // Parameters:
  1288. // [In] pIImgCtx - The image context for the image.
  1289. // [In] pSize - The size of the resultant image.
  1290. // [In/Out] hdcDst - The destination DC of the stretch blt.
  1291. //
  1292. // Return:
  1293. // S_OK if the image was successfully resized into the destination DC.
  1294. // E_FAIL otherwise.
  1295. //
  1296. // Comments:
  1297. // The destination DC already a bitmap of pSize selected into it.
  1298. //
  1299. ////////////////////////////////////////////////////////////////////////////////
  1300. HRESULT
  1301. CIconHandler::StretchBltCustomImage(
  1302. IImgCtx* pIImgCtx,
  1303. const SIZE* pSize,
  1304. HDC hdcDst
  1305. )
  1306. {
  1307. ASSERT(pIImgCtx);
  1308. ASSERT(hdcDst);
  1309. HRESULT hr;
  1310. SIZE sz;
  1311. ULONG fState;
  1312. hr = pIImgCtx->GetStateInfo(&fState, &sz, FALSE);
  1313. if (SUCCEEDED(hr))
  1314. {
  1315. HPALETTE hpal = NULL;
  1316. HPALETTE hpalOld;
  1317. hr = pIImgCtx->GetPalette( &hpal );
  1318. if (hpal)
  1319. {
  1320. hpalOld = SelectPalette( hdcDst, hpal, TRUE );
  1321. RealizePalette( hdcDst );
  1322. }
  1323. if (UseWideLogo(pSize->cx) && NULL == m_bstrImageWideURL)
  1324. {
  1325. hr = pIImgCtx->StretchBlt(hdcDst, 0, 0, LOGO_WIDTH, pSize->cy, 0, 0,
  1326. sz.cx, sz.cy, SRCCOPY);
  1327. if (SUCCEEDED(hr))
  1328. {
  1329. //
  1330. // Color fill the logo.
  1331. //
  1332. COLORREF clr = GetPixel(hdcDst, 0, 0);
  1333. if (m_dwClrDepth <= 8)
  1334. clr = PALETTEINDEX(GetNearestPaletteIndex(hpal, clr));
  1335. HBRUSH hbr = CreateSolidBrush(clr);
  1336. if (hbr)
  1337. {
  1338. RECT rc;
  1339. rc.top = 0;
  1340. rc.bottom = pSize->cy;
  1341. rc.left = LOGO_WIDTH;
  1342. rc.right = pSize->cx;
  1343. FillRect(hdcDst, &rc, hbr);
  1344. DeleteObject(hbr);
  1345. }
  1346. }
  1347. }
  1348. else
  1349. {
  1350. hr = pIImgCtx->StretchBlt(hdcDst, 0, 0, pSize->cx, pSize->cy, 0, 0,
  1351. sz.cx, sz.cy, SRCCOPY);
  1352. }
  1353. if (SUCCEEDED(hr) && m_fDrawGleam)
  1354. DrawGleam(hdcDst);
  1355. if ( hpal )
  1356. {
  1357. SelectPalette( hdcDst, hpalOld, TRUE );
  1358. RealizePalette( hdcDst );
  1359. }
  1360. }
  1361. return hr;
  1362. }
  1363. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1364. //
  1365. // *** CIconHandler::StretchBltDefaultImage ***
  1366. //
  1367. //
  1368. // Description:
  1369. // Stretches the deafult channel image to fit the requested size.
  1370. //
  1371. // Parameters:
  1372. // [In] pSize - The requested size of the image.
  1373. // [In/Out] hdcDest - The destination DC for the resized image.
  1374. //
  1375. // Return:
  1376. // S_OK if the image is successfully resized into the destination DC.
  1377. // E_FAIL otherwise.
  1378. //
  1379. // Comments:
  1380. // This function creates a source DC, copies the deafult bitmap into the
  1381. // the source DC, then strch blts the source DC into the destination DC.
  1382. //
  1383. ////////////////////////////////////////////////////////////////////////////////
  1384. /*HRESULT
  1385. CIconHandler::StretchBltDefaultImage(
  1386. const SIZE* pSize,
  1387. HDC hdcDst
  1388. )
  1389. {
  1390. ASSERT(hdcDst);
  1391. HRESULT hr = E_FAIL;
  1392. HBITMAP hBmp = LoadBitmap(g_hinst, MAKEINTRESOURCE(IDB_DEFAULT));
  1393. if (hBmp)
  1394. {
  1395. HDC hdcSrc = CreateCompatibleDC(NULL);
  1396. if (hdcSrc && SelectObject(hdcSrc, hBmp))
  1397. {
  1398. BITMAP bmp;
  1399. if (GetObject(hBmp, sizeof(BITMAP), (void*)&bmp))
  1400. {
  1401. if (StretchBlt(hdcDst, 0, 0, pSize->cx, pSize->cy,
  1402. hdcSrc, 0, 0, bmp.bmWidth, bmp.bmHeight,
  1403. SRCCOPY))
  1404. {
  1405. hr = S_OK;
  1406. }
  1407. }
  1408. DeleteDC(hdcSrc);
  1409. }
  1410. DeleteObject(hBmp);
  1411. }
  1412. return hr;
  1413. }*/
  1414. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1415. //
  1416. // *** CIconHandler::DrawGleam ***
  1417. //
  1418. //
  1419. // Description:
  1420. //
  1421. // Parameters:
  1422. //
  1423. // Return:
  1424. //
  1425. // Comments:
  1426. //
  1427. ////////////////////////////////////////////////////////////////////////////////
  1428. HRESULT
  1429. CIconHandler::DrawGleam(
  1430. HDC hdcDst
  1431. )
  1432. {
  1433. ASSERT(hdcDst)
  1434. HRESULT hr = E_FAIL;
  1435. HICON hGleam = (HICON)LoadImage(g_hinst, TEXT("LOGOGLEAM"),
  1436. IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
  1437. if (hGleam)
  1438. {
  1439. if (DrawIcon(hdcDst, 1, 1, hGleam))
  1440. hr = S_OK;
  1441. DestroyIcon(hGleam);
  1442. }
  1443. return hr;
  1444. }
  1445. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1446. //
  1447. // *** CIconHandler::SynchronousDownload ***
  1448. //
  1449. //
  1450. // Description:
  1451. // Synchronously downloads the image associated with the image context.
  1452. //
  1453. // Parameters:
  1454. // [In] pIImgCtx - A pointer to the image context.
  1455. //
  1456. // Return:
  1457. // S_OK if the image was successfully downloaded.
  1458. // E_FAIL if the image wasn't downloaded.
  1459. //
  1460. // Comments:
  1461. // The image context object doesn't directly support synchronous download.
  1462. // Here a message loop is used to make sure ulrmon keeps geeting messages
  1463. // and the download progresses.
  1464. //
  1465. ////////////////////////////////////////////////////////////////////////////////
  1466. HRESULT
  1467. CIconHandler::SynchronousDownload(
  1468. IImgCtx* pIImgCtx,
  1469. LPCWSTR pwszURL
  1470. )
  1471. {
  1472. ASSERT(pIImgCtx);
  1473. HRESULT hr;
  1474. TCHAR szLocalFile[MAX_PATH];
  1475. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  1476. SHUnicodeToTChar(pwszURL, szURL, ARRAYSIZE(szURL));
  1477. hr = URLGetLocalFileName(szURL, szLocalFile, ARRAYSIZE(szLocalFile), NULL);
  1478. TraceMsg(TF_GLEAM, "%c Logo Extract %s", m_fDrawGleam ? '+' : '-',
  1479. szLocalFile);
  1480. if (SUCCEEDED(hr))
  1481. {
  1482. TraceMsg(TF_CDFLOGO, "[URLGetLocalFileName %s]", szLocalFile);
  1483. #ifdef UNIX
  1484. unixEnsureFileScheme(szLocalFile);
  1485. #endif /* UNIX */
  1486. WCHAR szLocalFileW[MAX_PATH];
  1487. SHTCharToUnicode(szLocalFile, szLocalFileW, ARRAYSIZE(szLocalFileW));
  1488. hr = pIImgCtx->Load(szLocalFileW, 0);
  1489. if (SUCCEEDED(hr))
  1490. {
  1491. ULONG fState;
  1492. SIZE sz;
  1493. pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
  1494. if (!(fState & (IMGLOAD_COMPLETE | IMGLOAD_ERROR)))
  1495. {
  1496. m_fDone = FALSE;
  1497. hr = pIImgCtx->SetCallback(ImgCtx_Callback, &m_fDone);
  1498. if (SUCCEEDED(hr))
  1499. {
  1500. hr = pIImgCtx->SelectChanges(IMGCHG_COMPLETE, 0, TRUE);
  1501. if (SUCCEEDED(hr))
  1502. {
  1503. MSG msg;
  1504. BOOL fMsg;
  1505. // HACK: restrict the message pump to those messages we know that URLMON and
  1506. // HACK: the imageCtx stuff needs, otherwise we will be pumping messages for
  1507. // HACK: windows we shouldn't be pumping right now...
  1508. while(!m_fDone )
  1509. {
  1510. fMsg = PeekMessage(&msg, NULL, WM_USER + 1, WM_USER + 4, PM_REMOVE );
  1511. if (!fMsg)
  1512. {
  1513. fMsg = PeekMessage( &msg, NULL, WM_APP + 2, WM_APP + 2, PM_REMOVE );
  1514. }
  1515. if (!fMsg)
  1516. {
  1517. // go to sleep until we get a new message....
  1518. WaitMessage();
  1519. continue;
  1520. }
  1521. TranslateMessage(&msg);
  1522. DispatchMessage(&msg);
  1523. }
  1524. }
  1525. }
  1526. pIImgCtx->Disconnect();
  1527. }
  1528. hr = pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
  1529. if (SUCCEEDED(hr))
  1530. hr = (fState & IMGLOAD_COMPLETE) ? S_OK : E_FAIL;
  1531. }
  1532. }
  1533. else
  1534. {
  1535. TraceMsg(TF_CDFLOGO, "[URLGetLocalFileName %s FAILED]",szURL);
  1536. }
  1537. TraceMsg(TF_CDFPARSE, "[IImgCtx downloading logo %s %s]", szLocalFile,
  1538. SUCCEEDED(hr) ? TEXT("SUCCEEDED") : TEXT("FAILED"));
  1539. TraceMsg(TF_CDFLOGO, "[IImgCtx downloading logo %s %s]", szLocalFile,
  1540. SUCCEEDED(hr) ? TEXT("SUCCEEDED") : TEXT("FAILED"));
  1541. return hr;
  1542. }
  1543. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1544. //
  1545. // *** CIconHandler::Run ***
  1546. //
  1547. // IRunnableTask method.
  1548. //
  1549. ////////////////////////////////////////////////////////////////////////////////
  1550. STDMETHODIMP
  1551. CIconHandler::Run(
  1552. void
  1553. )
  1554. {
  1555. return E_NOTIMPL;
  1556. }
  1557. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1558. //
  1559. // *** CIconHandler::Kill ***
  1560. //
  1561. // IRunnableTask method.
  1562. //
  1563. ////////////////////////////////////////////////////////////////////////////////
  1564. STDMETHODIMP
  1565. CIconHandler::Kill(
  1566. BOOL fWait
  1567. )
  1568. {
  1569. m_fDone = TRUE;
  1570. return S_OK;
  1571. }
  1572. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1573. //
  1574. // *** CIconHandler::Suspend ***
  1575. //
  1576. // IRunnableTask method.
  1577. //
  1578. ////////////////////////////////////////////////////////////////////////////////
  1579. STDMETHODIMP
  1580. CIconHandler::Suspend(
  1581. void
  1582. )
  1583. {
  1584. return E_NOTIMPL;
  1585. }
  1586. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1587. //
  1588. // *** CIconHandler::Resume ***
  1589. //
  1590. // IRunnableTask method.
  1591. //
  1592. ////////////////////////////////////////////////////////////////////////////////
  1593. STDMETHODIMP
  1594. CIconHandler::Resume(
  1595. void
  1596. )
  1597. {
  1598. return E_NOTIMPL;
  1599. }
  1600. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1601. //
  1602. // *** CIconHandler::IsRunning ***
  1603. //
  1604. // IRunnableTask method.
  1605. //
  1606. ////////////////////////////////////////////////////////////////////////////////
  1607. STDMETHODIMP_(ULONG)
  1608. CIconHandler::IsRunning(
  1609. void
  1610. )
  1611. {
  1612. return E_NOTIMPL;
  1613. }