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.

705 lines
20 KiB

  1. #include "ctlspriv.h"
  2. #include "image.h"
  3. HRESULT Stream_WriteBitmap(LPSTREAM pstm, HBITMAP hbm, int cBitsPerPixel);
  4. HRESULT Stream_ReadBitmap(LPSTREAM pstm, int iExpectedBitdepth, HBITMAP* hbmp, PVOID* pvBits);
  5. HRESULT CImageList::_Read(ILFILEHEADER *pilfh, HBITMAP hbmImageI, PVOID pvBits, HBITMAP hbmMaskI)
  6. {
  7. int i;
  8. HRESULT hr = Initialize(pilfh->cx, pilfh->cy, pilfh->flags, 1, pilfh->cGrow);
  9. if (SUCCEEDED(hr))
  10. {
  11. // select into DC's before deleting existing bitmaps
  12. // patch in the bitmaps we loaded
  13. SelectObject(_hdcImage, hbmImageI);
  14. DeleteObject(_hbmImage);
  15. _hbmImage = hbmImageI;
  16. _pargbImage = (RGBQUAD*)pvBits;
  17. _clrBlend = CLR_NONE;
  18. // Same for the mask (if necessary)
  19. if (_hdcMask)
  20. {
  21. SelectObject(_hdcMask, hbmMaskI);
  22. DeleteObject(_hbmMask);
  23. _hbmMask = hbmMaskI;
  24. }
  25. _cAlloc = pilfh->cAlloc;
  26. //
  27. // Call ImageList_SetBkColor with 0 in piml->_cImage to avoid
  28. // calling expensive ImageList__ResetBkColor
  29. //
  30. _cImage = 0;
  31. _SetBkColor(pilfh->clrBk);
  32. _cImage = pilfh->cImage;
  33. for (i=0; i<NUM_OVERLAY_IMAGES; i++)
  34. _SetOverlayImage(pilfh->aOverlayIndexes[i], i+1);
  35. }
  36. else
  37. {
  38. DeleteObject(hbmImageI);
  39. DeleteObject(hbmMaskI);
  40. }
  41. return hr;
  42. }
  43. // Object: Create a 1 strip bitmap from a 4 strip bitmap.
  44. BOOL CreateUplevelBitmap(int cx, int cy, int cCount, BOOL f32bpp, BOOL fMono, HBITMAP* phbmpDest, PVOID* ppvBits)
  45. {
  46. BOOL fRet = FALSE;
  47. // src contains a 4 x cx bitmap
  48. HDC hdcSrc = CreateCompatibleDC(NULL);
  49. if (hdcSrc)
  50. {
  51. HBITMAP hbmpOldSrc = (HBITMAP)SelectObject(hdcSrc, *phbmpDest);
  52. HDC hdcDest = CreateCompatibleDC(NULL);
  53. if (hdcDest)
  54. {
  55. HBITMAP hbmpDest;
  56. if (fMono)
  57. {
  58. hbmpDest = CreateMonoBitmap(cx, cy * cCount);
  59. }
  60. else
  61. {
  62. if (f32bpp)
  63. {
  64. hbmpDest = CreateDIB(hdcSrc, cx, cy * cCount, (RGBQUAD**)ppvBits);
  65. }
  66. else
  67. {
  68. hbmpDest = CreateCompatibleBitmap(hdcSrc, cx, cy * cCount);
  69. if (hbmpDest)
  70. {
  71. BITMAP bm;
  72. GetObject(hbmpDest, sizeof(bm), &bm);
  73. *ppvBits = bm.bmBits;
  74. }
  75. }
  76. }
  77. if (hbmpDest)
  78. {
  79. HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcDest, hbmpDest);
  80. for (int i = 0; i < cCount; i++)
  81. {
  82. int xSrc = cx * (i % 4);
  83. int ySrc = cy * (i / 4);
  84. int yDst = cy * i;
  85. BitBlt(hdcDest, 0, yDst, cx, cy, hdcSrc, xSrc, ySrc, SRCCOPY);
  86. }
  87. fRet = TRUE;
  88. SelectObject(hdcDest, hbmpOld);
  89. DeleteObject(*phbmpDest);
  90. *phbmpDest = hbmpDest;
  91. }
  92. DeleteDC(hdcDest);
  93. }
  94. SelectObject(hdcSrc, hbmpOldSrc);
  95. DeleteDC(hdcSrc);
  96. }
  97. return fRet;
  98. }
  99. STDMETHODIMP CImageList::LoadEx(DWORD dwFlags, IStream* pstm)
  100. {
  101. if (pstm == NULL)
  102. return E_INVALIDARG;
  103. HRESULT hr = InitGlobals();
  104. if (SUCCEEDED(hr))
  105. {
  106. ENTERCRITICAL;
  107. ILFILEHEADER ilfh = {0};
  108. HBITMAP hbmImageI = NULL;
  109. HBITMAP hbmMaskI = NULL;
  110. HBITMAP hbmMirroredImage;
  111. HBITMAP hbmMirroredMask;
  112. BOOL bMirroredIL = FALSE;
  113. // fist read in the old struct
  114. hr = pstm->Read(&ilfh, ILFILEHEADER_SIZE0, NULL);
  115. if (SUCCEEDED(hr) && (ilfh.magic != IMAGELIST_MAGIC ||
  116. (ilfh.version != IMAGELIST_VER6 && ilfh.version != IMAGELIST_VER0)))
  117. {
  118. hr = E_FAIL;
  119. }
  120. if (ilfh.version == IMAGELIST_VER0)
  121. dwFlags |= ILP_DOWNLEVEL;
  122. if (ilfh.version == IMAGELIST_VER6)
  123. dwFlags &= ~ILP_DOWNLEVEL; // Uplevel, Don't run in compat mode.
  124. if (SUCCEEDED(hr))
  125. {
  126. PVOID pvBits, pvBitsMirror;
  127. hbmMaskI = NULL;
  128. hbmMirroredMask = NULL;
  129. hr = Stream_ReadBitmap(pstm, (ilfh.flags&ILC_COLORMASK), &hbmImageI, &pvBits);
  130. if (SUCCEEDED(hr))
  131. {
  132. if (dwFlags & ILP_DOWNLEVEL)
  133. CreateUplevelBitmap(ilfh.cx, ilfh.cy, ilfh.cAlloc, (ilfh.flags & ILC_COLOR32), FALSE, &hbmImageI, &pvBits);
  134. if (ilfh.flags & ILC_MASK)
  135. {
  136. hr = Stream_ReadBitmap(pstm, 1, &hbmMaskI, NULL);
  137. if (FAILED(hr))
  138. {
  139. DeleteBitmap(hbmImageI);
  140. hbmImageI = NULL;
  141. }
  142. else if (dwFlags & ILP_DOWNLEVEL)
  143. {
  144. CreateUplevelBitmap(ilfh.cx, ilfh.cy, ilfh.cAlloc, FALSE, TRUE, &hbmMaskI, NULL);
  145. }
  146. }
  147. if (SUCCEEDED(hr))
  148. {
  149. // Read in the rest of the struct, new overlay stuff.
  150. if (ilfh.flags & ILC_MOREOVERLAY)
  151. {
  152. hr = pstm->Read((LPBYTE)&ilfh + ILFILEHEADER_SIZE0, sizeof(ilfh) - ILFILEHEADER_SIZE0, NULL);
  153. if (SUCCEEDED(hr))
  154. {
  155. ilfh.flags &= ~ILC_MOREOVERLAY;
  156. }
  157. }
  158. else
  159. {
  160. // Properly initialize the new stuff since we are not reading it in...
  161. for (int i = NUM_OVERLAY_IMAGES_0; i < NUM_OVERLAY_IMAGES; i++)
  162. ilfh.aOverlayIndexes[i] = -1;
  163. }
  164. }
  165. if (SUCCEEDED(hr))
  166. {
  167. if (ilfh.flags & ILC_MIRROR)
  168. {
  169. ilfh.flags &= ~ILC_MIRROR;
  170. bMirroredIL = TRUE;
  171. hr = Stream_ReadBitmap(pstm, (ilfh.flags&ILC_COLORMASK), &hbmMirroredImage, &pvBitsMirror);
  172. if (SUCCEEDED(hr))
  173. {
  174. if (dwFlags & ILP_DOWNLEVEL)
  175. CreateUplevelBitmap(ilfh.cx, ilfh.cy, ilfh.cAlloc, (ilfh.flags & ILC_COLOR32), FALSE, &hbmMirroredImage, &pvBitsMirror);
  176. if (ilfh.flags & ILC_MASK)
  177. {
  178. hr = Stream_ReadBitmap(pstm, 1, &hbmMirroredMask, NULL);
  179. if (FAILED(hr))
  180. {
  181. DeleteBitmap(hbmMirroredImage);
  182. hbmMirroredImage = NULL;
  183. }
  184. else if (dwFlags & ILP_DOWNLEVEL)
  185. {
  186. CreateUplevelBitmap(ilfh.cx, ilfh.cy, ilfh.cAlloc, FALSE, TRUE, &hbmMirroredMask, NULL);
  187. }
  188. }
  189. }
  190. }
  191. if (SUCCEEDED(hr))
  192. {
  193. hr = _Read(&ilfh, hbmImageI, pvBits, hbmMaskI);
  194. if(SUCCEEDED(hr))
  195. {
  196. _ScanForAlpha();
  197. if (bMirroredIL)
  198. {
  199. hr = E_OUTOFMEMORY;
  200. _pimlMirror = new CImageList();
  201. if (_pimlMirror)
  202. {
  203. hr = _pimlMirror->_Read(&ilfh, hbmMirroredImage, pvBitsMirror, hbmMirroredMask);
  204. if (SUCCEEDED(hr))
  205. _pimlMirror->_ScanForAlpha();
  206. }
  207. }
  208. }
  209. }
  210. if (FAILED(hr))
  211. {
  212. if (hbmImageI)
  213. DeleteBitmap(hbmImageI);
  214. if (hbmMaskI)
  215. DeleteBitmap(hbmMaskI);
  216. }
  217. }
  218. }
  219. }
  220. LEAVECRITICAL;
  221. }
  222. return hr;
  223. }
  224. BOOL CImageList::_MoreOverlaysUsed()
  225. {
  226. int i;
  227. for (i = NUM_OVERLAY_IMAGES_0; i < NUM_OVERLAY_IMAGES; i++)
  228. if (_aOverlayIndexes[i] != -1)
  229. return TRUE;
  230. return FALSE;
  231. }
  232. // Object: Create a 4 strip bitmap from a single strip bitmap.
  233. BOOL CreateDownlevelBitmap(int cx, int cy, int cCount, HDC hdc, HBITMAP hbmp, HBITMAP* hbmpDest)
  234. {
  235. BOOL fRet = FALSE;
  236. HDC hdcDest = CreateCompatibleDC(hdc);
  237. if (hdcDest)
  238. {
  239. *hbmpDest = CreateCompatibleBitmap(hdc, 4 * cx, cy * ((cCount / 4) + 1));
  240. if (*hbmpDest)
  241. {
  242. HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcDest, *hbmpDest);
  243. for (int i = 0; i < cCount; i++)
  244. {
  245. int xDest = cx * (i % 4);
  246. int yDest = cy * (i / 4);
  247. int ySrc = cy * i;
  248. BitBlt(hdcDest, xDest, yDest, cx, cy, hdc, 0, ySrc, SRCCOPY);
  249. }
  250. fRet = TRUE;
  251. SelectObject(hdcDest, hbmpOld);
  252. }
  253. DeleteDC(hdcDest);
  254. }
  255. return fRet;
  256. }
  257. STDMETHODIMP CImageList::SaveEx(DWORD dwFlags, IStream* pstm)
  258. {
  259. int i;
  260. ILFILEHEADER ilfh;
  261. HRESULT hr = S_OK;
  262. HBITMAP hbmpMask = _hbmMask;
  263. HBITMAP hbmpImage = _hbmImage;
  264. if (pstm == NULL)
  265. return E_INVALIDARG;
  266. ilfh.magic = IMAGELIST_MAGIC;
  267. if (dwFlags == ILP_NORMAL)
  268. ilfh.version = IMAGELIST_VER6;
  269. else
  270. ilfh.version = IMAGELIST_VER0;
  271. ilfh.cImage = (SHORT) _cImage;
  272. ilfh.cAlloc = (SHORT) _cAlloc;
  273. ilfh.cGrow = (SHORT) _cGrow;
  274. ilfh.cx = (SHORT) _cx;
  275. ilfh.cy = (SHORT) _cy;
  276. ilfh.clrBk = _clrBk;
  277. ilfh.flags = (SHORT) _flags;
  278. if (dwFlags == ILP_DOWNLEVEL)
  279. {
  280. CreateDownlevelBitmap(_cx, _cy, _cImage, _hdcImage, _hbmImage, &hbmpImage);
  281. if (_hbmMask)
  282. CreateDownlevelBitmap(_cx, _cy, _cImage, _hdcMask, _hbmMask, &hbmpMask);
  283. }
  284. //
  285. // Store mirror flags
  286. //
  287. if (_pimlMirror)
  288. ilfh.flags |= ILC_MIRROR;
  289. if (_MoreOverlaysUsed())
  290. ilfh.flags |= ILC_MOREOVERLAY;
  291. for (i=0; i < NUM_OVERLAY_IMAGES; i++)
  292. ilfh.aOverlayIndexes[i] = (SHORT) _aOverlayIndexes[i];
  293. hr = pstm->Write(&ilfh, ILFILEHEADER_SIZE0, NULL);
  294. if (SUCCEEDED(hr))
  295. {
  296. hr = Stream_WriteBitmap(pstm, hbmpImage, 0);
  297. if (SUCCEEDED(hr))
  298. {
  299. if (_hdcMask)
  300. {
  301. hr = Stream_WriteBitmap(pstm, hbmpMask, 1);
  302. }
  303. if (SUCCEEDED(hr))
  304. {
  305. if (ilfh.flags & ILC_MOREOVERLAY)
  306. hr = pstm->Write((LPBYTE)&ilfh + ILFILEHEADER_SIZE0, sizeof(ilfh) - ILFILEHEADER_SIZE0, NULL);
  307. if (_pimlMirror)
  308. {
  309. HBITMAP hbmpImageM = _pimlMirror->_hbmImage;
  310. HBITMAP hbmpMaskM = _pimlMirror->_hbmMask;
  311. if (dwFlags == ILP_DOWNLEVEL)
  312. {
  313. CreateDownlevelBitmap(_cx, _cy, _pimlMirror->_cImage, _pimlMirror->_hdcImage, _pimlMirror->_hbmImage, &hbmpImageM);
  314. if (_hbmMask)
  315. CreateDownlevelBitmap(_cx, _cy, _pimlMirror->_cImage, _pimlMirror->_hdcMask, _pimlMirror->_hbmMask, &hbmpMaskM);
  316. }
  317. // Don't call pidlMirror's Save, because of the header difference.
  318. hr = Stream_WriteBitmap(pstm, hbmpImageM, 0);
  319. if (_pimlMirror->_hdcMask)
  320. {
  321. hr = Stream_WriteBitmap(pstm, hbmpMaskM, 1);
  322. }
  323. if (hbmpMaskM && (hbmpMaskM != _pimlMirror->_hbmMask))
  324. DeleteObject(hbmpMaskM);
  325. if (hbmpImageM && (hbmpImageM != _pimlMirror->_hbmImage))
  326. DeleteObject(hbmpImageM);
  327. }
  328. }
  329. }
  330. }
  331. if (hbmpMask && (hbmpMask != _hbmMask))
  332. DeleteObject(hbmpMask);
  333. if (hbmpImage && (hbmpImage != _hbmImage))
  334. DeleteObject(hbmpImage);
  335. return hr;
  336. }
  337. STDMETHODIMP CImageList::Load(IStream* pstm)
  338. {
  339. return LoadEx(ILP_NORMAL, pstm);
  340. }
  341. STDMETHODIMP CImageList::Save(IStream* pstm, int fClearDirty)
  342. {
  343. return SaveEx(ILP_NORMAL, pstm);
  344. }
  345. HRESULT Stream_WriteBitmap(LPSTREAM pstm, HBITMAP hbm, int cBitsPerPixel)
  346. {
  347. BOOL fSuccess;
  348. BITMAP bm;
  349. int cx, cy;
  350. BITMAPFILEHEADER bf;
  351. BITMAPINFOHEADER bi;
  352. BITMAPINFOHEADER * pbi;
  353. BYTE * pbuf;
  354. HDC hdc;
  355. UINT cbColorTable;
  356. int cLines;
  357. int cLinesWritten;
  358. HRESULT hr = E_INVALIDARG;
  359. ASSERT(pstm);
  360. fSuccess = FALSE;
  361. hdc = NULL;
  362. pbi = NULL;
  363. pbuf = NULL;
  364. if (GetObject(hbm, sizeof(bm), &bm) != sizeof(bm))
  365. goto Error;
  366. hdc = GetDC(HWND_DESKTOP);
  367. cx = bm.bmWidth;
  368. cy = bm.bmHeight;
  369. if (cBitsPerPixel == 0)
  370. cBitsPerPixel = bm.bmPlanes * bm.bmBitsPixel;
  371. if (cBitsPerPixel <= 8)
  372. cbColorTable = (1 << cBitsPerPixel) * sizeof(RGBQUAD);
  373. else
  374. cbColorTable = 0;
  375. bi.biSize = sizeof(bi);
  376. bi.biWidth = cx;
  377. bi.biHeight = cy;
  378. bi.biPlanes = 1;
  379. bi.biBitCount = (WORD) cBitsPerPixel;
  380. bi.biCompression = BI_RGB; // RLE not supported!
  381. bi.biSizeImage = 0;
  382. bi.biXPelsPerMeter = 0;
  383. bi.biYPelsPerMeter = 0;
  384. bi.biClrUsed = 0;
  385. bi.biClrImportant = 0;
  386. bf.bfType = BFTYPE_BITMAP;
  387. bf.bfOffBits = sizeof(BITMAPFILEHEADER) +
  388. sizeof(BITMAPINFOHEADER) + cbColorTable;
  389. bf.bfSize = bf.bfOffBits + bi.biSizeImage;
  390. bf.bfReserved1 = 0;
  391. bf.bfReserved2 = 0;
  392. hr = E_OUTOFMEMORY;
  393. pbi = (BITMAPINFOHEADER *)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + cbColorTable);
  394. if (!pbi)
  395. goto Error;
  396. // Get the color table and fill in the rest of *pbi
  397. //
  398. *pbi = bi;
  399. if (GetDIBits(hdc, hbm, 0, cy, NULL, (BITMAPINFO *)pbi, DIB_RGB_COLORS) == 0)
  400. goto Error;
  401. if (cBitsPerPixel == 1)
  402. {
  403. ((DWORD *)(pbi+1))[0] = CLR_BLACK;
  404. ((DWORD *)(pbi+1))[1] = CLR_WHITE;
  405. }
  406. pbi->biSizeImage = WIDTHBYTES(cx, cBitsPerPixel) * cy;
  407. hr = pstm->Write(&bf, sizeof(bf), NULL);
  408. if (FAILED(hr))
  409. goto Error;
  410. hr = pstm->Write(pbi, sizeof(bi) + cbColorTable, NULL);
  411. if (FAILED(hr))
  412. goto Error;
  413. //
  414. // if we have a DIBSection just write the bits out
  415. //
  416. if (bm.bmBits != NULL)
  417. {
  418. hr = pstm->Write(bm.bmBits, pbi->biSizeImage, NULL);
  419. if (FAILED(hr))
  420. goto Error;
  421. goto Done;
  422. }
  423. // Calculate number of horizontal lines that'll fit into our buffer...
  424. //
  425. cLines = CBDIBBUF / WIDTHBYTES(cx, cBitsPerPixel);
  426. hr = E_OUTOFMEMORY;
  427. pbuf = (PBYTE)LocalAlloc(LPTR, CBDIBBUF);
  428. if (!pbuf)
  429. goto Error;
  430. for (cLinesWritten = 0; cLinesWritten < cy; cLinesWritten += cLines)
  431. {
  432. hr = E_OUTOFMEMORY;
  433. if (cLines > cy - cLinesWritten)
  434. cLines = cy - cLinesWritten;
  435. if (GetDIBits(hdc, hbm, cLinesWritten, cLines,
  436. pbuf, (BITMAPINFO *)pbi, DIB_RGB_COLORS) == 0)
  437. goto Error;
  438. hr = pstm->Write(pbuf, WIDTHBYTES(cx, cBitsPerPixel) * cLines, NULL);
  439. if (FAILED(hr))
  440. goto Error;
  441. }
  442. Done:
  443. hr = S_OK;
  444. Error:
  445. if (hdc)
  446. ReleaseDC(HWND_DESKTOP, hdc);
  447. if (pbi)
  448. LocalFree((HLOCAL)pbi);
  449. if (pbuf)
  450. LocalFree((HLOCAL)pbuf);
  451. return hr;
  452. }
  453. HRESULT Stream_ReadBitmap(LPSTREAM pstm, int iExpectedBitdepth, HBITMAP* phbmp, PVOID* ppvBits)
  454. {
  455. HDC hdc = NULL;
  456. HBITMAP hbm = NULL;
  457. BITMAPFILEHEADER bf;
  458. BITMAPINFOHEADER bi;
  459. BITMAPINFOHEADER * pbi = NULL;
  460. BYTE * pbuf=NULL;
  461. int cBitsPerPixel;
  462. UINT cbColorTable;
  463. int cx, cy;
  464. int cLines, cLinesRead;
  465. HRESULT hr = pstm->Read(&bf, sizeof(bf), NULL);
  466. if (FAILED(hr))
  467. goto Error;
  468. hr = E_INVALIDARG;
  469. if (bf.bfType != BFTYPE_BITMAP)
  470. goto Error;
  471. hr = pstm->Read(&bi, sizeof(bi), NULL);
  472. if (FAILED(hr))
  473. goto Error;
  474. hr = E_INVALIDARG;
  475. if (bi.biSize != sizeof(bi))
  476. goto Error;
  477. cx = (int)bi.biWidth;
  478. cy = (int)bi.biHeight;
  479. cBitsPerPixel = (int)bi.biBitCount * (int)bi.biPlanes;
  480. if (iExpectedBitdepth != ILC_COLORDDB &&
  481. cBitsPerPixel != iExpectedBitdepth)
  482. {
  483. goto Error;
  484. }
  485. if (cBitsPerPixel <= 8)
  486. cbColorTable = (1 << cBitsPerPixel) * sizeof(RGBQUAD);
  487. else
  488. cbColorTable = 0;
  489. hr = E_OUTOFMEMORY;
  490. pbi = (BITMAPINFOHEADER*)LocalAlloc(LPTR, sizeof(bi) + cbColorTable);
  491. if (!pbi)
  492. goto Error;
  493. *pbi = bi;
  494. pbi->biSizeImage = WIDTHBYTES(cx, cBitsPerPixel) * cy;
  495. if (cbColorTable)
  496. {
  497. hr = pstm->Read(pbi + 1, cbColorTable, NULL);
  498. if (FAILED(hr))
  499. goto Error;
  500. }
  501. hdc = GetDC(HWND_DESKTOP);
  502. //
  503. // see if we can make a DIBSection
  504. //
  505. if ((cBitsPerPixel > 1) && (iExpectedBitdepth != ILC_COLORDDB))
  506. {
  507. //
  508. // create DIBSection and read the bits directly into it!
  509. //
  510. hr = E_OUTOFMEMORY;
  511. hbm = CreateDIBSection(hdc, (LPBITMAPINFO)pbi, DIB_RGB_COLORS, (void**)&pbuf, NULL, 0);
  512. if (hbm == NULL)
  513. goto Error;
  514. hr = pstm->Read(pbuf, pbi->biSizeImage, NULL);
  515. if (FAILED(hr))
  516. goto Error;
  517. if (ppvBits)
  518. *ppvBits = pbuf;
  519. pbuf = NULL; // dont free this
  520. goto Done;
  521. }
  522. //
  523. // cant make a DIBSection make a mono or color bitmap.
  524. //
  525. else if (cBitsPerPixel > 1)
  526. hbm = CreateColorBitmap(cx, cy);
  527. else
  528. hbm = CreateMonoBitmap(cx, cy);
  529. hr = E_OUTOFMEMORY;
  530. if (!hbm)
  531. goto Error;
  532. // Calculate number of horizontal lines that'll fit into our buffer...
  533. //
  534. cLines = CBDIBBUF / WIDTHBYTES(cx, cBitsPerPixel);
  535. hr = E_OUTOFMEMORY;
  536. pbuf = (PBYTE)LocalAlloc(LPTR, CBDIBBUF);
  537. if (!pbuf)
  538. goto Error;
  539. for (cLinesRead = 0; cLinesRead < cy; cLinesRead += cLines)
  540. {
  541. if (cLines > cy - cLinesRead)
  542. cLines = cy - cLinesRead;
  543. hr = pstm->Read(pbuf, WIDTHBYTES(cx, cBitsPerPixel) * cLines, NULL);
  544. if (FAILED(hr))
  545. goto Error;
  546. hr = E_OUTOFMEMORY;
  547. if (!SetDIBits(hdc, hbm, cLinesRead, cLines,
  548. pbuf, (BITMAPINFO *)pbi, DIB_RGB_COLORS))
  549. {
  550. goto Error;
  551. }
  552. }
  553. Done:
  554. hr = S_OK;
  555. Error:
  556. if (hdc)
  557. ReleaseDC(HWND_DESKTOP, hdc);
  558. if (pbi)
  559. LocalFree((HLOCAL)pbi);
  560. if (pbuf)
  561. LocalFree((HLOCAL)pbuf);
  562. if (FAILED(hr) && hbm)
  563. {
  564. DeleteBitmap(hbm);
  565. hbm = NULL;
  566. }
  567. *phbmp = hbm;
  568. return hr;
  569. }