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.

1605 lines
40 KiB

  1. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  2. //
  3. // exticon.cpp
  4. //
  5. // IExtractIcon com object. Used by the shell to obtain icons.
  6. //
  7. // History:
  8. //
  9. // 3/21/97 edwardp Created.
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. //
  15. #include "stdinc.h"
  16. #include "resource.h"
  17. #include "cdfidl.h"
  18. #include "xmlutil.h"
  19. #include "exticon.h"
  20. #include "dll.h"
  21. #include "persist.h"
  22. //
  23. // Constructor and destructor.
  24. //
  25. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  26. //
  27. // *** CExtractIcon::CExtractIcon ***
  28. //
  29. // Constructor.
  30. //
  31. ////////////////////////////////////////////////////////////////////////////////
  32. CExtractIcon::CExtractIcon (
  33. PCDFITEMIDLIST pcdfidl,
  34. IXMLElementCollection *pIXMLElementCollection
  35. )
  36. : m_cRef(1)
  37. {
  38. ASSERT(CDFIDL_IsValid(pcdfidl));
  39. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)pcdfidl)));
  40. ASSERT(XML_IsCdfidlMemberOf(pIXMLElementCollection, pcdfidl));
  41. ASSERT(NULL == m_bstrIconURL);
  42. ASSERT(FALSE == m_fGleam);
  43. //
  44. // Set the default icon type.
  45. //
  46. if (CDFIDL_IsFolderId(&pcdfidl->mkid))
  47. {
  48. m_iconType = IDI_CLOSESUBCHANNEL;
  49. }
  50. else
  51. {
  52. m_iconType = IDI_STORY;
  53. }
  54. //
  55. // Get the URL for the custom icon.
  56. //
  57. if (pIXMLElementCollection)
  58. {
  59. IXMLElement* pIXMLElement;
  60. HRESULT hr;
  61. if (CDFIDL_GetIndex(pcdfidl) != -1)
  62. {
  63. hr = XML_GetElementByIndex(pIXMLElementCollection,
  64. CDFIDL_GetIndex(pcdfidl), &pIXMLElement);
  65. }
  66. else
  67. {
  68. IXMLElement *pIXMLElementChild;
  69. hr = XML_GetElementByIndex(pIXMLElementCollection, 0, &pIXMLElementChild);
  70. if (pIXMLElementChild)
  71. {
  72. hr = pIXMLElementChild->get_parent(&pIXMLElement);
  73. if (!pIXMLElement)
  74. {
  75. ASSERT(FALSE);
  76. hr = E_FAIL;
  77. }
  78. pIXMLElementChild->Release();
  79. }
  80. }
  81. if (SUCCEEDED(hr))
  82. {
  83. ASSERT(pIXMLElement);
  84. m_bstrIconURL = XML_GetAttribute(pIXMLElement, XML_ICON);
  85. pIXMLElement->Release();
  86. }
  87. }
  88. //
  89. // Don't allow the DLL to unload.
  90. //
  91. TraceMsg(TF_OBJECTS, "+ IExtractIcon");
  92. DllAddRef();
  93. return;
  94. }
  95. // Used for initializing the Root Element
  96. CExtractIcon::CExtractIcon (
  97. PCDFITEMIDLIST pcdfidl,
  98. IXMLElement *pElem
  99. )
  100. : m_cRef(1)
  101. {
  102. ASSERT(CDFIDL_IsValid(pcdfidl));
  103. ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)pcdfidl)));
  104. ASSERT(NULL == m_bstrIconURL);
  105. ASSERT(FALSE == m_fGleam);
  106. //
  107. // Set the default icon type.
  108. //
  109. m_iconType = IDI_CHANNEL;
  110. //
  111. // Get the URL for the custom icon.
  112. //
  113. if (pElem)
  114. {
  115. HRESULT hr;
  116. IXMLElement *pDeskElem;
  117. LONG nIndex;
  118. hr = XML_GetDesktopElementFromChannelElement(pElem, &pDeskElem, &nIndex);
  119. if (SUCCEEDED(hr))
  120. {
  121. m_iconType = IDI_DESKTOP;
  122. pDeskElem->Release();
  123. }
  124. m_bstrIconURL = XML_GetAttribute(pElem, XML_ICON);
  125. }
  126. //
  127. // Don't allow the DLL to unload.
  128. //
  129. TraceMsg(TF_OBJECTS, "+ IExtractIcon");
  130. DllAddRef();
  131. return;
  132. }
  133. // this constructor is used for the default channel case where
  134. // we draw the icon information from the desktop.ini case
  135. // to avoid having to parse the XML stuff
  136. CExtractIcon::CExtractIcon( BSTR pstrPath ) : m_cRef(1)
  137. {
  138. ASSERT(NULL == m_bstrIconURL);
  139. ASSERT(FALSE == m_fGleam);
  140. m_iconType = IDI_CHANNEL;
  141. m_bstrIconURL = SysAllocString( pstrPath );
  142. DllAddRef();
  143. }
  144. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  145. //
  146. // *** CExtractIcon::~CExtractIcon ***
  147. //
  148. // Destructor.
  149. //
  150. ////////////////////////////////////////////////////////////////////////////////
  151. CExtractIcon::~CExtractIcon (
  152. void
  153. )
  154. {
  155. ASSERT(0 == m_cRef);
  156. if (m_bstrIconURL)
  157. SysFreeString(m_bstrIconURL);
  158. //
  159. // Matching Release for the constructor Addref.
  160. //
  161. TraceMsg(TF_OBJECTS, "- IExtractIcon");
  162. DllRelease();
  163. return;
  164. }
  165. //
  166. // IUnknown methods.
  167. //
  168. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  169. //
  170. // *** CExtractIcon::QueryInterface ***
  171. //
  172. // CExtractIcon QI.
  173. //
  174. ////////////////////////////////////////////////////////////////////////////////
  175. STDMETHODIMP
  176. CExtractIcon::QueryInterface (
  177. REFIID riid,
  178. void **ppv
  179. )
  180. {
  181. ASSERT(ppv);
  182. HRESULT hr;
  183. if (IID_IUnknown == riid || IID_IExtractIcon == riid)
  184. {
  185. AddRef();
  186. *ppv = (IExtractIcon*)this;
  187. hr = S_OK;
  188. }
  189. #ifdef UNICODE
  190. else if (IID_IExtractIconA == riid)
  191. {
  192. AddRef();
  193. *ppv = (IExtractIconA*)this;
  194. hr = S_OK;
  195. }
  196. #endif
  197. else
  198. {
  199. *ppv = NULL;
  200. hr = E_NOINTERFACE;
  201. }
  202. ASSERT((SUCCEEDED(hr) && *ppv) || (FAILED(hr) && NULL == *ppv));
  203. return hr;
  204. }
  205. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  206. //
  207. // *** CExtractIcon::AddRef ***
  208. //
  209. // CExtractIcon AddRef.
  210. //
  211. ////////////////////////////////////////////////////////////////////////////////
  212. STDMETHODIMP_(ULONG)
  213. CExtractIcon::AddRef (
  214. void
  215. )
  216. {
  217. ASSERT(m_cRef != 0);
  218. ASSERT(m_cRef < (ULONG)-1);
  219. return ++m_cRef;
  220. }
  221. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  222. //
  223. // *** CExtractIcon::Release ***
  224. //
  225. // CExtractIcon Release.
  226. //
  227. ////////////////////////////////////////////////////////////////////////////////
  228. STDMETHODIMP_(ULONG)
  229. CExtractIcon::Release (
  230. void
  231. )
  232. {
  233. ASSERT (m_cRef != 0);
  234. ULONG cRef = --m_cRef;
  235. if (0 == cRef)
  236. delete this;
  237. return cRef;
  238. }
  239. //
  240. // IExtractIcon methods.
  241. //
  242. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  243. //
  244. // *** CExtractIcon::GetIconLocation ***
  245. //
  246. //
  247. // Description:
  248. // Returns a name index pair for the icon associated with this cdf item.
  249. //
  250. // Parameters:
  251. // [In] uFlags - GIL_FORSHELL, GIL_OPENICON.
  252. // [Out] szIconFile - The address of the buffer that receives the associated
  253. // icon name. It can be a filename, but doesn't have to
  254. // be.
  255. // [In] cchMax - Size of the buffer that receives the icon location.
  256. // [Out] piIndex - A pointer that receives the icon's index.
  257. // [Out] pwFlags - A pointer the receives flags about the icon.
  258. //
  259. // Return:
  260. // S_OK if an was found.
  261. // S_FALSE if the shell should supply a default icon.
  262. //
  263. // Comments:
  264. // The shell can cache an icon associated with a name index pair. This
  265. // improves performance on subsequent calls for an icon with the same name
  266. // index pair.
  267. //
  268. ////////////////////////////////////////////////////////////////////////////////
  269. STDMETHODIMP
  270. CExtractIcon::GetIconLocation(
  271. UINT uFlags,
  272. LPTSTR szIconFile,
  273. UINT cchMax,
  274. int *piIndex,
  275. UINT *pwFlags
  276. )
  277. {
  278. ASSERT(szIconFile);
  279. ASSERT(piIndex);
  280. ASSERT(pwFlags);
  281. HRESULT hr = E_FAIL;
  282. //TraceMsg(TF_CDFICON, "<IN> CExtractIcon::GetLocation (icon) tid:0x%x",
  283. // GetCurrentThreadId());
  284. if (m_bstrIconURL && (uFlags & GIL_ASYNC))
  285. {
  286. hr = E_PENDING;
  287. }
  288. else
  289. {
  290. if (m_bstrIconURL)
  291. {
  292. hr = GetCustomIconLocation(uFlags, szIconFile, cchMax, piIndex,
  293. pwFlags);
  294. if (FAILED(hr))
  295. {
  296. SysFreeString(m_bstrIconURL);
  297. m_bstrIconURL = NULL;
  298. }
  299. }
  300. if (FAILED(hr))
  301. {
  302. hr = GetDefaultIconLocation(uFlags, szIconFile, cchMax, piIndex,
  303. pwFlags);
  304. }
  305. //
  306. // If szIconFile is a path the shell will only use the filename part
  307. // of the path as the cache index. To ensure a unique index the full
  308. // path must be used. This is accomplished by modifying the path string
  309. // so it is no longer recognized as a path.
  310. //
  311. if (SUCCEEDED(hr) && INDEX_IMAGE == *piIndex)
  312. MungePath(szIconFile);
  313. if (FAILED(hr))
  314. {
  315. *szIconFile = TEXT('\0');
  316. *piIndex = 0;
  317. hr = S_FALSE; // The shell will use a default icon.
  318. }
  319. ASSERT((S_OK == hr && *szIconFile) ||
  320. (S_FALSE == hr && 0 == *szIconFile));
  321. }
  322. //TraceMsg(TF_CDFICON, "<OUT> CExtractIcon::GetLocation (icon) tid:0x%x",
  323. // GetCurrentThreadId());
  324. return hr;
  325. }
  326. #ifdef UNICODE
  327. // IExtractIconA methods.
  328. STDMETHODIMP
  329. CExtractIcon::GetIconLocation(
  330. UINT uFlags,
  331. LPSTR szIconFile,
  332. UINT cchMax,
  333. int *piIndex,
  334. UINT *pwFlags
  335. )
  336. {
  337. HRESULT hr;
  338. WCHAR* pszIconFileW = new WCHAR[cchMax];
  339. if (pszIconFileW == NULL)
  340. return ERROR_OUTOFMEMORY;
  341. hr = GetIconLocation(uFlags, pszIconFileW, cchMax, piIndex, pwFlags);
  342. if (SUCCEEDED(hr))
  343. SHUnicodeToAnsi(pszIconFileW, szIconFile, cchMax);
  344. delete [] pszIconFileW;
  345. return hr;
  346. }
  347. #endif
  348. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  349. //
  350. // *** CExtractIcon::Extract ***
  351. //
  352. //
  353. // Description:
  354. // Return an icon given the name index pair returned from GetIconLocation.
  355. //
  356. // Parameters:
  357. // [In] pszFile - A pointer to the name associated with the requested
  358. // icon.
  359. // [In] nIconIndex - An index associated with the requested icon.
  360. // [Out] phiconLarge - Pointer to the variable that receives the handle of
  361. // the large icon.
  362. // [Out] phiconSmall - Pointer to the variable that receives the handle of
  363. // the small icon.
  364. // [Out] nIconSize - Value specifying the size, in pixels, of the icon
  365. // required. The LOWORD and HIWORD specify the size of
  366. // the large and small icons, respectively.
  367. //
  368. // Return:
  369. // S_OK if the icon was extracted.
  370. // S_FALSE if the shell should extract the icon assuming the name is a
  371. // filename and the index is the icon index.
  372. //
  373. // Comments:
  374. // The shell may cache the icon returned from this function.
  375. //
  376. // If the icon index indicates that the icon is specified by an internet
  377. // image then custom extraction is required.
  378. //
  379. ////////////////////////////////////////////////////////////////////////////////
  380. STDMETHODIMP
  381. CExtractIcon::Extract(
  382. LPCTSTR pszFile,
  383. UINT nIconIndex,
  384. HICON *phiconLarge,
  385. HICON *phiconSmall,
  386. UINT nIconSize
  387. )
  388. {
  389. HRESULT hr;
  390. TCHAR szPath[MAX_PATH];
  391. TCHAR* pszPath = szPath;
  392. StrCpyN(szPath, pszFile, ARRAYSIZE(szPath) - 1);
  393. //TraceMsg(TF_CDFICON, "<IN> CExtractIcon::Extract (icon) tid:0x%x",
  394. // GetCurrentThreadId());
  395. if (INDEX_IMAGE == nIconIndex)
  396. {
  397. DemungePath(pszPath);
  398. if (m_fGleam && *pszPath == TEXT('G'))
  399. {
  400. pszPath++;
  401. }
  402. IImgCtx* pIImgCtx;
  403. HANDLE hExitThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  404. if (hExitThreadEvent)
  405. {
  406. #ifdef UNIX
  407. unixEnsureFileScheme(pszPath);
  408. #endif /* UNIX */
  409. hr = SynchronousDownload(pszPath, &pIImgCtx, hExitThreadEvent);
  410. if (SUCCEEDED(hr))
  411. {
  412. ASSERT(pIImgCtx);
  413. *phiconLarge = ExtractImageIcon(LOWORD(nIconSize), pIImgCtx,
  414. m_fGleam);
  415. *phiconSmall = ExtractImageIcon(HIWORD(nIconSize), pIImgCtx,
  416. m_fGleam);
  417. pIImgCtx->Release();
  418. }
  419. SetEvent(hExitThreadEvent);
  420. }
  421. else
  422. {
  423. hr = E_OUTOFMEMORY;
  424. }
  425. }
  426. else if (m_fGleam)
  427. {
  428. // Add gleam to icon for the shell
  429. hr = ExtractGleamedIcon(pszPath + 1, nIconIndex, 0,
  430. phiconLarge, phiconSmall, nIconSize);
  431. }
  432. else
  433. {
  434. hr = S_FALSE; // Let shell extract it.
  435. }
  436. //TraceMsg(TF_CDFICON, "<OUT> CExtractIcon::Extract (icon) tid:0x%x",
  437. // GetCurrentThreadId());
  438. return hr;
  439. }
  440. #ifdef UNICODE
  441. STDMETHODIMP
  442. CExtractIcon::Extract(
  443. LPCSTR pszFile,
  444. UINT nIconIndex,
  445. HICON *phiconLarge,
  446. HICON *phiconSmall,
  447. UINT nIconSize)
  448. {
  449. HRESULT hr;
  450. int cch = lstrlenA(pszFile) + 1;
  451. WCHAR* pszFileW = new WCHAR[cch];
  452. if (pszFileW == NULL)
  453. return ERROR_OUTOFMEMORY;
  454. SHAnsiToUnicode(pszFile, pszFileW, cch);
  455. hr = Extract(pszFileW, nIconIndex, phiconLarge, phiconSmall, nIconSize);
  456. delete [] pszFileW;
  457. return hr;
  458. }
  459. #endif
  460. //
  461. // Helper functions.
  462. //
  463. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  464. //
  465. // *** CExtractIcon::GetCustomIconLocation ***
  466. //
  467. //
  468. // Description:
  469. // Gets the location string name for an icon specified via a LOGO element
  470. // in a cdf.
  471. //
  472. // Parameters:
  473. // [In] uFlags - GIL_FORSHELL, GIL_OPENICON.
  474. // [Out] szIconFile - The address of the buffer that receives the associated
  475. // icon name.
  476. // [In] cchMax - Size of the buffer that receives the icon location.
  477. // [Out] piIndex - A pointer that receives the icon's index.
  478. // [Out] pwFlags - A pointer the receives flags about the icon.
  479. //
  480. // Return:
  481. // S_OK if the custom icon location was determined.
  482. // E_FAIL if the location couldn't be determined.
  483. //
  484. // Comments:
  485. // If the extension of the image url isn't .ico then it's treated as an
  486. // internet image file. IImgCtx is used to convert these files into icons.
  487. //
  488. ////////////////////////////////////////////////////////////////////////////////
  489. HRESULT
  490. CExtractIcon::GetCustomIconLocation(
  491. UINT uFlags,
  492. LPTSTR szIconFile,
  493. UINT cchMax,
  494. int *piIndex,
  495. UINT *pwFlags
  496. )
  497. {
  498. ASSERT(szIconFile);
  499. ASSERT(piIndex);
  500. ASSERT(pwFlags);
  501. HRESULT hr;
  502. ASSERT(m_bstrIconURL);
  503. *piIndex = 0;
  504. *pwFlags = 0;
  505. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  506. if (SHUnicodeToTChar(m_bstrIconURL, szURL, ARRAYSIZE(szURL)))
  507. {
  508. hr = URLGetLocalFileName(szURL, szIconFile, cchMax, NULL);
  509. #ifdef DEBUG
  510. if (SUCCEEDED(hr))
  511. {
  512. TraceMsg(TF_CDFICON, "[URLGetLocalFileName %s]", szIconFile);
  513. }
  514. else
  515. {
  516. TraceMsg(TF_CDFICON, "[URLGetLocalFileName %s FAILED]",
  517. szURL);
  518. }
  519. #endif // DEBUG
  520. //hr = URLDownloadToCacheFile(NULL, szURL, szIconFile, cchMax, 0, NULL);
  521. if (SUCCEEDED(hr))
  522. {
  523. LPTSTR pszExt = PathFindExtension(szIconFile);
  524. if (*pszExt != TEXT('.') || 0 != StrCmpI(pszExt, TSTR_ICO_EXT))
  525. *piIndex = INDEX_IMAGE;
  526. }
  527. }
  528. else
  529. {
  530. *szIconFile = TEXT('\0');
  531. hr = E_FAIL;
  532. }
  533. return hr;
  534. }
  535. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  536. //
  537. // *** CExtractIcon::GetDefaultIconLocation ***
  538. //
  539. //
  540. // Description:
  541. // Return the location of the defualt icon.
  542. //
  543. // Parameters:
  544. // [In] uFlags - GIL_FORSHELL, GIL_OPENICON.
  545. // [Out] szIconFile - The address of the buffer that receives the associated
  546. // icon name.
  547. // [In] cchMax - Size of the buffer that receives the icon location.
  548. // [Out] piIndex - A pointer that receives the icon's index.
  549. // [Out] pwFlags - A pointer the receives flags about the icon.
  550. //
  551. // Return:
  552. // S_OK if the default location is returned.
  553. // E_FAIL otherwise.
  554. //
  555. // Comments:
  556. // The default icons are in the resource file.
  557. //
  558. ////////////////////////////////////////////////////////////////////////////////
  559. HRESULT
  560. CExtractIcon::GetDefaultIconLocation(
  561. UINT uFlags,
  562. LPTSTR szIconFile,
  563. UINT cchMax,
  564. int *piIndex,
  565. UINT *pwFlags
  566. )
  567. {
  568. ASSERT(szIconFile);
  569. ASSERT(piIndex);
  570. ASSERT(pwFlags);
  571. HRESULT hr;
  572. *pwFlags = 0;
  573. ASSERT(g_szModuleName[0]);
  574. StrCpyN(szIconFile, g_szModuleName, cchMax);
  575. if (*szIconFile)
  576. {
  577. switch (m_iconType)
  578. {
  579. case IDI_STORY:
  580. case IDI_CHANNEL:
  581. case IDI_DESKTOP:
  582. *piIndex = - m_iconType;
  583. break;
  584. default:
  585. *piIndex = (uFlags & GIL_OPENICON) ?
  586. (-IDI_OPENSUBCHANNEL) :
  587. (-IDI_CLOSESUBCHANNEL);
  588. break;
  589. }
  590. hr = S_OK;
  591. }
  592. else
  593. {
  594. hr = E_FAIL;
  595. }
  596. ASSERT((SUCCEEDED(hr) && *szIconFile) || FAILED(hr));
  597. return hr;
  598. }
  599. struct ThreadData
  600. {
  601. HANDLE hEvent;
  602. HANDLE hExitThreadEvent;
  603. IImgCtx * pImgCtx;
  604. LPCWSTR pszBuffer;
  605. HRESULT * pHr;
  606. };
  607. DWORD CALLBACK SyncDownloadThread( LPVOID pData )
  608. {
  609. ThreadData * pTD = (ThreadData * ) pData;
  610. HANDLE hExitThreadEvent = pTD->hExitThreadEvent;
  611. CoInitialize(NULL);
  612. pTD->pImgCtx = NULL;
  613. HRESULT hr;
  614. hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER,
  615. IID_IImgCtx, (void**)&(pTD->pImgCtx));
  616. if (SUCCEEDED(hr))
  617. {
  618. hr = pTD->pImgCtx->Load(pTD->pszBuffer, 0);
  619. if (SUCCEEDED(hr))
  620. {
  621. ULONG fState;
  622. SIZE sz;
  623. pTD->pImgCtx->GetStateInfo(&fState, &sz, TRUE);
  624. if (!(fState & (IMGLOAD_COMPLETE | IMGLOAD_ERROR)))
  625. {
  626. BOOL fDone = FALSE;
  627. hr = pTD->pImgCtx->SetCallback(ImgCtx_Callback, &fDone);
  628. if (SUCCEEDED(hr))
  629. {
  630. hr = pTD->pImgCtx->SelectChanges(IMGCHG_COMPLETE, 0, TRUE);
  631. if (SUCCEEDED(hr))
  632. {
  633. MSG msg;
  634. BOOL fMsg;
  635. // HACK: restrict the message pump to those messages we know that URLMON and
  636. // HACK: the imageCtx stuff needs, otherwise we will be pumping messages for
  637. // HACK: windows we shouldn't be pumping right now...
  638. while(!fDone )
  639. {
  640. fMsg = PeekMessage(&msg, NULL, WM_USER + 1, WM_USER + 4, PM_REMOVE );
  641. if (!fMsg)
  642. {
  643. fMsg = PeekMessage( &msg, NULL, WM_APP + 2, WM_APP + 2, PM_REMOVE );
  644. }
  645. if (!fMsg)
  646. {
  647. // go to sleep until we get a new message....
  648. WaitMessage();
  649. continue;
  650. }
  651. TranslateMessage(&msg);
  652. DispatchMessage(&msg);
  653. }
  654. }
  655. }
  656. }
  657. hr = pTD->pImgCtx->GetStateInfo(&fState, &sz, TRUE);
  658. if (SUCCEEDED(hr))
  659. hr = (fState & IMGLOAD_ERROR) ? E_FAIL : S_OK;
  660. }
  661. // Must disconnect on the same thread that SetCallback is
  662. // done. This object becomes a primary object on the thread
  663. // which connects the callback function. The primary object
  664. // count is decremented when Disconnect is called, or when the
  665. // object is released. In this case, the release is definitely
  666. // going to happen on a different thread than this one, so we
  667. // need to disconnect the callback function right now before
  668. // returning. There is no further needs for callbacks at this
  669. // point.
  670. pTD->pImgCtx->Disconnect();
  671. }
  672. if ( FAILED( hr ) && pTD->pImgCtx )
  673. {
  674. pTD->pImgCtx->Release();
  675. pTD->pImgCtx = NULL;
  676. }
  677. *(pTD->pHr) = hr;
  678. SetEvent( pTD->hEvent );
  679. //
  680. // Wait for the calling thread to finish up with IImgCtx before
  681. // CoUninitialize gets called.
  682. //
  683. WaitForSingleObject(hExitThreadEvent, INFINITE);
  684. CloseHandle(hExitThreadEvent);
  685. CoUninitialize();
  686. return 0;
  687. }
  688. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  689. //
  690. // *** CExtractIcon::SynchronousDownload ***
  691. //
  692. //
  693. // Description:
  694. // Synchronously downloads the image associated with the image context.
  695. //
  696. // Parameters:
  697. // [In] szFile - The local (already in cache) file name of the
  698. // image.
  699. // [In] pIImgCtx - A pointer to the image context.
  700. // [In] hExitThreadEvent - An event that gets signaled when the IImgCtx
  701. // object is no longer in use.
  702. //
  703. // Return:
  704. // S_OK if the image was successfully downloaded.
  705. // E_FAIL if the image wasn't downloaded.
  706. //
  707. // Comments:
  708. // The image context object doesn't directly support synchronous download.
  709. // Here a message loop is used to make sure ulrmon keeps geeting messages
  710. // and the download progresses.
  711. //
  712. ////////////////////////////////////////////////////////////////////////////////
  713. HRESULT
  714. CExtractIcon::SynchronousDownload(
  715. LPCTSTR pszFile,
  716. IImgCtx** ppIImgCtx,
  717. HANDLE hExitThreadEvent
  718. )
  719. {
  720. ASSERT(ppIImgCtx);
  721. HRESULT hr;
  722. TraceMsg(TF_CDFPARSE, "[*** IImgCtx downloading logo %s ***]",
  723. pszFile);
  724. TraceMsg(TF_CDFICON, "[*** IImgCtx downloading logo %s ***]",
  725. pszFile);
  726. WCHAR szFileW[MAX_PATH];
  727. SHTCharToUnicode(pszFile, szFileW, ARRAYSIZE(szFileW));
  728. ThreadData rgData;
  729. rgData.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  730. if ( rgData.hEvent == NULL )
  731. {
  732. CloseHandle(hExitThreadEvent);
  733. return E_OUTOFMEMORY;
  734. }
  735. rgData.hExitThreadEvent = hExitThreadEvent;
  736. rgData.pszBuffer = szFileW;
  737. rgData.pHr = &hr;
  738. *ppIImgCtx = NULL;
  739. if ( SHCreateThread( SyncDownloadThread, &rgData, 0, NULL ))
  740. {
  741. WaitForSingleObject( rgData.hEvent, INFINITE );
  742. *ppIImgCtx = rgData.pImgCtx;
  743. }
  744. else
  745. {
  746. CloseHandle(hExitThreadEvent);
  747. hr = E_OUTOFMEMORY;
  748. }
  749. CloseHandle( rgData.hEvent );
  750. return hr;
  751. }
  752. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  753. //
  754. // *** CExtractIcon::ExtractImageIcon ***
  755. //
  756. //
  757. // Description:
  758. // Returns an HICON for the image in IImgCtx.
  759. //
  760. // Parameters:
  761. // [In] wSize - The height and width of the icon,
  762. // [In] pIImgCtx - The image to convert into an icon.
  763. // [In] fDrawGleam - TRUE if a gleam should be added, FALSE otherwise.
  764. //
  765. // Return:
  766. // An hicon of size nSize for the given IImgCtx.
  767. // NULL on failure.
  768. //
  769. // Comments:
  770. // Uses the image in IImgCtx to create bitmaps to pass to
  771. // CreateIconIndirect.
  772. //
  773. ////////////////////////////////////////////////////////////////////////////////
  774. HICON
  775. CExtractIcon::ExtractImageIcon(
  776. WORD wSize,
  777. IImgCtx* pIImgCtx,
  778. BOOL fDrawGleam
  779. )
  780. {
  781. ASSERT(pIImgCtx);
  782. HICON hiconRet = NULL;
  783. HDC hdcScreen = GetDC(NULL);
  784. if (hdcScreen)
  785. {
  786. HBITMAP hbmImage = CreateCompatibleBitmap(hdcScreen, wSize, wSize);
  787. if (hbmImage)
  788. {
  789. HBITMAP hbmMask = CreateBitmap(wSize, wSize, 1, 1, NULL);
  790. if (hbmMask)
  791. {
  792. SIZE sz;
  793. sz.cx = sz.cy = wSize;
  794. if (SUCCEEDED(CreateImageAndMask(pIImgCtx, hdcScreen, &sz,
  795. &hbmImage, &hbmMask,
  796. fDrawGleam)))
  797. {
  798. ICONINFO ii;
  799. ii.fIcon = TRUE;
  800. ii.hbmMask = hbmMask;
  801. ii.hbmColor = hbmImage;
  802. hiconRet = CreateIconIndirect(&ii);
  803. }
  804. DeleteObject(hbmMask);
  805. }
  806. DeleteObject(hbmImage);
  807. }
  808. ReleaseDC(NULL, hdcScreen);
  809. }
  810. return hiconRet;
  811. }
  812. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  813. //
  814. // *** CExtractIcon::CreateImageAndMask ***
  815. //
  816. //
  817. // Description:
  818. // Create the image and mask bitmaps that get used by CreateIconIndirect,
  819. //
  820. // Parameters:
  821. // [In] IImgCtx - The internet image.
  822. // [In] hdcScreen - The screen hdc.
  823. // [In] pSize - The size of the image and mask bitmaps.
  824. // [In Out] phbmImage - A pointer to the handle of the Image bitmap.
  825. // [In Out] phbmMask - A pointer to the handle of the Mask bitmap.
  826. // [In] fDrawGleam - TRUE if a gleam should be added, FALSE otherwise.
  827. //
  828. // Return:
  829. // S_OK if the image and mask bitmaps where successfully created.
  830. // E_FAIL if the image or mask couldn't be created.
  831. //
  832. // Comments:
  833. // The image bitmap has the opaque section come through and the transparent
  834. // sections set to black.
  835. //
  836. // The mask has the transparent sections set to 1 and the opaque sections to
  837. // 0.
  838. //
  839. ////////////////////////////////////////////////////////////////////////////////
  840. HRESULT
  841. CExtractIcon::CreateImageAndMask(
  842. IImgCtx* pIImgCtx,
  843. HDC hdcScreen,
  844. SIZE* pSize,
  845. HBITMAP* phbmImage,
  846. HBITMAP* phbmMask,
  847. BOOL fDrawGleam
  848. )
  849. {
  850. ASSERT(pIImgCtx);
  851. ASSERT(phbmImage);
  852. ASSERT(phbmMask);
  853. HRESULT hr = E_FAIL;
  854. HDC hdcImgDst = CreateCompatibleDC(NULL);
  855. if (hdcImgDst)
  856. {
  857. HGDIOBJ hbmOld = SelectObject(hdcImgDst, *phbmImage);
  858. if (hbmOld)
  859. {
  860. if (ColorFill(hdcImgDst, pSize, COLOR1))
  861. {
  862. hr = StretchBltImage(pIImgCtx, pSize, hdcImgDst, fDrawGleam);
  863. if (SUCCEEDED(hr))
  864. {
  865. hr = CreateMask(pIImgCtx, hdcScreen, hdcImgDst, pSize,
  866. phbmMask, fDrawGleam);
  867. }
  868. }
  869. SelectObject(hdcImgDst, hbmOld);
  870. }
  871. DeleteDC(hdcImgDst);
  872. }
  873. return hr;
  874. }
  875. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  876. //
  877. // *** CExtractIcon::StretchBltImage ***
  878. //
  879. //
  880. // Description:
  881. // Stretches the image associated with IImgCtx to the given size and places
  882. // the result in the given DC.
  883. //
  884. // Parameters:
  885. // [In] pIImgCtx - The image context for the image.
  886. // [In] pSize - The size of the resultant image.
  887. // [In/Out] hdcDst - The destination DC of the stretch blt.
  888. //
  889. // Return:
  890. // S_OK if the image was successfully resized into the destination DC.
  891. // E_FAIL otherwise.
  892. //
  893. // Comments:
  894. // The destination DC already has a bitmap of pSize selected into it.
  895. //
  896. ////////////////////////////////////////////////////////////////////////////////
  897. HRESULT
  898. CExtractIcon::StretchBltImage(
  899. IImgCtx* pIImgCtx,
  900. const SIZE* pSize,
  901. HDC hdcDst,
  902. BOOL fDrawGleam
  903. )
  904. {
  905. ASSERT(pIImgCtx);
  906. ASSERT(hdcDst);
  907. HRESULT hr;
  908. SIZE sz;
  909. ULONG fState;
  910. hr = pIImgCtx->GetStateInfo(&fState, &sz, FALSE);
  911. if (SUCCEEDED(hr))
  912. {
  913. hr = pIImgCtx->StretchBlt(hdcDst, 0, 0, pSize->cx, pSize->cy, 0, 0,
  914. sz.cx, sz.cy, SRCCOPY);
  915. ASSERT(SUCCEEDED(hr) && "Icon extraction pIImgCtx->StretchBlt failed!");
  916. if (fDrawGleam)
  917. {
  918. hr = E_FAIL;
  919. HANDLE hGleam = LoadImage(g_hinst, TEXT("ICONGLEAM"),
  920. IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
  921. if (hGleam)
  922. {
  923. if (DrawIconEx(hdcDst, 0, 0, (HICON)hGleam, pSize->cx, pSize->cy, 0, NULL,DI_NORMAL))
  924. hr = S_OK;
  925. DeleteObject(hGleam);
  926. }
  927. }
  928. }
  929. return hr;
  930. }
  931. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  932. //
  933. // *** CExtractIcon::CreateMask ***
  934. //
  935. //
  936. // Description:
  937. // Creates the mask for an icon and also adjusts the image bitmap for use
  938. // with the mask.
  939. //
  940. // Parameters:
  941. // [In] pIImgCtx - The original image.
  942. // [In] hdcScreen - A screen dc.
  943. // [In/Out] hdc1 - The DC containing the image bitmap.
  944. // [In] pSize - The size of the bitmaps.
  945. // [In/Out] phbMask - A pointer to the handle of the mask bitmap
  946. //
  947. // Return:
  948. // S_OK if the mask is properly constructed.
  949. // E_FAIL otherwise.
  950. //
  951. // Comments:
  952. // The mask is created by first drawing the original image into a bitmap
  953. // with background COLOR1. Then the same image is drawn into another
  954. // bitmap but this bitmap has background of COLOR2. These two bitmaps
  955. // are XOR'ed and the opaque sections come out 0 while the transparent
  956. // sections are COLOR1 XOR COLOR2.
  957. //
  958. ////////////////////////////////////////////////////////////////////////////////
  959. HRESULT
  960. CExtractIcon::CreateMask(
  961. IImgCtx* pIImgCtx,
  962. HDC hdcScreen,
  963. HDC hdc1,
  964. const SIZE* pSize,
  965. HBITMAP* phbMask,
  966. BOOL fDrawGleam
  967. )
  968. {
  969. ASSERT(hdc1);
  970. ASSERT(pSize);
  971. ASSERT(phbMask);
  972. HRESULT hr = E_FAIL;
  973. HDC hdc2 = CreateCompatibleDC(NULL);
  974. if (hdc2)
  975. {
  976. HBITMAP hbm2 = CreateCompatibleBitmap(hdcScreen, pSize->cx, pSize->cy);
  977. if (hbm2)
  978. {
  979. HGDIOBJ hbmOld2 = SelectObject(hdc2, hbm2);
  980. if (hbmOld2)
  981. {
  982. ColorFill(hdc2, pSize, COLOR2);
  983. hr = StretchBltImage(pIImgCtx, pSize, hdc2, fDrawGleam);
  984. #ifndef UNIX
  985. if (SUCCEEDED(hr) &&
  986. BitBlt(hdc2, 0, 0, pSize->cx, pSize->cy, hdc1, 0, 0,
  987. SRCINVERT))
  988. {
  989. if (GetDeviceCaps(hdcScreen, BITSPIXEL) <= 8)
  990. {
  991. //
  992. // 6 is the XOR of the index for COLOR1 and the index
  993. // for COLOR2.
  994. //
  995. SetBkColor(hdc2, PALETTEINDEX(6));
  996. }
  997. else
  998. {
  999. SetBkColor(hdc2, (COLORREF)(COLOR1 ^ COLOR2));
  1000. }
  1001. HDC hdcMask = CreateCompatibleDC(NULL);
  1002. if (hdcMask)
  1003. {
  1004. HGDIOBJ hbmOld = SelectObject(hdcMask, *phbMask);
  1005. if (hbmOld)
  1006. {
  1007. if (BitBlt(hdcMask, 0, 0, pSize->cx, pSize->cy, hdc2, 0,
  1008. 0, SRCCOPY))
  1009. {
  1010. //
  1011. // RasterOP 0x00220326 does a copy of the ~mask bits
  1012. // of hdc1 and sets everything else to 0 (Black).
  1013. //
  1014. if (BitBlt(hdc1, 0, 0, pSize->cx, pSize->cy, hdcMask,
  1015. 0, 0, 0x00220326))
  1016. {
  1017. hr = S_OK;
  1018. }
  1019. }
  1020. SelectObject(hdcMask, hbmOld);
  1021. }
  1022. DeleteDC(hdcMask);
  1023. }
  1024. }
  1025. #else
  1026. SetBkColor(hdc2, COLOR2);
  1027. HDC hdcMask = CreateCompatibleDC(NULL);
  1028. if (hdcMask)
  1029. {
  1030. HGDIOBJ hbmOld = SelectObject(hdcMask, *phbMask);
  1031. if (hbmOld)
  1032. {
  1033. if (BitBlt(hdcMask, 0, 0, pSize->cx, pSize->cy, hdc2, 0,
  1034. 0, SRCCOPY))
  1035. {
  1036. //
  1037. // RasterOP 0x00220326 does a copy of the ~mask bits
  1038. // of hdc1 and sets everything else to 0 (Black).
  1039. //
  1040. if (BitBlt(hdc1, 0, 0, pSize->cx, pSize->cy, hdcMask,
  1041. 0, 0, 0x00220326))
  1042. {
  1043. hr = S_OK;
  1044. }
  1045. }
  1046. SelectObject(hdcMask, hbmOld);
  1047. }
  1048. DeleteDC(hdcMask);
  1049. }
  1050. #endif /* UNIX */
  1051. SelectObject(hdc2, hbmOld2);
  1052. }
  1053. DeleteObject(hbm2);
  1054. }
  1055. DeleteDC(hdc2);
  1056. }
  1057. return hr;
  1058. }
  1059. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1060. //
  1061. // *** ImgCtx_Callback ***
  1062. //
  1063. //
  1064. // Description:
  1065. // Callback function for IImgCtx loads.
  1066. //
  1067. // Parameters:
  1068. // [In] pIImgCtx - Not Used.
  1069. // [Out] pfDone - Set to TRUE on this callback.
  1070. //
  1071. // Return:
  1072. // None.
  1073. //
  1074. // Comments:
  1075. // This callback gets called if IImgCtx is finished downloading an image.
  1076. // It is used in CExtractIcon and CIconHandler.
  1077. //
  1078. ////////////////////////////////////////////////////////////////////////////////
  1079. void
  1080. CALLBACK
  1081. ImgCtx_Callback(
  1082. void* pIImgCtx,
  1083. void* pfDone
  1084. )
  1085. {
  1086. ASSERT(pfDone);
  1087. *(BOOL*)pfDone = TRUE;
  1088. return;
  1089. }
  1090. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1091. //
  1092. // *** CExtractIcon::ColorFill ***
  1093. //
  1094. //
  1095. // Description:
  1096. // Fills the given bitmap with the given color.
  1097. //
  1098. // Parameters:
  1099. // [In/Out] hdc - The hdc that contains the bitmap.
  1100. // [In] pSize - the size of the bitmap.
  1101. // [In] clr - The color used to fill in the bitmap.
  1102. //
  1103. // Return:
  1104. // TRUE if the bitmap was filled with color clr.
  1105. // FALSE if the itmap wasn't filled.
  1106. //
  1107. ////////////////////////////////////////////////////////////////////////////////
  1108. BOOL
  1109. CExtractIcon::ColorFill(
  1110. HDC hdc,
  1111. const SIZE* pSize,
  1112. COLORREF clr
  1113. )
  1114. {
  1115. ASSERT(hdc);
  1116. BOOL fRet = FALSE;
  1117. HBRUSH hbSolid = CreateSolidBrush(clr);
  1118. if (hbSolid)
  1119. {
  1120. HGDIOBJ hbOld = SelectObject(hdc, hbSolid);
  1121. if (hbOld)
  1122. {
  1123. PatBlt(hdc, 0, 0, pSize->cx, pSize->cy, PATCOPY);
  1124. fRet = TRUE;
  1125. SelectObject(hdc, hbOld);
  1126. }
  1127. DeleteObject(hbSolid);
  1128. }
  1129. return fRet;
  1130. }
  1131. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1132. //
  1133. // *** CExtractIcon::ExtractGleamedIcon ***
  1134. //
  1135. //
  1136. // Description:
  1137. // Extracts icon resources and applies gleams to them.
  1138. //
  1139. // Parameters:
  1140. // [In] pszIconFile - path to the icon
  1141. // [In] iIndex - index of icon with the file
  1142. // [In] uFlags - ignore, pass 0
  1143. // [Out] phiconLarge - HICON in large format with gleam
  1144. // [Out] phiconSmall - HICON in small format with gleam
  1145. //
  1146. // Return:
  1147. // S_OK if success
  1148. // S_FALSE if the file has no icons (or not the asked for icon)
  1149. // E_FAIL for files on a slow link.
  1150. // E_FAIL if cant access the file
  1151. // E_FAIL if gleam icon construction failed
  1152. //
  1153. ////////////////////////////////////////////////////////////////////////////////
  1154. HRESULT
  1155. CExtractIcon::ExtractGleamedIcon(
  1156. LPCTSTR pszIconFile,
  1157. int iIndex,
  1158. UINT uFlags,
  1159. HICON *phiconLarge,
  1160. HICON *phiconSmall,
  1161. UINT nIconSize)
  1162. {
  1163. HICON hIconLargeShell, hIconSmallShell;
  1164. HRESULT hr;
  1165. hr = Priv_SHDefExtractIcon(pszIconFile, iIndex, uFlags,
  1166. &hIconLargeShell, &hIconSmallShell, nIconSize);
  1167. if (FAILED(hr))
  1168. goto cleanup1;
  1169. if (hIconLargeShell)
  1170. {
  1171. hr = ApplyGleamToIcon(hIconLargeShell, LOWORD(nIconSize), phiconLarge);
  1172. if (FAILED(hr))
  1173. goto cleanup2;
  1174. }
  1175. if (hIconSmallShell)
  1176. {
  1177. hr = ApplyGleamToIcon(hIconSmallShell, HIWORD(nIconSize), phiconSmall);
  1178. if (FAILED(hr))
  1179. goto cleanup3;
  1180. }
  1181. cleanup3:
  1182. if (FAILED(hr) && *phiconLarge)
  1183. {
  1184. DestroyIcon(*phiconLarge);
  1185. *phiconLarge = NULL;
  1186. }
  1187. cleanup2:
  1188. if (hIconLargeShell)
  1189. DestroyIcon(hIconLargeShell);
  1190. if (hIconSmallShell)
  1191. DestroyIcon(hIconSmallShell);
  1192. cleanup1:
  1193. return hr;
  1194. }
  1195. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
  1196. //
  1197. // *** CExtractIcon::ApplyGleamToIcon ***
  1198. //
  1199. //
  1200. // Description:
  1201. // Makes a gleamed version of an icon.
  1202. //
  1203. // Parameters:
  1204. // [In] hIcon - icon that needs to be gleamed
  1205. // [In] nSize - size of icon in pixels
  1206. // [Out] phGleamIcon - variable to contain the gleamed icon
  1207. //
  1208. //
  1209. // Return:
  1210. // S_OK if success
  1211. // E_FAIL if unsuccessful
  1212. //
  1213. ////////////////////////////////////////////////////////////////////////////////
  1214. HRESULT
  1215. CExtractIcon::ApplyGleamToIcon(
  1216. HICON hIcon1,
  1217. ULONG nSize,
  1218. HICON *phGleamedIcon)
  1219. {
  1220. HRESULT hr = E_FAIL;
  1221. HICON hIcon2 = (HICON)LoadImage(g_hinst, TEXT("ICONGLEAM"), IMAGE_ICON,
  1222. nSize, nSize, 0);
  1223. if (hIcon2)
  1224. {
  1225. HDC dc = GetDC(NULL);
  1226. if (dc)
  1227. {
  1228. ICONINFO ii1, ii2;
  1229. if (GetIconInfo(hIcon1, &ii1) && GetIconInfo(hIcon2, &ii2))
  1230. {
  1231. HDC dcSrc = CreateCompatibleDC(dc);
  1232. if (dcSrc)
  1233. {
  1234. HDC dcDst = CreateCompatibleDC(dc);
  1235. if (dcDst)
  1236. {
  1237. HBITMAP bmMask = CreateBitmap(nSize, nSize, 1, 1, NULL);
  1238. if (bmMask)
  1239. {
  1240. HBITMAP bmImage = CreateCompatibleBitmap(dc, nSize,
  1241. nSize);
  1242. if (bmImage)
  1243. {
  1244. int cx1, cy1, cx2, cy2;
  1245. GetBitmapSize(ii1.hbmMask, &cx1, &cy1);
  1246. GetBitmapSize(ii2.hbmMask, &cx2, &cy2);
  1247. //
  1248. // Mask
  1249. //
  1250. HBITMAP hbmpOldDst = (HBITMAP)SelectObject(
  1251. dcDst,
  1252. bmMask);
  1253. HBITMAP hbmpOldSrc = (HBITMAP)SelectObject(
  1254. dcSrc,
  1255. ii1.hbmMask);
  1256. StretchBlt(dcDst, 0, 0, nSize, nSize, dcSrc, 0,
  1257. 0, cx1, cy1, SRCCOPY);
  1258. SelectObject(dcSrc, ii2.hbmMask);
  1259. StretchBlt(dcDst, 0, 0, nSize, nSize, dcSrc, 0,
  1260. 0, cx2, cy2, SRCAND);
  1261. //
  1262. // Image.
  1263. //
  1264. SelectObject(dcDst, bmImage);
  1265. SelectObject(dcSrc, ii1.hbmColor);
  1266. StretchBlt(dcDst, 0, 0, nSize, nSize, dcSrc, 0,
  1267. 0, cx1, cy1, SRCCOPY);
  1268. SelectObject(dcSrc, ii2.hbmMask);
  1269. StretchBlt(dcDst, 0, 0, nSize, nSize, dcSrc, 0,
  1270. 0, cx2, cy2, SRCAND);
  1271. SelectObject(dcSrc, ii2.hbmColor);
  1272. StretchBlt(dcDst, 0, 0, nSize, nSize, dcSrc, 0,
  1273. 0, cx2, cy2, SRCINVERT);
  1274. ii1.hbmMask = bmMask;
  1275. ii1.hbmColor = bmImage;
  1276. *phGleamedIcon = CreateIconIndirect(&ii1);
  1277. if (*phGleamedIcon)
  1278. hr = S_OK;
  1279. SelectObject(dcSrc, hbmpOldSrc);
  1280. SelectObject(dcDst, hbmpOldDst);
  1281. DeleteObject(bmImage);
  1282. }
  1283. DeleteObject(bmMask);
  1284. }
  1285. DeleteDC(dcDst);
  1286. }
  1287. DeleteDC(dcSrc);
  1288. }
  1289. }
  1290. ReleaseDC(NULL, dc);
  1291. }
  1292. DestroyIcon(hIcon2);
  1293. }
  1294. return hr;
  1295. }
  1296. //
  1297. // Get the size of the given bitmap.
  1298. //
  1299. BOOL
  1300. CExtractIcon::GetBitmapSize(HBITMAP hbmp, int* pcx, int* pcy)
  1301. {
  1302. BOOL fRet;
  1303. BITMAP bm;
  1304. if (GetObject(hbmp, sizeof(bm), &bm))
  1305. {
  1306. *pcx = bm.bmWidth;
  1307. *pcy = bm.bmHeight;
  1308. fRet = TRUE;
  1309. }
  1310. else
  1311. {
  1312. fRet = FALSE;
  1313. }
  1314. return fRet;
  1315. }
  1316. //
  1317. // Replace '\' with '*' so the path is nolonger a recognized path name. This
  1318. // is done in-place and can be called multiple times on the same string.
  1319. //
  1320. void
  1321. MungePath(LPTSTR pszPath)
  1322. {
  1323. ASSERT(pszPath);
  1324. while(*pszPath)
  1325. {
  1326. if (TEXT(FILENAME_SEPARATOR) == *pszPath)
  1327. *pszPath = TEXT('*');
  1328. pszPath++;
  1329. }
  1330. return;
  1331. }
  1332. //
  1333. // Replace '*' with '\'.
  1334. //
  1335. void
  1336. DemungePath(LPTSTR pszPath)
  1337. {
  1338. ASSERT(pszPath);
  1339. while(*pszPath)
  1340. {
  1341. if (TEXT('*') == *pszPath)
  1342. *pszPath = TEXT(FILENAME_SEPARATOR);
  1343. pszPath++;
  1344. }
  1345. return;
  1346. }