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.

1904 lines
43 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: gen.cpp
  7. //
  8. // Contents: Implementation of the generic picture object (CGenObject)
  9. // and dib routines.
  10. //
  11. // Classes: CGenObject implementation
  12. //
  13. // Functions: DibDraw (internal)
  14. // DibMakeLogPalette (internal)
  15. // DibFillPaletteEntries (internal)
  16. //
  17. // History: dd-mmm-yy Author Comment
  18. // 01-Feb-95 t-ScottH add Dump method and DumpCGenObject API
  19. // 25-Jan-94 alexog first pass at converting to Cairo-style
  20. // memory allocations.
  21. // 11-Jan-94 alexgo added VDATEHEAP macros to every function
  22. // and method
  23. // 07-Dec-93 ChrisWe make default params to StSetSize explicit
  24. // 07-Dec-93 alexgo merged 16bit RC9 changes
  25. // 29-Nov-93 ChrisWe make default arguments to UtDupGlobal,
  26. // UtConvertBitmapToDib explicit
  27. // 23-Nov-93 alexgo 32bit port
  28. // srinik 06/04/93 Added the support for demand loading and
  29. // discarding the caches.
  30. // SriniK 03/19/1993 Deleted dib.cpp and moved DIB drawing routines
  31. // into this file.
  32. // SriniK 01/07/1993 Merged dib.cpp into gen.cpp
  33. //
  34. //--------------------------------------------------------------------------
  35. /*
  36. REVIEW32::: WARNING WARNING
  37. There are many potentially bogus pointer to Palette, etc handle conversions
  38. put in to make the code compile. :(
  39. (Gee, thanks for marking them as you went)
  40. */
  41. #include <le2int.h>
  42. #pragma SEG(gen)
  43. #include "gen.h"
  44. #ifdef _DEBUG
  45. #include <dbgdump.h>
  46. #endif // _DEBUG
  47. ASSERTDATA
  48. #define M_HPRES() (m_hPres ? m_hPres : LoadHPRES())
  49. //local functions
  50. INTERNAL DibDraw(HANDLE hDib, HDC hdc, LPCRECTL lprc);
  51. INTERNAL_(HANDLE) DibMakeLogPalette (BYTE FAR *lpColorData,
  52. WORD wDataSize,
  53. LPLOGPALETTE FAR* lplpLogPalette);
  54. INTERNAL_(void) DibFillPaletteEntries(BYTE FAR *lpColorData,
  55. WORD wDataSize, LPLOGPALETTE lpLogPalette);
  56. /*
  57. * IMPLEMENTATION of CGenObject
  58. *
  59. */
  60. NAME_SEG(Gen)
  61. //+-------------------------------------------------------------------------
  62. //
  63. // Member: CGenObject::CGenObject
  64. //
  65. // Synopsis: Constructor
  66. //
  67. // Effects:
  68. //
  69. // Arguments: [pCacheNode] -- cache for the object
  70. // [cfFormat] -- clipboard format of the object
  71. // [dwAspect] -- drawing aspect of the object
  72. //
  73. // Requires:
  74. //
  75. // Returns: void
  76. //
  77. // Signals:
  78. //
  79. // Modifies:
  80. //
  81. // Derivation:
  82. //
  83. // Algorithm: just initializes member variables
  84. //
  85. // History: dd-mmm-yy Author Comment
  86. // 23-Nov-93 alexgo 32bit port
  87. //
  88. // Notes:
  89. //
  90. //--------------------------------------------------------------------------
  91. #pragma SEG(CGenObject_ctor)
  92. CGenObject::CGenObject(LPCACHENODE pCacheNode, CLIPFORMAT cfFormat,
  93. DWORD dwAspect)
  94. {
  95. VDATEHEAP();
  96. m_ulRefs = 1;
  97. m_dwSize = NULL;
  98. m_lWidth = NULL;
  99. m_lHeight = NULL;
  100. m_hPres = NULL;
  101. m_cfFormat = cfFormat;
  102. m_dwAspect = dwAspect;
  103. m_pCacheNode = pCacheNode;
  104. }
  105. //+-------------------------------------------------------------------------
  106. //
  107. // Member: CGenObject::~CGenObject
  108. //
  109. // Synopsis: Destructor
  110. //
  111. // Effects:
  112. //
  113. // Arguments: void
  114. //
  115. // Requires:
  116. //
  117. // Returns: void
  118. //
  119. // Signals:
  120. //
  121. // Modifies:
  122. //
  123. // Derivation:
  124. //
  125. // Algorithm:
  126. //
  127. // History: dd-mmm-yy Author Comment
  128. // 23-Nov-93 alexgo 32bit port
  129. //
  130. // Notes:
  131. //
  132. //--------------------------------------------------------------------------
  133. #pragma SEG(CGenObject_dtor)
  134. CGenObject::~CGenObject(void)
  135. {
  136. VDATEHEAP();
  137. if (m_hPres)
  138. {
  139. LEVERIFY( NULL == GlobalFree (m_hPres));
  140. }
  141. }
  142. //+-------------------------------------------------------------------------
  143. //
  144. // Member: CGenObject::QueryInterface
  145. //
  146. // Synopsis: returns interfaces on the generic picture object
  147. //
  148. // Effects:
  149. //
  150. // Arguments: [iid] -- the requested interface ID
  151. // [ppvObj] -- where to put the interface pointer
  152. //
  153. // Requires:
  154. //
  155. // Returns: NOERROR, E_NOINTERFACE
  156. //
  157. // Signals:
  158. //
  159. // Modifies:
  160. //
  161. // Derivation: IUnkown
  162. //
  163. // Algorithm:
  164. //
  165. // History: dd-mmm-yy Author Comment
  166. // 23-Nov-93 alexgo 32bit port
  167. //
  168. // Notes:
  169. //
  170. //--------------------------------------------------------------------------
  171. #pragma SEG(CGenObject_QueryInterface)
  172. STDMETHODIMP CGenObject::QueryInterface (REFIID iid, void FAR* FAR* ppvObj)
  173. {
  174. VDATEHEAP();
  175. if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IOlePresObj))
  176. {
  177. *ppvObj = this;
  178. AddRef();
  179. return NOERROR;
  180. }
  181. else
  182. {
  183. *ppvObj = NULL;
  184. return ResultFromScode(E_NOINTERFACE);
  185. }
  186. }
  187. //+-------------------------------------------------------------------------
  188. //
  189. // Member: CGenObject::AddRef
  190. //
  191. // Synopsis: increments the reference count
  192. //
  193. // Effects:
  194. //
  195. // Arguments:
  196. //
  197. // Requires:
  198. //
  199. // Returns: ULONG -- the new reference count
  200. //
  201. // Signals:
  202. //
  203. // Modifies:
  204. //
  205. // Derivation: IUnknown
  206. //
  207. // Algorithm:
  208. //
  209. // History: dd-mmm-yy Author Comment
  210. // 23-Nov-93 alexgo 32bit port
  211. //
  212. // Notes:
  213. //
  214. //--------------------------------------------------------------------------
  215. #pragma SEG(CGenObject_AddRef)
  216. STDMETHODIMP_(ULONG) CGenObject::AddRef(void)
  217. {
  218. VDATEHEAP();
  219. return ++m_ulRefs;
  220. }
  221. //+-------------------------------------------------------------------------
  222. //
  223. // Member: CGenObject::Release
  224. //
  225. // Synopsis: Decrements the reference count
  226. //
  227. // Effects: may delete [this] object
  228. //
  229. // Arguments:
  230. //
  231. // Requires:
  232. //
  233. // Returns: ULONG -- the new reference count
  234. //
  235. // Signals:
  236. //
  237. // Modifies:
  238. //
  239. // Derivation: IUnknown
  240. //
  241. // Algorithm:
  242. //
  243. // History: dd-mmm-yy Author Comment
  244. // 23-Nov-93 alexgo 32bit port
  245. //
  246. // Notes:
  247. //
  248. //--------------------------------------------------------------------------
  249. #pragma SEG(CGenObject_Release)
  250. STDMETHODIMP_(ULONG) CGenObject::Release(void)
  251. {
  252. VDATEHEAP();
  253. if (--m_ulRefs == 0)
  254. {
  255. delete this;
  256. return 0;
  257. }
  258. return m_ulRefs;
  259. }
  260. //+-------------------------------------------------------------------------
  261. //
  262. // Member: CGenObject::GetData
  263. //
  264. // Synopsis: retrieves data of the specified format
  265. //
  266. // Effects:
  267. //
  268. // Arguments: [pformatetcIn] -- the requested data format
  269. // [pmedium] -- where to put the data
  270. //
  271. // Requires:
  272. //
  273. // Returns: HRESULT
  274. //
  275. // Signals:
  276. //
  277. // Modifies:
  278. //
  279. // Derivation: IOlePresObject
  280. //
  281. // Algorithm: If available, copies the presentation to pmedium
  282. //
  283. // History: dd-mmm-yy Author Comment
  284. // 23-Nov-93 alexgo 32bit port
  285. //
  286. // Notes:
  287. //
  288. //--------------------------------------------------------------------------
  289. #pragma SEG(CGenObject_GetData)
  290. STDMETHODIMP CGenObject::GetData
  291. (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
  292. {
  293. VDATEHEAP();
  294. SCODE sc;
  295. if (IsBlank())
  296. {
  297. sc = OLE_E_BLANK;
  298. }
  299. else if (pformatetcIn->cfFormat != m_cfFormat)
  300. {
  301. if (m_cfFormat == CF_DIB &&
  302. pformatetcIn->cfFormat == CF_BITMAP)
  303. {
  304. return GetBitmapData(pformatetcIn, pmedium);
  305. }
  306. else
  307. {
  308. sc = DV_E_CLIPFORMAT;
  309. }
  310. }
  311. else if (0 == (pformatetcIn->tymed & TYMED_HGLOBAL))
  312. {
  313. sc = DV_E_TYMED;
  314. }
  315. else
  316. {
  317. if (NULL == (pmedium->hGlobal = GetCopyOfHPRES()))
  318. {
  319. sc = E_OUTOFMEMORY;
  320. goto errRtn;
  321. }
  322. pmedium->tymed = TYMED_HGLOBAL;
  323. return NOERROR;
  324. }
  325. errRtn:
  326. // null out in case of error
  327. pmedium->tymed = TYMED_NULL;
  328. pmedium->pUnkForRelease = NULL;
  329. return ResultFromScode(sc);
  330. }
  331. //+-------------------------------------------------------------------------
  332. //
  333. // Member: CGenObject::GetDataHere
  334. //
  335. // Synopsis: retrieves presentation data into the given pmedium
  336. //
  337. // Effects:
  338. //
  339. // Arguments: [pformatetcIn] -- the requested data format
  340. // [pmedium] -- where to put the data
  341. //
  342. // Requires:
  343. //
  344. // Returns: HRESULT
  345. //
  346. // Signals:
  347. //
  348. // Modifies:
  349. //
  350. // Derivation: IOlePresObj
  351. //
  352. // Algorithm: copies presentation data into the given storage medium
  353. // after error checking on the arguments
  354. //
  355. // History: dd-mmm-yy Author Comment
  356. // 23-Nov-93 alexgo 32bit port
  357. //
  358. // Notes:
  359. //
  360. //--------------------------------------------------------------------------
  361. #pragma SEG(CGenObject_GetDataHere)
  362. STDMETHODIMP CGenObject::GetDataHere
  363. (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
  364. {
  365. VDATEHEAP();
  366. SCODE scode = S_OK;
  367. if (pformatetcIn->cfFormat != m_cfFormat)
  368. {
  369. scode = DV_E_CLIPFORMAT;
  370. }
  371. else if (pmedium->tymed != TYMED_HGLOBAL
  372. && pmedium->tymed != TYMED_ISTREAM)
  373. {
  374. scode = DV_E_TYMED;
  375. }
  376. else if (pmedium->hGlobal == NULL)
  377. {
  378. scode = E_INVALIDARG;
  379. }
  380. else if (IsBlank())
  381. {
  382. scode = OLE_E_BLANK;
  383. }
  384. else // actually get the data now
  385. {
  386. if (pmedium->tymed == TYMED_HGLOBAL)
  387. {
  388. // check the size of the given pmedium and then
  389. // copy the data into it
  390. LPVOID lpsrc = NULL;
  391. LPVOID lpdst = NULL;
  392. DWORD dwSizeDst;
  393. scode = E_OUTOFMEMORY;
  394. if (0 == (dwSizeDst = (DWORD) GlobalSize(pmedium->hGlobal)))
  395. {
  396. goto errRtn;
  397. }
  398. // not enough room to copy
  399. if (dwSizeDst < m_dwSize)
  400. {
  401. goto errRtn;
  402. }
  403. if (NULL == (lpdst = (LPVOID) GlobalLock(pmedium->hGlobal)))
  404. {
  405. goto errRtn;
  406. }
  407. if (NULL == (lpsrc = (LPVOID) GlobalLock(M_HPRES())))
  408. {
  409. goto errMem;
  410. }
  411. _xmemcpy(lpdst, lpsrc, m_dwSize);
  412. scode = S_OK;
  413. errMem:
  414. if (lpdst)
  415. {
  416. GlobalUnlock(pmedium->hGlobal);
  417. }
  418. if (lpsrc)
  419. {
  420. GlobalUnlock(m_hPres);
  421. }
  422. }
  423. else
  424. {
  425. Assert(pmedium->tymed == TYMED_ISTREAM);
  426. if (m_cfFormat == CF_DIB)
  427. {
  428. return UtHDIBToDIBFileStm(M_HPRES(),
  429. m_dwSize,pmedium->pstm);
  430. }
  431. else
  432. {
  433. return UtHGLOBALtoStm(M_HPRES(),
  434. m_dwSize, pmedium->pstm);
  435. }
  436. }
  437. }
  438. errRtn:
  439. return ResultFromScode(scode);
  440. }
  441. //+-------------------------------------------------------------------------
  442. //
  443. // Member: CGenObject::SetDataWDO
  444. //
  445. // Synopsis: Takes the given presentation data and stores it
  446. //
  447. // Effects:
  448. //
  449. // Arguments: [pformatetc] -- the format of the data
  450. // [pmedium] -- the new presentation data
  451. // [fRelease] -- if TRUE, then we keep the data, else
  452. // we keep a copy
  453. // [pDataObj] -- pointer to the IDataObject, may be NULL
  454. //
  455. // Requires:
  456. //
  457. // Returns: HRESULT
  458. //
  459. // Signals:
  460. //
  461. // Modifies:
  462. //
  463. // Derivation: IOlePresObj
  464. //
  465. // Algorithm:
  466. //
  467. // History: dd-mmm-yy Author Comment
  468. // 23-Nov-93 alexgo 32bit port
  469. //
  470. // Notes:
  471. //
  472. //--------------------------------------------------------------------------
  473. STDMETHODIMP CGenObject::SetDataWDO
  474. (LPFORMATETC pformatetc, LPSTGMEDIUM pmedium, BOOL fRelease, IDataObject * pDataObj)
  475. {
  476. VDATEHEAP();
  477. HRESULT error;
  478. BOOL fTakeData = FALSE;
  479. if (pformatetc->cfFormat != m_cfFormat)
  480. {
  481. if (m_cfFormat == CF_DIB && pformatetc->cfFormat == CF_BITMAP)
  482. {
  483. return SetBitmapData(pformatetc, pmedium, fRelease, pDataObj);
  484. }
  485. else
  486. {
  487. return ResultFromScode(DV_E_CLIPFORMAT);
  488. }
  489. }
  490. if (pmedium->tymed != TYMED_HGLOBAL)
  491. {
  492. return ResultFromScode(DV_E_TYMED);
  493. }
  494. if ((pmedium->pUnkForRelease == NULL) && fRelease)
  495. {
  496. // we can take the ownership of the data
  497. fTakeData = TRUE;
  498. }
  499. // ChangeData will keep the data if fRelease is TRUE, else it copies
  500. error = ChangeData (pmedium->hGlobal, fTakeData);
  501. if (fTakeData)
  502. {
  503. pmedium->tymed = TYMED_NULL;
  504. }
  505. else if (fRelease)
  506. {
  507. ReleaseStgMedium(pmedium);
  508. }
  509. return error;
  510. }
  511. //+-------------------------------------------------------------------------
  512. //
  513. // Member: CGenObject::ChangeData (private)
  514. //
  515. // Synopsis: Replaces the stored presentation
  516. //
  517. // Effects:
  518. //
  519. // Arguments: [hNewData] -- the new presentation
  520. // [fDelete] -- if TRUE, then free hNewData
  521. //
  522. // Requires:
  523. //
  524. // Returns: HRESULT
  525. //
  526. // Signals:
  527. //
  528. // Modifies:
  529. //
  530. // Derivation:
  531. //
  532. // Algorithm:
  533. //
  534. // History: dd-mmm-yy Author Comment
  535. // 23-Nov-93 alexgo 32bit port
  536. // Notes:
  537. //
  538. // If the routine fails then the object will be left with it's old data.
  539. // In case of failure if fDelete is TRUE, then hNewData will be freed.
  540. //
  541. //--------------------------------------------------------------------------
  542. #pragma SEG(CGenObject_ChangeData)
  543. INTERNAL CGenObject::ChangeData (HANDLE hNewData, BOOL fDelete)
  544. {
  545. VDATEHEAP();
  546. HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
  547. if (!hNewData)
  548. {
  549. return ResultFromScode(OLE_E_BLANK);
  550. }
  551. if (!fDelete)
  552. {
  553. if (NULL == (hNewData = UtDupGlobal(hNewData, GMEM_MOVEABLE)))
  554. {
  555. return hresult;
  556. }
  557. }
  558. else
  559. {
  560. HANDLE hTmp;
  561. // change the ownership to yourself
  562. hTmp = GlobalReAlloc (hNewData, 0L, GMEM_MODIFY|GMEM_SHARE);
  563. if (NULL == hTmp)
  564. {
  565. if (NULL == (hTmp = UtDupGlobal(hNewData, GMEM_MOVEABLE)))
  566. {
  567. goto errRtn;
  568. }
  569. // Realloc failed but copying succeeded. Since this is fDelete
  570. // case, free the source global handle.
  571. LEVERIFY( NULL == GlobalFree(hNewData));
  572. }
  573. hNewData = hTmp;
  574. }
  575. #ifndef _MAC
  576. // CF_DIB format specific code. Get the it's extents
  577. if (m_cfFormat == CF_DIB)
  578. {
  579. LPBITMAPINFOHEADER lpBi;
  580. if (NULL == (lpBi = (LPBITMAPINFOHEADER) GlobalLock (hNewData)))
  581. {
  582. goto errRtn;
  583. }
  584. UtGetDibExtents (lpBi, &m_lWidth, &m_lHeight);
  585. GlobalUnlock (hNewData);
  586. }
  587. #endif
  588. // free the old presentation
  589. if (m_hPres)
  590. {
  591. LEVERIFY( NULL == GlobalFree (m_hPres));
  592. }
  593. // store the new presentation in m_hPres
  594. m_dwSize = (DWORD) GlobalSize (m_hPres = hNewData);
  595. return NOERROR;
  596. errRtn:
  597. if (hNewData && fDelete)
  598. {
  599. LEVERIFY( NULL == GlobalFree (hNewData));
  600. }
  601. return hresult;
  602. }
  603. //+-------------------------------------------------------------------------
  604. //
  605. // Member: CGenObject::Draw
  606. //
  607. // Synopsis: Calls DibDraw to draw the stored bitmap presentation
  608. //
  609. // Effects:
  610. //
  611. // Arguments: [pvAspect] -- drawing aspect
  612. // [hicTargetDev] -- the target device
  613. // [hdcDraw] -- the device context
  614. // [lprcBounds] -- drawing boundary
  615. // [lprcWBounds] -- boundary rectangle for metafiles
  616. // [pfnContinue] -- callback function to periodically call
  617. // for long drawing operations
  618. // [dwContinue] -- argument to be passed to pfnContinue
  619. //
  620. // Requires:
  621. //
  622. // Returns: HRESULT
  623. //
  624. // Signals:
  625. //
  626. // Modifies:
  627. //
  628. // Derivation: IOlePresObj
  629. //
  630. // Algorithm:
  631. //
  632. // History: dd-mmm-yy Author Comment
  633. // 23-Nov-93 alexgo 32bit port
  634. //
  635. // Notes:
  636. //
  637. //--------------------------------------------------------------------------
  638. #pragma SEG(CGenObject_Draw)
  639. STDMETHODIMP CGenObject::Draw(void * /* UNUSED pvAspect */,
  640. HDC /* UNUSED hicTargetDev */,
  641. HDC hdcDraw,
  642. LPCRECTL lprcBounds,
  643. LPCRECTL /* UNUSED lprcWBounds */,
  644. BOOL (CALLBACK * /*UNUSED pfcCont*/)(ULONG_PTR),
  645. ULONG_PTR /* UNUSED dwContinue */)
  646. {
  647. VDATEHEAP();
  648. #ifndef _MAC
  649. if (m_cfFormat == CF_DIB)
  650. {
  651. return DibDraw (M_HPRES(), hdcDraw,lprcBounds);
  652. }
  653. #endif
  654. return ResultFromScode(E_NOTIMPL);
  655. }
  656. //+-------------------------------------------------------------------------
  657. //
  658. // Member: CGenObject::Load
  659. //
  660. // Synopsis: Loads a stored presentation object from the given stream
  661. //
  662. // Effects:
  663. //
  664. // Arguments: [lpstream] -- the stream from which to load
  665. // [fReadHeaderOnly] -- if TRUE, only get header info
  666. // (such as size, width, height, etc)
  667. //
  668. // Requires:
  669. //
  670. // Returns: HRESULT
  671. //
  672. // Signals:
  673. //
  674. // Modifies:
  675. //
  676. // Derivation: IOlePresObj
  677. //
  678. // Algorithm:
  679. //
  680. // History: dd-mmm-yy Author Comment
  681. // 23-Nov-93 alexgo 32bit port
  682. //
  683. // Notes:
  684. //
  685. //--------------------------------------------------------------------------
  686. STDMETHODIMP CGenObject::Load(LPSTREAM lpstream, BOOL fReadHeaderOnly)
  687. {
  688. VDATEHEAP();
  689. DWORD dwBuf[4];
  690. HRESULT error;
  691. /* read dwCompression, width, height, size of data */
  692. error = StRead(lpstream, dwBuf, 4 * sizeof(DWORD));
  693. if (error)
  694. {
  695. return error;
  696. }
  697. // we don't allow for compression yet
  698. AssertSz (dwBuf[0] == 0, "Picture compression factor is non-zero");
  699. m_lWidth = (LONG) dwBuf[1];
  700. m_lHeight = (LONG) dwBuf[2];
  701. m_dwSize = dwBuf[3];
  702. if (!m_dwSize || fReadHeaderOnly)
  703. {
  704. return NOERROR;
  705. }
  706. return UtGetHGLOBALFromStm(lpstream, m_dwSize, &m_hPres);
  707. }
  708. //+-------------------------------------------------------------------------
  709. //
  710. // Member: CGenObject::Save
  711. //
  712. // Synopsis: Stores presentation data to the given stream
  713. //
  714. // Effects:
  715. //
  716. // Arguments: [lpstream] -- where to store the data
  717. //
  718. // Requires:
  719. //
  720. // Returns: HRESULT
  721. //
  722. // Signals:
  723. //
  724. // Modifies:
  725. //
  726. // Derivation: IOlePresObj
  727. //
  728. // Algorithm:
  729. //
  730. // History: dd-mmm-yy Author Comment
  731. // 23-Nov-93 alexgo 32bit port
  732. //
  733. // Notes:
  734. //
  735. //--------------------------------------------------------------------------
  736. STDMETHODIMP CGenObject::Save(LPSTREAM lpstream)
  737. {
  738. VDATEHEAP();
  739. HRESULT error;
  740. DWORD dwBuf[4];
  741. /* write dwCompression, width, height, size of data */
  742. dwBuf[0] = 0L;
  743. dwBuf[1] = (DWORD) m_lWidth;
  744. dwBuf[2] = (DWORD) m_lHeight;
  745. dwBuf[3] = m_dwSize;
  746. error = StWrite(lpstream, dwBuf, 4*sizeof(DWORD));
  747. if (error)
  748. {
  749. return error;
  750. }
  751. // if we're blank or don't have any presentation data, then
  752. // nothing to else to save.
  753. if (IsBlank() || m_hPres == NULL)
  754. {
  755. StSetSize(lpstream, 0, TRUE);
  756. return NOERROR;
  757. }
  758. return UtHGLOBALtoStm(m_hPres, m_dwSize, lpstream);
  759. }
  760. //+-------------------------------------------------------------------------
  761. //
  762. // Member: CGenObject::GetExtent
  763. //
  764. // Synopsis: retrieves the size (width/height) of the presentation bitmap
  765. //
  766. // Effects:
  767. //
  768. // Arguments: [dwDrawAspect] -- the drawing aspect the caller is
  769. // interested in
  770. // [lpsizel] -- where to put the size extents
  771. //
  772. // Requires:
  773. //
  774. // Returns: HRESULT (NOERROR, DV_E_DVASPECT, OLE_E_BLANK)
  775. //
  776. // Signals:
  777. //
  778. // Modifies:
  779. //
  780. // Derivation: IOlePresObj
  781. //
  782. // Algorithm: retrieves the stored dimensions
  783. //
  784. // History: dd-mmm-yy Author Comment
  785. // 23-Nov-93 alexgo 32bit port
  786. //
  787. // Notes:
  788. //
  789. //--------------------------------------------------------------------------
  790. #pragma SEG(CGenObject_GetExtent)
  791. STDMETHODIMP CGenObject::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
  792. {
  793. VDATEHEAP();
  794. // aspects must match
  795. if (!(dwDrawAspect & m_dwAspect))
  796. {
  797. return ResultFromScode(DV_E_DVASPECT);
  798. }
  799. if (IsBlank())
  800. {
  801. return ResultFromScode(OLE_E_BLANK);
  802. }
  803. lpsizel->cx = m_lWidth;
  804. lpsizel->cy = m_lHeight;
  805. if (lpsizel->cx || lpsizel->cy)
  806. {
  807. return NOERROR;
  808. }
  809. else
  810. {
  811. return ResultFromScode(OLE_E_BLANK);
  812. }
  813. }
  814. //+-------------------------------------------------------------------------
  815. //
  816. // Member: CGenObject::GetColorSet
  817. //
  818. // Synopsis: Retrieves the pallette associated with the bitmap
  819. //
  820. // Effects:
  821. //
  822. // Arguments: [pvAspect] -- the drawing aspect (unused)
  823. // [hicTargetDev] -- the target device (unused)
  824. // [ppColorSet] -- where to put the new palette
  825. //
  826. // Requires:
  827. //
  828. // Returns: HRESULT
  829. //
  830. // Signals:
  831. //
  832. // Modifies:
  833. //
  834. // Derivation: IOlePresObj
  835. //
  836. // Algorithm: Allocates a new pallette and copies the bitmap
  837. // palette into it.
  838. //
  839. // History: dd-mmm-yy Author Comment
  840. // 23-Nov-93 alexgo 32bit port, fixed bad memory bugs
  841. //
  842. // Notes:
  843. //
  844. //--------------------------------------------------------------------------
  845. STDMETHODIMP CGenObject::GetColorSet(LPVOID /* UNUSED pvAspect */,
  846. HDC /* UNUSED hicTargetDev */,
  847. LPLOGPALETTE * ppColorSet)
  848. {
  849. VDATEHEAP();
  850. HRESULT hresult = ResultFromScode(S_FALSE);
  851. if (m_cfFormat == CF_DIB)
  852. {
  853. if (IsBlank())
  854. {
  855. return ResultFromScode(OLE_E_BLANK);
  856. }
  857. LPBITMAPINFOHEADER lpbmih;
  858. LPLOGPALETTE lpLogpal;
  859. WORD wPalSize;
  860. if (NULL == (lpbmih = (LPBITMAPINFOHEADER) GlobalLock (M_HPRES())))
  861. {
  862. return ResultFromScode(E_OUTOFMEMORY);
  863. }
  864. // A bitmap with more than 8 bpp cannot have a palette at all,
  865. // so we just return S_FALSE
  866. if (lpbmih->biBitCount > 8)
  867. {
  868. goto errRtn;
  869. }
  870. // Note: the return from UtPaletteSize can overflow the WORD
  871. // wPalSize, but utPaletteSize asserts against this
  872. if (0 == (wPalSize = (WORD) UtPaletteSize(lpbmih)))
  873. {
  874. goto errRtn;
  875. }
  876. lpLogpal = (LPLOGPALETTE)PubMemAlloc(wPalSize +
  877. 2*sizeof(WORD));
  878. if (lpLogpal == NULL)
  879. {
  880. hresult = ResultFromScode(E_OUTOFMEMORY);
  881. goto errRtn;
  882. }
  883. DibFillPaletteEntries((BYTE FAR *)++lpbmih, wPalSize, lpLogpal);
  884. *ppColorSet = lpLogpal;
  885. hresult = NOERROR;
  886. errRtn:
  887. GlobalUnlock(m_hPres);
  888. return hresult;
  889. }
  890. return hresult;
  891. }
  892. //+-------------------------------------------------------------------------
  893. //
  894. // Member: CGenObject::IsBlank
  895. //
  896. // Synopsis: returns TRUE if the presentation is blank
  897. //
  898. // Effects:
  899. //
  900. // Arguments: void
  901. //
  902. // Requires:
  903. //
  904. // Returns: TRUE/FALSE
  905. //
  906. // Signals:
  907. //
  908. // Modifies:
  909. //
  910. // Derivation: IOlePresObject
  911. //
  912. // Algorithm:
  913. //
  914. // History: dd-mmm-yy Author Comment
  915. // 23-Nov-93 alexgo 32bit port
  916. //
  917. // Notes:
  918. //
  919. //--------------------------------------------------------------------------
  920. #pragma SEG(CGenObject_IsBlank)
  921. STDMETHODIMP_(BOOL) CGenObject::IsBlank(void)
  922. {
  923. VDATEHEAP();
  924. return (m_dwSize ? FALSE : TRUE);
  925. }
  926. //+-------------------------------------------------------------------------
  927. //
  928. // Member: CGenObject::LoadHPRES (private)
  929. //
  930. // Synopsis: Loads the presentation from the internal cache's stream
  931. //
  932. // Effects:
  933. //
  934. // Arguments: void
  935. //
  936. // Requires:
  937. //
  938. // Returns: HANDLE (to the presentation)
  939. //
  940. // Signals:
  941. //
  942. // Modifies:
  943. //
  944. // Derivation:
  945. //
  946. // Algorithm:
  947. //
  948. // History: dd-mmm-yy Author Comment
  949. // 23-Nov-93 alexgo 32bit port
  950. //
  951. // Notes:
  952. //
  953. //--------------------------------------------------------------------------
  954. INTERNAL_(HANDLE) CGenObject::LoadHPRES()
  955. {
  956. VDATEHEAP();
  957. LPSTREAM pstm;
  958. pstm = m_pCacheNode->GetStm(TRUE /*fSeekToPresBits*/, STGM_READ);
  959. if (pstm)
  960. {
  961. LEVERIFY( SUCCEEDED(Load(pstm)));
  962. pstm->Release();
  963. }
  964. return m_hPres;
  965. }
  966. //+-------------------------------------------------------------------------
  967. //
  968. // Member: CGenObject::DiscardHPRES
  969. //
  970. // Synopsis: Deletes the object's presentation
  971. //
  972. // Effects:
  973. //
  974. // Arguments: void
  975. //
  976. // Requires:
  977. //
  978. // Returns: void
  979. //
  980. // Signals:
  981. //
  982. // Modifies:
  983. //
  984. // Derivation: IOlePresObj
  985. //
  986. // Algorithm:
  987. //
  988. // History: dd-mmm-yy Author Comment
  989. // 23-Nov-93 alexgo 32bit port
  990. //
  991. // Notes:
  992. //
  993. //--------------------------------------------------------------------------
  994. STDMETHODIMP_(void) CGenObject::DiscardHPRES(void)
  995. {
  996. VDATEHEAP();
  997. if (m_hPres)
  998. {
  999. LEVERIFY( NULL == GlobalFree(m_hPres));
  1000. m_hPres = NULL;
  1001. }
  1002. }
  1003. //+-------------------------------------------------------------------------
  1004. //
  1005. // Member: CGenObject::GetCopyOfHPRES (private)
  1006. //
  1007. // Synopsis: Returns a handle to a copy of the presentation data
  1008. //
  1009. // Effects:
  1010. //
  1011. // Arguments: void
  1012. //
  1013. // Requires:
  1014. //
  1015. // Returns: HANDLE
  1016. //
  1017. // Signals:
  1018. //
  1019. // Modifies:
  1020. //
  1021. // Derivation:
  1022. //
  1023. // Algorithm: makes a copy of m_hPres if not NULL, otherwise loads it
  1024. // from the stream (without setting m_hPres)
  1025. //
  1026. // History: dd-mmm-yy Author Comment
  1027. // 23-Nov-93 alexgo 32bit port
  1028. //
  1029. // Notes:
  1030. //
  1031. //--------------------------------------------------------------------------
  1032. INTERNAL_(HANDLE) CGenObject::GetCopyOfHPRES()
  1033. {
  1034. VDATEHEAP();
  1035. HANDLE hPres;
  1036. // Make a copy if the presentation data is already loaded
  1037. if (m_hPres)
  1038. {
  1039. return(UtDupGlobal(m_hPres, GMEM_MOVEABLE));
  1040. }
  1041. // Load the presentation data now and return the same handle.
  1042. // No need to copy the data. If the caller wants the m_hPres to be
  1043. // set he would call LoadHPRES() directly.
  1044. hPres = LoadHPRES();
  1045. m_hPres = NULL;
  1046. return hPres;
  1047. }
  1048. //+-------------------------------------------------------------------------
  1049. //
  1050. // Member: CGenObject::GetBitmapData (private)
  1051. //
  1052. // Synopsis: Gets bitmap data from a dib
  1053. //
  1054. // Effects:
  1055. //
  1056. // Arguments: [pformatetcIn] -- the requested format
  1057. // [pmedium] -- where to put the data
  1058. //
  1059. // Requires:
  1060. //
  1061. // Returns: HRESULT
  1062. //
  1063. // Signals:
  1064. //
  1065. // Modifies:
  1066. //
  1067. // Derivation:
  1068. //
  1069. // Algorithm: checks the parameters, then calls UtConvertDibtoBitmap
  1070. // to get raw bitmap data from the device-independent bitmap
  1071. //
  1072. // History: dd-mmm-yy Author Comment
  1073. // 23-Nov-93 alexgo 32bit port
  1074. //
  1075. // Notes:
  1076. //
  1077. //--------------------------------------------------------------------------
  1078. #ifndef _MAC
  1079. #pragma SEG(CGenObject_GetBitmapData)
  1080. INTERNAL CGenObject::GetBitmapData
  1081. (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
  1082. {
  1083. VDATEHEAP();
  1084. SCODE sc = E_OUTOFMEMORY;
  1085. if (0 == (pformatetcIn->tymed & TYMED_GDI))
  1086. {
  1087. sc = DV_E_TYMED;
  1088. }
  1089. pmedium->pUnkForRelease = NULL;
  1090. pmedium->hGlobal = UtConvertDibToBitmap(M_HPRES());
  1091. // if pmedium->hGlobal is not NULL, then UtConvertDibToBitmap succeeded
  1092. // so the tymed needs to be set appropriately, and the return value
  1093. // changed to S_OK.
  1094. if (NULL != pmedium->hGlobal)
  1095. {
  1096. pmedium->tymed = TYMED_GDI;
  1097. sc = S_OK;
  1098. }
  1099. else
  1100. {
  1101. pmedium->tymed = TYMED_NULL;
  1102. }
  1103. return ResultFromScode(sc);
  1104. }
  1105. //+-------------------------------------------------------------------------
  1106. //
  1107. // Member: CGenObject::SetBitmapData (private)
  1108. //
  1109. // Synopsis: Converts bitmap data to a dib and stores it in [this]
  1110. // presenatation object
  1111. //
  1112. // Effects:
  1113. //
  1114. // Arguments: [pformatetc] -- the format of the data
  1115. // [pmedium] -- the data
  1116. // [fRelease] -- if TRUE, then pmedium will be free'd
  1117. //
  1118. // Returns: HRESULT
  1119. //
  1120. // Algorithm: calls UtConvertBitmapToDib and stores the result
  1121. //
  1122. // History: dd-mmm-yy Author Comment
  1123. // 07-Jul-94 DavePl Added CF_PALETTE support
  1124. //
  1125. // Notes: if [fRelease] == TRUE, then [pmedium] is released, even
  1126. // if a dib could not be built
  1127. //
  1128. //--------------------------------------------------------------------------
  1129. INTERNAL CGenObject::SetBitmapData(LPFORMATETC pformatetc,
  1130. STGMEDIUM * pmedium,
  1131. BOOL fRelease,
  1132. IDataObject * pDataObject)
  1133. {
  1134. VDATEHEAP();
  1135. HGLOBAL hDib;
  1136. if (pmedium->tymed != TYMED_GDI)
  1137. {
  1138. return ResultFromScode(DV_E_TYMED);
  1139. }
  1140. // If we have a data object and if we can get the palette from it,
  1141. // use that to do the bitmap -> dib conversion. Otherwise, just
  1142. // pass a NULL palette along and the default one will be used
  1143. STGMEDIUM stgmPalette;
  1144. FORMATETC fetcPalette = {
  1145. CF_PALETTE,
  1146. NULL,
  1147. pformatetc->dwAspect,
  1148. DEF_LINDEX,
  1149. TYMED_GDI
  1150. };
  1151. if (pDataObject && SUCCEEDED(pDataObject->GetData(&fetcPalette, &stgmPalette)))
  1152. {
  1153. hDib = UtConvertBitmapToDib((HBITMAP)pmedium->hGlobal,
  1154. (HPALETTE) stgmPalette.hGlobal);
  1155. ReleaseStgMedium(&stgmPalette);
  1156. }
  1157. else
  1158. {
  1159. hDib = UtConvertBitmapToDib((HBITMAP)pmedium->hGlobal, NULL);
  1160. }
  1161. if (fRelease)
  1162. {
  1163. ReleaseStgMedium(pmedium);
  1164. }
  1165. if (!hDib)
  1166. {
  1167. return ResultFromScode(E_OUTOFMEMORY);
  1168. }
  1169. FORMATETC foretcTmp = *pformatetc;
  1170. STGMEDIUM pmedTmp = *pmedium;
  1171. foretcTmp.cfFormat = CF_DIB;
  1172. foretcTmp.tymed = TYMED_HGLOBAL;
  1173. pmedTmp.pUnkForRelease = NULL;
  1174. pmedTmp.tymed = TYMED_HGLOBAL;
  1175. pmedTmp.hGlobal = hDib;
  1176. // Now that we have converted the bitmap data to DIB,
  1177. // SetData _back_ on ourselves again with the DIB info
  1178. return SetDataWDO(&foretcTmp, &pmedTmp, TRUE, NULL);
  1179. }
  1180. //+-------------------------------------------------------------------------
  1181. //
  1182. // Member: CGenObject::Dump, public (_DEBUG only)
  1183. //
  1184. // Synopsis: return a string containing the contents of the data members
  1185. //
  1186. // Effects:
  1187. //
  1188. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  1189. // [ulFlag] - flag determining prefix of all newlines of the
  1190. // out character array (default is 0 - no prefix)
  1191. // [nIndentLevel] - will add a indent prefix after the other prefix
  1192. // for ALL newlines (including those with no prefix)
  1193. //
  1194. // Requires:
  1195. //
  1196. // Returns: HRESULT
  1197. //
  1198. // Signals:
  1199. //
  1200. // Modifies: [ppszDump] - argument
  1201. //
  1202. // Derivation:
  1203. //
  1204. // Algorithm: use dbgstream to create a string containing information on the
  1205. // content of data structures
  1206. //
  1207. // History: dd-mmm-yy Author Comment
  1208. // 01-Feb-95 t-ScottH author
  1209. //
  1210. // Notes:
  1211. //
  1212. //--------------------------------------------------------------------------
  1213. #ifdef _DEBUG
  1214. HRESULT CGenObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  1215. {
  1216. int i;
  1217. char *pszPrefix;
  1218. char *pszDVASPECT;
  1219. char *pszCLIPFORMAT;
  1220. dbgstream dstrPrefix;
  1221. dbgstream dstrDump(500);
  1222. // determine prefix of newlines
  1223. if ( ulFlag & DEB_VERBOSE )
  1224. {
  1225. dstrPrefix << this << " _VB ";
  1226. }
  1227. // determine indentation prefix for all newlines
  1228. for (i = 0; i < nIndentLevel; i++)
  1229. {
  1230. dstrPrefix << DUMPTAB;
  1231. }
  1232. pszPrefix = dstrPrefix.str();
  1233. // put data members in stream
  1234. dstrDump << pszPrefix << "No. of References = " << m_ulRefs << endl;
  1235. pszDVASPECT = DumpDVASPECTFlags(m_dwAspect);
  1236. dstrDump << pszPrefix << "Aspect flags = " << pszDVASPECT << endl;
  1237. CoTaskMemFree(pszDVASPECT);
  1238. dstrDump << pszPrefix << "Size = " << m_dwSize << endl;
  1239. dstrDump << pszPrefix << "Width = " << m_lWidth << endl;
  1240. dstrDump << pszPrefix << "Height = " << m_lHeight << endl;
  1241. dstrDump << pszPrefix << "Presentation Handle = " << m_hPres << endl;
  1242. pszCLIPFORMAT = DumpCLIPFORMAT(m_cfFormat);
  1243. dstrDump << pszPrefix << "Clip Format = " << pszCLIPFORMAT << endl;
  1244. CoTaskMemFree(pszCLIPFORMAT);
  1245. dstrDump << pszPrefix << "pCacheNode = " << m_pCacheNode << endl;
  1246. // cleanup and provide pointer to character array
  1247. *ppszDump = dstrDump.str();
  1248. if (*ppszDump == NULL)
  1249. {
  1250. *ppszDump = UtDupStringA(szDumpErrorMessage);
  1251. }
  1252. CoTaskMemFree(pszPrefix);
  1253. return NOERROR;
  1254. }
  1255. #endif // _DEBUG
  1256. //+-------------------------------------------------------------------------
  1257. //
  1258. // Function: DumpCGenObject, public (_DEBUG only)
  1259. //
  1260. // Synopsis: calls the CGenObject::Dump method, takes care of errors and
  1261. // returns the zero terminated string
  1262. //
  1263. // Effects:
  1264. //
  1265. // Arguments: [pGO] - pointer to CGenObject
  1266. // [ulFlag] - flag determining prefix of all newlines of the
  1267. // out character array (default is 0 - no prefix)
  1268. // [nIndentLevel] - will add a indent prefix after the other prefix
  1269. // for ALL newlines (including those with no prefix)
  1270. //
  1271. // Requires:
  1272. //
  1273. // Returns: character array of structure dump or error (null terminated)
  1274. //
  1275. // Signals:
  1276. //
  1277. // Modifies:
  1278. //
  1279. // Algorithm:
  1280. //
  1281. // History: dd-mmm-yy Author Comment
  1282. // 01-Feb-95 t-ScottH author
  1283. //
  1284. // Notes:
  1285. //
  1286. //--------------------------------------------------------------------------
  1287. #ifdef _DEBUG
  1288. char *DumpCGenObject(CGenObject *pGO, ULONG ulFlag, int nIndentLevel)
  1289. {
  1290. HRESULT hresult;
  1291. char *pszDump;
  1292. if (pGO == NULL)
  1293. {
  1294. return UtDupStringA(szDumpBadPtr);
  1295. }
  1296. hresult = pGO->Dump(&pszDump, ulFlag, nIndentLevel);
  1297. if (hresult != NOERROR)
  1298. {
  1299. CoTaskMemFree(pszDump);
  1300. return DumpHRESULT(hresult);
  1301. }
  1302. return pszDump;
  1303. }
  1304. #endif // _DEBUG
  1305. //+-------------------------------------------------------------------------
  1306. //
  1307. // Function: DibDraw
  1308. //
  1309. // Synopsis: Draws a device independent bitmap
  1310. //
  1311. // Effects:
  1312. //
  1313. // Arguments: [hDib] -- the bitmap
  1314. // [hdc] -- the device context
  1315. // [lprc] -- the bounding rectangle
  1316. //
  1317. // Requires:
  1318. //
  1319. // Returns: HRESULT
  1320. //
  1321. // Signals:
  1322. //
  1323. // Modifies:
  1324. //
  1325. // Algorithm: Sets the palette to the palette in the dib, sizes and draws
  1326. // the dib to the bounding rectangle. The original palette
  1327. // is then restored
  1328. //
  1329. // History: dd-mmm-yy Author Comment
  1330. // 23-Nov-93 alexgo 32bit port
  1331. // 07-Dec-93 alexgo merged RC9 16bit changes. The
  1332. // error-handling code used to reset the
  1333. // old palette and then RealizePalette.
  1334. // The call to RealizePalette was removed
  1335. // 11-May-94 davepl Added support for BITMAPCOREINFO dibs
  1336. // 17-Jul-94 davepl Added 12, 32 bpp support
  1337. //
  1338. // Notes:
  1339. //
  1340. //--------------------------------------------------------------------------
  1341. INTERNAL DibDraw (HANDLE hDib, HDC hdc, LPCRECTL lprc)
  1342. {
  1343. VDATEHEAP();
  1344. HRESULT error = ResultFromScode(E_DRAW);
  1345. BYTE FAR * lpDib;
  1346. HANDLE hPalette = NULL;
  1347. HPALETTE hLogPalette = NULL,
  1348. hOldPalette = NULL;
  1349. LPLOGPALETTE lpLogPalette;
  1350. WORD wPalSize;
  1351. DWORD cbHeaderSize;
  1352. BOOL fNeedPalette = FALSE;
  1353. WORD iHeight;
  1354. WORD iWidth;
  1355. int iOffBits;
  1356. BITMAPINFO * pbi = NULL;
  1357. BOOL fWeAllocd = FALSE;
  1358. if (NULL == hDib)
  1359. {
  1360. return ResultFromScode(OLE_E_BLANK);
  1361. }
  1362. Assert(lprc);
  1363. if (NULL == (lpDib = (BYTE FAR *) GlobalLock (hDib)))
  1364. {
  1365. return ResultFromScode(E_OUTOFMEMORY);
  1366. }
  1367. // The bitmap header could be BITMAPINFOHEADER or
  1368. // BITMAPCOREHEADER. Set our cbHeaderSize flag
  1369. // based on the header type. We can then calculate the
  1370. // palette size and the offset to the raw data bits. If
  1371. // we don't recognize either one of the structures here,
  1372. // we bail; the data is likely corrupt.
  1373. // Just a thought here: could be dangerous if the struct
  1374. // is not LONG aligned and this is run on an Alpha. As far
  1375. // as I've been able to find out, they always are long
  1376. // aligned
  1377. cbHeaderSize = *((ULONG *) lpDib);
  1378. LEWARN( cbHeaderSize > 500, "Struct size > 500, likely invalid!");
  1379. if (cbHeaderSize == sizeof(BITMAPINFOHEADER))
  1380. {
  1381. // Note: this assignment can overflow the WORD wPalSize,
  1382. // but the UtPaletteSize function asserts against this
  1383. wPalSize = (WORD) UtPaletteSize((LPBITMAPINFOHEADER)lpDib);
  1384. iWidth = (WORD) ((LPBITMAPINFOHEADER)lpDib)->biWidth;
  1385. iHeight = (WORD) ((LPBITMAPINFOHEADER)lpDib)->biHeight;
  1386. pbi = (LPBITMAPINFO) lpDib;
  1387. iOffBits = wPalSize + sizeof(BITMAPINFOHEADER);
  1388. }
  1389. else if (cbHeaderSize == sizeof(BITMAPCOREHEADER))
  1390. {
  1391. // Since the clipboard itself does not support COREINFO
  1392. // bitmaps, we will not support them in the presentation
  1393. // cache. When (if) windows adds complete support for
  1394. // these, the code is here and ready.
  1395. #ifndef CACHE_SUPPORT_COREINFO
  1396. error = DV_E_TYMED;
  1397. goto errRtn;
  1398. #else
  1399. // Special case 32 bpp bitmaps
  1400. // If we have a palette, we need to calculate its size and
  1401. // allocate enough memory for the palette entries (remember
  1402. // we get one entry for free with the BITMAPINFO struct, so
  1403. // less one). If we don't have a palette, we only need to
  1404. // allocate enough for the BITMAPINFO struct itself.
  1405. // Bitmaps with more than 64K colors lack a palette; they
  1406. // use direct RGB entries in the pixels
  1407. if ((((LPBITMAPCOREHEADER)lpDib)->bcBitCount) > 16)
  1408. {
  1409. wPalSize = 0;
  1410. pbi = (BITMAPINFO *) PrivMemAlloc(sizeof(BITMAPINFO));
  1411. }
  1412. else
  1413. {
  1414. wPalSize = sizeof(RGBQUAD) *
  1415. (1 << (((LPBITMAPCOREHEADER)lpDib)->bcBitCount));
  1416. pbi = (BITMAPINFO *) PrivMemAlloc(sizeof(BITMAPINFO)
  1417. + wPalSize - sizeof(RGBQUAD));
  1418. }
  1419. if (NULL == pbi)
  1420. {
  1421. return ResultFromScode(E_OUTOFMEMORY);
  1422. }
  1423. else
  1424. {
  1425. fWeAllocd = TRUE;
  1426. }
  1427. // Grab the width and height
  1428. iWidth = ((LPBITMAPCOREHEADER)lpDib)->bcWidth;
  1429. iHeight = ((LPBITMAPCOREHEADER)lpDib)->bcHeight;
  1430. // Clear all the fields. Don't worry about color table, as if
  1431. // it exists we will set the entries explicitly.
  1432. memset(pbi, 0, sizeof(BITMAPINFOHEADER));
  1433. // Transfer what fields we do have from the COREINFO
  1434. pbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1435. pbi->bmiHeader.biWidth = iWidth;
  1436. pbi->bmiHeader.biHeight = iHeight;
  1437. pbi->bmiHeader.biPlanes = 1;
  1438. pbi->bmiHeader.biBitCount = ((LPBITMAPCOREHEADER)lpDib)->bcBitCount;
  1439. // Set up the color palette, if required.
  1440. // Note that we must translate from RGBTRIPLE entries to
  1441. // RGBQUAD.
  1442. for (WORD c = 0; c < wPalSize / sizeof(RGBQUAD); c++)
  1443. {
  1444. pbi->bmiColors[c].rgbRed = ((BITMAPCOREINFO *)lpDib)->bmciColors[c].rgbtRed;
  1445. pbi->bmiColors[c].rgbBlue = ((BITMAPCOREINFO *)lpDib)->bmciColors[c].rgbtBlue;
  1446. pbi->bmiColors[c].rgbGreen = ((BITMAPCOREINFO *)lpDib)->bmciColors[c].rgbtGreen;
  1447. pbi->bmiColors[c].rgbReserved = 0;
  1448. }
  1449. iOffBits = wPalSize + sizeof(BITMAPCOREHEADER);
  1450. #endif
  1451. }
  1452. else
  1453. {
  1454. error = E_FAIL;
  1455. goto errRtn;
  1456. }
  1457. // if color info exists, create a palette from the data and select it
  1458. // images with < 16 bpp do not have a palette from which we can create
  1459. // a logical palette
  1460. fNeedPalette = ((LPBITMAPINFOHEADER)lpDib)->biBitCount < 16;
  1461. if (wPalSize && fNeedPalette)
  1462. {
  1463. hLogPalette = (HPALETTE)DibMakeLogPalette(lpDib + cbHeaderSize,
  1464. wPalSize,
  1465. &lpLogPalette);
  1466. if (NULL == hLogPalette)
  1467. {
  1468. error = ResultFromScode(E_OUTOFMEMORY);
  1469. goto errRtn;
  1470. }
  1471. if (NULL == (hPalette = CreatePalette (lpLogPalette)))
  1472. {
  1473. goto errRtn;
  1474. }
  1475. // we're done with lpLogPalette now, so unlock it
  1476. // (DibMakeLogPalette got the pointer via a GlobalLock)
  1477. GlobalUnlock(hLogPalette);
  1478. // select as a background palette
  1479. hOldPalette = SelectPalette (hdc, (HPALETTE)hPalette, TRUE);
  1480. if (NULL == hOldPalette)
  1481. {
  1482. goto errRtn;
  1483. }
  1484. LEVERIFY( 0 < RealizePalette(hdc) );
  1485. }
  1486. // size the dib to fit our drawing rectangle and draw it
  1487. if (!StretchDIBits( hdc, // HDC
  1488. lprc->left, // XDest
  1489. lprc->top, // YDest
  1490. lprc->right - lprc->left, // nDestWidth
  1491. lprc->bottom - lprc->top, // nDestHeight
  1492. 0, // XSrc
  1493. 0, // YSrc
  1494. iWidth, // nSrcWidth
  1495. iHeight, // nSrcHeight
  1496. lpDib + iOffBits, // lpBits
  1497. pbi, // lpBitsInfo
  1498. DIB_RGB_COLORS, // iUsage
  1499. SRCCOPY // dwRop
  1500. )
  1501. )
  1502. {
  1503. error = ResultFromScode(E_DRAW);
  1504. }
  1505. else
  1506. {
  1507. error = NOERROR;
  1508. }
  1509. errRtn:
  1510. // We only want to free the header if it is was one which we allocated,
  1511. // which can only happen when we were give a core header type in the
  1512. // first place
  1513. if (fWeAllocd)
  1514. {
  1515. PrivMemFree(pbi);
  1516. }
  1517. if (lpDib)
  1518. {
  1519. GlobalUnlock (hDib);
  1520. }
  1521. // if color palette exists do the following
  1522. if (fNeedPalette)
  1523. {
  1524. hOldPalette = (HPALETTE)(OleIsDcMeta (hdc) ?
  1525. GetStockObject(DEFAULT_PALETTE)
  1526. : (HPALETTE)hOldPalette);
  1527. if (hOldPalette)
  1528. {
  1529. LEVERIFY( SelectPalette (hdc, hOldPalette, TRUE) );
  1530. // Do we need to realize the palette? [Probably not]
  1531. }
  1532. if (hPalette)
  1533. {
  1534. LEVERIFY( DeleteObject (hPalette) );
  1535. }
  1536. if (hLogPalette)
  1537. {
  1538. LEVERIFY( NULL == GlobalFree (hLogPalette) );
  1539. }
  1540. }
  1541. return error;
  1542. }
  1543. //+-------------------------------------------------------------------------
  1544. //
  1545. // Function: DibMakeLogPalette
  1546. //
  1547. // Synopsis: Makes a logical palette from a byte array of color info
  1548. //
  1549. // Effects:
  1550. //
  1551. // Arguments: [lpColorData] -- the color data
  1552. // [wDataSize] -- size of the data
  1553. // [lplpLogPalette] -- where to put a pointer to the
  1554. //
  1555. // Requires:
  1556. //
  1557. // Returns: HANDLE to the logical palette (must be global unlock'ed
  1558. //
  1559. // Signals:
  1560. //
  1561. // Modifies:
  1562. //
  1563. // Algorithm:
  1564. //
  1565. // History: dd-mmm-yy Author Comment
  1566. // 23-Nov-93 alexgo 32bit port
  1567. //
  1568. // Notes: The caller MUST call GlobalUnlock on the returned handle
  1569. // to avoid a memory leak (*lplpLogPalette is the result
  1570. // of a global lock on the handle)
  1571. //
  1572. //--------------------------------------------------------------------------
  1573. #pragma SEG(DibMakeLogPalette)
  1574. INTERNAL_(HANDLE) DibMakeLogPalette(
  1575. BYTE FAR * lpColorData, WORD wDataSize,
  1576. LPLOGPALETTE FAR *lplpLogPalette)
  1577. {
  1578. VDATEHEAP();
  1579. HANDLE hLogPalette=NULL;
  1580. LPLOGPALETTE lpLogPalette;
  1581. DWORD dwLogPalSize = wDataSize + 2 * sizeof(WORD);
  1582. if (NULL == (hLogPalette = GlobalAlloc(GMEM_MOVEABLE, dwLogPalSize)))
  1583. {
  1584. return NULL;
  1585. }
  1586. if (NULL == (lpLogPalette = (LPLOGPALETTE) GlobalLock (hLogPalette)))
  1587. {
  1588. LEVERIFY( NULL == GlobalFree (hLogPalette));
  1589. return NULL;
  1590. }
  1591. *lplpLogPalette = lpLogPalette;
  1592. DibFillPaletteEntries(lpColorData, wDataSize, lpLogPalette);
  1593. return hLogPalette;
  1594. }
  1595. //+-------------------------------------------------------------------------
  1596. //
  1597. // Function: DibFillPaletteEntries
  1598. //
  1599. // Synopsis: Fills the logical palette with the color info in [lpColorData]
  1600. //
  1601. // Effects:
  1602. //
  1603. // Arguments: [lpColorData] -- the color info
  1604. // [wDataSize] -- the size of the color info
  1605. // [lpLogPalette] -- the logical palette
  1606. //
  1607. // Requires:
  1608. //
  1609. // Returns: void
  1610. //
  1611. // Signals:
  1612. //
  1613. // Modifies:
  1614. //
  1615. // Algorithm:
  1616. //
  1617. // History: dd-mmm-yy Author Comment
  1618. // 23-Nov-93 alexgo 32bit port
  1619. //
  1620. // Notes:
  1621. //
  1622. //--------------------------------------------------------------------------
  1623. INTERNAL_(void) DibFillPaletteEntries(
  1624. BYTE FAR * lpColorData, WORD wDataSize, LPLOGPALETTE lpLogPalette)
  1625. {
  1626. VDATEHEAP();
  1627. LPPALETTEENTRY lpPE;
  1628. RGBQUAD FAR * lpQuad;
  1629. lpLogPalette->palVersion = 0x300;
  1630. lpLogPalette->palNumEntries = wDataSize / sizeof(PALETTEENTRY);
  1631. /* now convert RGBQUAD to PALETTEENTRY as we copy color info */
  1632. for (lpQuad = (RGBQUAD far *)lpColorData,
  1633. lpPE = (LPPALETTEENTRY)lpLogPalette->palPalEntry,
  1634. wDataSize /= sizeof(RGBQUAD);
  1635. wDataSize--;
  1636. ++lpQuad,++lpPE)
  1637. {
  1638. lpPE->peFlags = NULL;
  1639. lpPE->peRed = lpQuad->rgbRed;
  1640. lpPE->peBlue = lpQuad->rgbBlue;
  1641. lpPE->peGreen = lpQuad->rgbGreen;
  1642. }
  1643. }
  1644. #endif