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.

1729 lines
44 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1994.
  5. //
  6. // File: emf.cpp
  7. //
  8. // Contents: Implentation of the enhanced metafile picture object
  9. //
  10. // Classes: CEMfObject
  11. //
  12. // History: dd-mmm-yy Author Comment
  13. // 01-Feb-95 t-ScottH added Dump method to EMfObject
  14. // added DumpEMfObject API
  15. // initialize m_pfnContinue in constructor
  16. // 12-May-94 DavePl Created
  17. //
  18. //--------------------------------------------------------------------------
  19. #include <le2int.h>
  20. #include <limits.h>
  21. #include "emf.h"
  22. #ifdef _DEBUG
  23. #include <dbgdump.h>
  24. #endif // _DEBUG
  25. ASSERTDATA
  26. //+-------------------------------------------------------------------------
  27. //
  28. // Function: CEMfObject::M_HPRES
  29. //
  30. // Synopsis: Returns handle to EMF, possibly after demand-loading it
  31. //
  32. // History: dd-mmm-yy Author Comment
  33. // 12-May-94 DavePl Created
  34. //
  35. // Notes:
  36. // The following macro allows for demand loading of the
  37. // presentation bits for enhanced metafiles. If the handle to
  38. // the EMF (m_hPres) is already set, it is returned. If it is
  39. // not, LoadHPRES() is called which loads the presentation and
  40. // returns the handle to it.
  41. //
  42. //--------------------------------------------------------------------------
  43. inline HENHMETAFILE CEMfObject::M_HPRES(void)
  44. {
  45. return (m_hPres ? m_hPres : LoadHPRES());
  46. }
  47. //+-------------------------------------------------------------------------
  48. //
  49. // Member: CEMfObject::CEMfObject
  50. //
  51. // Synopsis: constructor for the enhanced metafile object
  52. //
  53. // Effects:
  54. //
  55. // Arguments: [pCacheNode] -- pointer to the cache node for this object
  56. // [dwAspect] -- drawing aspect for the object
  57. //
  58. // History: dd-mmm-yy Author Comment
  59. // 13-Feb-95 t-ScottH initialize m_pfnContinue
  60. // 12-May-94 DavePl Created
  61. //
  62. // Notes:
  63. //
  64. //--------------------------------------------------------------------------
  65. CEMfObject::CEMfObject(LPCACHENODE pCacheNode, DWORD dwAspect)
  66. {
  67. VDATEHEAP();
  68. m_ulRefs = 1;
  69. m_hPres = NULL;
  70. m_dwSize = 0;
  71. m_dwAspect = dwAspect;
  72. m_pCacheNode = pCacheNode;
  73. m_dwContinue = 0;
  74. m_pfnContinue = NULL;
  75. m_lWidth = 0;
  76. m_lHeight = 0;
  77. m_fMetaDC = FALSE;
  78. m_nRecord = 0;
  79. m_error = NOERROR;
  80. }
  81. //+-------------------------------------------------------------------------
  82. //
  83. // Member: CEMfObject::~CEMfObject
  84. //
  85. // Synopsis: Destroys an enahnced metafile presentation object
  86. //
  87. // History: dd-mmm-yy Author Comment
  88. // 12-May-94 DavePl Created
  89. //
  90. //--------------------------------------------------------------------------
  91. CEMfObject::~CEMfObject (void)
  92. {
  93. VDATEHEAP();
  94. CEMfObject::DiscardHPRES();
  95. }
  96. //+-------------------------------------------------------------------------
  97. //
  98. // Member: CEMfObject::QueryInterface
  99. //
  100. // Synopsis: returns supported interfaces
  101. //
  102. // Arguments: [iid] -- the requested interface ID
  103. // [ppvObj] -- where to put the interface pointer
  104. //
  105. // Requires:
  106. //
  107. // Returns: NOERROR, E_NOINTERFACE
  108. //
  109. // Derivation: IOlePresObj
  110. //
  111. // Algorithm:
  112. //
  113. // History: dd-mmm-yy Author Comment
  114. // 12-May-94 DavePl Created
  115. //
  116. //--------------------------------------------------------------------------
  117. STDMETHODIMP CEMfObject::QueryInterface (REFIID iid, void ** ppvObj)
  118. {
  119. VDATEHEAP();
  120. if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IOlePresObj))
  121. {
  122. *ppvObj = this;
  123. AddRef();
  124. return NOERROR;
  125. }
  126. else
  127. {
  128. *ppvObj = NULL;
  129. return E_NOINTERFACE;
  130. }
  131. }
  132. //+-------------------------------------------------------------------------
  133. //
  134. // Member: CEMfObject::AddRef
  135. //
  136. // Synopsis: Increments the reference count
  137. //
  138. // Returns: ULONG -- the new reference count
  139. //
  140. // Derivation: IOlePresObj
  141. //
  142. // History: dd-mmm-yy Author Comment
  143. // 12-May-94 DavePl Created
  144. //
  145. //--------------------------------------------------------------------------
  146. STDMETHODIMP_(ULONG) CEMfObject::AddRef(void)
  147. {
  148. VDATEHEAP();
  149. return (ULONG) InterlockedIncrement((LONG *) &m_ulRefs);
  150. }
  151. //+-------------------------------------------------------------------------
  152. //
  153. // Member: CEMfObject::Release
  154. //
  155. // Synopsis: decrements the reference count
  156. //
  157. // Effects: deletes the object once the ref count goes to zero
  158. //
  159. // Returns: ULONG -- the new reference count
  160. //
  161. // Derivation: IOlePresObj
  162. //
  163. // History: dd-mmm-yy Author Comment
  164. // 12-May-94 DavePl Created
  165. //
  166. // Notes: Not multi-threaded safe
  167. //
  168. //--------------------------------------------------------------------------
  169. STDMETHODIMP_(ULONG) CEMfObject::Release(void)
  170. {
  171. VDATEHEAP();
  172. ULONG cTmp = (ULONG) InterlockedDecrement((LONG *) &m_ulRefs);
  173. if (0 == cTmp)
  174. {
  175. delete this;
  176. }
  177. return cTmp;
  178. }
  179. //+-------------------------------------------------------------------------
  180. //
  181. // Member: CEMfObject::GetData
  182. //
  183. // Synopsis: Retrieves data in the specified format from the object
  184. //
  185. // Arguments: [pformatetcIn] -- the requested data format
  186. // [pmedium] -- where to put the data
  187. //
  188. // Returns: HRESULT
  189. //
  190. // Derivation: IOlePresObject
  191. //
  192. // History: dd-mmm-yy Author Comment
  193. // 12-May-94 DavePl Created
  194. //
  195. //--------------------------------------------------------------------------
  196. STDMETHODIMP CEMfObject::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
  197. {
  198. VDATEHEAP();
  199. HRESULT hr = NOERROR;
  200. pmedium->tymed = (DWORD) TYMED_NULL;
  201. pmedium->pUnkForRelease = NULL;
  202. // We can only support enhanced metafile TYMED
  203. if (!(pformatetcIn->tymed & (DWORD) TYMED_ENHMF))
  204. {
  205. hr = DV_E_TYMED;
  206. }
  207. // We can only support enhanced metafile clipformat
  208. else if (pformatetcIn->cfFormat != CF_ENHMETAFILE)
  209. {
  210. hr = DV_E_CLIPFORMAT;
  211. }
  212. // Check to ensure we are not blank
  213. else if (IsBlank())
  214. {
  215. hr = OLE_E_BLANK;
  216. }
  217. // Go ahead and try to get the data
  218. else
  219. {
  220. HENHMETAFILE hEMF = M_HPRES();
  221. if (NULL == hEMF)
  222. {
  223. hr = OLE_E_BLANK;
  224. }
  225. else if (NULL == (pmedium->hEnhMetaFile = CopyEnhMetaFile(hEMF, NULL)))
  226. {
  227. hr = HRESULT_FROM_WIN32(GetLastError());
  228. }
  229. else
  230. {
  231. pmedium->tymed = (DWORD) TYMED_ENHMF;
  232. }
  233. }
  234. return hr;
  235. }
  236. //+-------------------------------------------------------------------------
  237. //
  238. // Member: CEMfObject::GetDataHere
  239. //
  240. // Synopsis: Retrieves data of the specified format into the specified
  241. // medium
  242. //
  243. // Arguments: [pformatetcIn] -- the requested data format
  244. // [pmedium] -- where to put the data
  245. //
  246. // Derivation: IOlePresObj
  247. //
  248. // Algorithm: Does error checking and then copies the EMF into a
  249. // stream.
  250. //
  251. // History: dd-mmm-yy Author Comment
  252. // 14-May-94 DavePl Created
  253. //
  254. // Notes: Although I'm only handling TYMED_ISTREAM here, since that's
  255. // all standard metafiles provide, there's no compelling reason
  256. // we couldn't support other formats. In fact, supporting
  257. // raw bits on TYMED_HGLOBAL might be a nice addition, and
  258. // TYMED_MFPICT would make for an easy way to do enhanced to
  259. // standard conversions. NTIssue #2802.
  260. //
  261. //
  262. // _______
  263. // | DWORD | One DWORD indicating the size of the header
  264. // |-------|
  265. // | |
  266. // | HDR | The ENHMETAHEADER structure
  267. // | |
  268. // |-------|
  269. // | |
  270. // | DATA | Raw EMF bits
  271. // |_______|
  272. //
  273. //--------------------------------------------------------------------------
  274. STDMETHODIMP CEMfObject::GetDataHere
  275. (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
  276. {
  277. VDATEHEAP();
  278. HRESULT hr = NOERROR;
  279. // We can only handle EMF format
  280. if (pformatetcIn->cfFormat != CF_ENHMETAFILE)
  281. {
  282. hr = DV_E_CLIPFORMAT;
  283. }
  284. // We can only support returns to ISTREAM
  285. else if (pmedium->tymed != (DWORD) TYMED_ISTREAM)
  286. {
  287. hr = DV_E_TYMED;
  288. }
  289. // The stream ptr must be valid
  290. else if (pmedium->pstm == NULL)
  291. {
  292. hr = E_INVALIDARG;
  293. }
  294. // The presentation must not be blank
  295. else if (IsBlank())
  296. {
  297. hr = OLE_E_BLANK;
  298. }
  299. else
  300. {
  301. // Get the metaheader size
  302. HENHMETAFILE hEMF = M_HPRES();
  303. DWORD dwMetaHdrSize = GetEnhMetaFileHeader(hEMF, 0, NULL);
  304. if (dwMetaHdrSize == 0)
  305. {
  306. return HRESULT_FROM_WIN32(GetLastError());
  307. }
  308. // Allocate the meta header
  309. void * pvHeader = PrivMemAlloc(dwMetaHdrSize);
  310. if (NULL == pvHeader)
  311. {
  312. return E_OUTOFMEMORY;
  313. }
  314. // Retrieve the ENHMETAHEADER
  315. if (0 == GetEnhMetaFileHeader(hEMF, dwMetaHdrSize, (ENHMETAHEADER *) pvHeader))
  316. {
  317. PrivMemFree(pvHeader);
  318. return HRESULT_FROM_WIN32(GetLastError());
  319. }
  320. // Write the byte count to disk.
  321. hr = StWrite(pmedium->pstm, &dwMetaHdrSize, sizeof(DWORD));
  322. if (FAILED(hr))
  323. {
  324. return hr;
  325. }
  326. // Write the enhmetaheader to disk
  327. hr = StWrite(pmedium->pstm, pvHeader, dwMetaHdrSize);
  328. PrivMemFree(pvHeader);
  329. if (FAILED(hr))
  330. {
  331. return hr;
  332. }
  333. DWORD dwSize = GetEnhMetaFileBits(hEMF, 0, NULL);
  334. if (0 == dwSize)
  335. {
  336. return HRESULT_FROM_WIN32(GetLastError());
  337. }
  338. // Write the EMF bits to the stream
  339. hr = UtHEMFToEMFStm(hEMF,
  340. m_dwSize,
  341. pmedium->pstm,
  342. WRITE_AS_EMF);
  343. }
  344. return hr;
  345. }
  346. //+-------------------------------------------------------------------------
  347. //
  348. // Member: CEMfObject::SetDataWDO
  349. //
  350. // Synopsis: Stores an ehanced metafile in this object
  351. //
  352. // Effects:
  353. //
  354. // Arguments: [pformatetc] -- format of the data coming in
  355. // [pmedium] -- the new metafile (data)
  356. // [fRelease] -- if true, then we'll release the [pmedium]
  357. // [IDataObject] -- unused for EMF objects
  358. //
  359. // Derivation: IOlePresObj
  360. //
  361. // History: dd-mmm-yy Author Comment
  362. // 14-May-94 Davepl Created
  363. //
  364. // Notes:
  365. //
  366. //--------------------------------------------------------------------------
  367. STDMETHODIMP CEMfObject::SetDataWDO
  368. (LPFORMATETC pformatetc, STGMEDIUM * pmedium, BOOL fRelease, IDataObject * )
  369. {
  370. VDATEHEAP();
  371. HRESULT hr;
  372. BOOL fTakeData = FALSE;
  373. // If someone is trying to SetData on our EMF object with a standard
  374. // metafile, we must convert it to EMF format
  375. if (pformatetc->cfFormat == CF_METAFILEPICT)
  376. {
  377. // If its a standard metafile, it must be TYMED_MFPICT
  378. if (pmedium->tymed != (DWORD) TYMED_MFPICT)
  379. {
  380. return DV_E_TYMED;
  381. }
  382. // We need to know the size of the metafile in bytes,
  383. // so we have to lock the structure and grab the handle
  384. // for a call to GetMetaFileBitsEx
  385. METAFILEPICT * pMF = (METAFILEPICT *) GlobalLock(pmedium->hMetaFilePict);
  386. if (NULL == pMF)
  387. {
  388. return E_OUTOFMEMORY;
  389. }
  390. // Determine the no. of bytes needed to hold the
  391. // metafile
  392. DWORD dwSize = GetMetaFileBitsEx(pMF->hMF, NULL, 0);
  393. if (0 == dwSize)
  394. {
  395. GlobalUnlock(pmedium->hMetaFilePict);
  396. return E_FAIL;
  397. }
  398. // Allocate space for the metafile bits
  399. void *pvBuffer = PrivMemAlloc(dwSize);
  400. if (NULL == pvBuffer)
  401. {
  402. GlobalUnlock(pmedium->hMetaFilePict);
  403. return E_OUTOFMEMORY;
  404. }
  405. // Retrieve the bits to our buffer
  406. if (0 == GetMetaFileBitsEx(pMF->hMF, dwSize, pvBuffer))
  407. {
  408. GlobalUnlock(pmedium->hMetaFilePict);
  409. PrivMemFree(pvBuffer);
  410. return E_FAIL;
  411. }
  412. HENHMETAFILE hEMF = SetWinMetaFileBits(dwSize,
  413. (const BYTE *) pvBuffer, NULL, pMF);
  414. if (NULL == hEMF)
  415. {
  416. hr = HRESULT_FROM_WIN32(GetLastError());
  417. GlobalUnlock(pmedium->hMetaFilePict);
  418. PrivMemFree(pvBuffer);
  419. return hr;
  420. }
  421. GlobalUnlock(pmedium->hMetaFilePict);
  422. PrivMemFree(pvBuffer);
  423. // Update the cache node. To avoid a copy operation, let the cache
  424. // node keep our EMF. It will take the data even in the event of
  425. // an error
  426. hr = ChangeData (hEMF, TRUE /* fTakeData */ );
  427. if (fRelease)
  428. {
  429. ReleaseStgMedium(pmedium);
  430. }
  431. return hr;
  432. }
  433. // Other than standard metafile ,we can only accept enhanced metafile format
  434. if (pformatetc->cfFormat != CF_ENHMETAFILE)
  435. {
  436. return DV_E_CLIPFORMAT;
  437. }
  438. // The medium must be enhanced metafile
  439. if (pmedium->tymed != (DWORD) TYMED_ENHMF)
  440. {
  441. return DV_E_TYMED;
  442. }
  443. // If no controlling unkown, and the release flag is set,
  444. // it is up to us to take control of the data
  445. if ((pmedium->pUnkForRelease == NULL) && fRelease)
  446. {
  447. fTakeData = TRUE;
  448. }
  449. // ChangeData will keep the data if fRelease is TRUE, else it copies
  450. hr = ChangeData (pmedium->hEnhMetaFile, fTakeData);
  451. // If we've taken the data, clear the TYMED
  452. if (fTakeData)
  453. {
  454. pmedium->tymed = (DWORD) TYMED_NULL;
  455. pmedium->hEnhMetaFile = NULL;
  456. }
  457. // If we are supposed to release the data, do it now
  458. else if (fRelease)
  459. {
  460. ReleaseStgMedium(pmedium);
  461. }
  462. return hr;
  463. }
  464. //+-------------------------------------------------------------------------
  465. //
  466. // Member: CEMfObject::ChangeData (internal)
  467. //
  468. // Synopsis: Swaps the stored enhanced metafile presentation into the
  469. // cache node
  470. //
  471. // Arguments: [hEMF] -- the new enhanced metafile
  472. // [fTakeData] -- if TRUE, then delete [hEMF]
  473. //
  474. // History: dd-mmm-yy Author Comment
  475. // 14-May-94 DavePl Created
  476. //
  477. // Notes: If the routine fails then the object will be left with it's
  478. // old data. We are supposed to delete the incoming EMF when
  479. // fTakeData is set, even in the event of an error.
  480. //
  481. //--------------------------------------------------------------------------
  482. INTERNAL CEMfObject::ChangeData (HENHMETAFILE hEMF, BOOL fTakeData)
  483. {
  484. VDATEHEAP();
  485. HENHMETAFILE hNewEMF;
  486. DWORD dwSize;
  487. HRESULT hr = NOERROR;
  488. // If we're not supposed to delete the metafile when we're
  489. // done, we need to make a copy. Otherwise, we can just
  490. // use the handle that came in.
  491. if (!fTakeData)
  492. {
  493. hNewEMF = CopyEnhMetaFile(hEMF, NULL);
  494. if (NULL == hNewEMF)
  495. {
  496. return HRESULT_FROM_WIN32(GetLastError());
  497. }
  498. }
  499. else
  500. {
  501. hNewEMF = hEMF;
  502. }
  503. // We get the size of the EMF by calling GetEnhMetaFileBits with
  504. // a NULL buffer
  505. dwSize = GetEnhMetaFileBits(hNewEMF, 0, NULL);
  506. if (0 == dwSize)
  507. {
  508. hr = OLE_E_BLANK;
  509. }
  510. else
  511. {
  512. // We need the dimensions of the metafile, so
  513. // we have to get the header.
  514. ENHMETAHEADER emfHeader;
  515. UINT result = GetEnhMetaFileHeader(hNewEMF,
  516. sizeof(emfHeader),
  517. &emfHeader);
  518. if (0 == result)
  519. {
  520. hr = HRESULT_FROM_WIN32(GetLastError());
  521. }
  522. else
  523. {
  524. // If there already is an EMF presentation, kill it
  525. // so we can replace it
  526. DiscardHPRES();
  527. // Set up our new EMF as the presentation
  528. m_hPres = hNewEMF;
  529. m_dwSize = dwSize;
  530. m_lWidth = emfHeader.rclFrame.right -
  531. emfHeader.rclFrame.left;
  532. m_lHeight = emfHeader.rclFrame.bottom -
  533. emfHeader.rclFrame.top;
  534. // EMF extents are returned in physical himets,
  535. // but all of the other formats are in logical
  536. // himets, so we need to convert.
  537. LONG HorzSize,
  538. HorzRes,
  539. VertSize,
  540. VertRes,
  541. LogXPels,
  542. LogYPels;
  543. HDC hdcTmp = GetDC(NULL);
  544. if (hdcTmp)
  545. {
  546. const LONG HIMET_PER_MM = 100;
  547. const LONG HIMET_PER_LINCH = 2540;
  548. HorzSize = GetDeviceCaps(hdcTmp, HORZSIZE);
  549. HorzRes = GetDeviceCaps(hdcTmp, HORZRES);
  550. VertSize = GetDeviceCaps(hdcTmp, VERTSIZE);
  551. VertRes = GetDeviceCaps(hdcTmp, VERTRES);
  552. LogXPels = GetDeviceCaps(hdcTmp, LOGPIXELSX);
  553. LogYPels = GetDeviceCaps(hdcTmp, LOGPIXELSY);
  554. LEVERIFY( ReleaseDC(NULL, hdcTmp) );
  555. // The GDI cannot fail the above calls, but
  556. // it's a possibility that some broken driver
  557. // returns a zero. Unlikely, but a division
  558. // by zero is severe, so check for it...
  559. if ( !HorzSize || !HorzRes || !VertSize ||
  560. !VertRes || !LogXPels || !LogYPels)
  561. {
  562. Assert(0 && " A Devicecap is zero! ");
  563. hr = E_FAIL;
  564. }
  565. if (SUCCEEDED(hr))
  566. {
  567. // Convert physical himetrics to pixels
  568. m_lWidth = MulDiv(m_lWidth, HorzRes, HorzSize);
  569. m_lHeight = MulDiv(m_lHeight, VertRes, VertSize);
  570. m_lWidth = m_lWidth / HIMET_PER_MM;
  571. m_lHeight = m_lHeight / HIMET_PER_MM;
  572. // Convert pixels to logical himetrics
  573. m_lWidth =
  574. MulDiv(m_lWidth, HIMET_PER_LINCH, LogXPels);
  575. m_lHeight =
  576. MulDiv(m_lHeight, HIMET_PER_LINCH, LogYPels);
  577. }
  578. }
  579. else
  580. {
  581. hr = HRESULT_FROM_WIN32(GetLastError());
  582. }
  583. }
  584. }
  585. if (FAILED(hr))
  586. {
  587. LEVERIFY( DeleteEnhMetaFile(hNewEMF) );
  588. }
  589. return hr;
  590. }
  591. //+-------------------------------------------------------------------------
  592. //
  593. // Member: CEMfObject::Draw
  594. //
  595. // Synopsis: Draws the stored presentation
  596. //
  597. // Arguments: [pvAspect] -- (UNUSED) the drawing aspect
  598. // [hicTargetDev] -- (UNUSED) the target device
  599. // [hdcDraw] -- hdc to draw into
  600. // [lprcBounds] -- bounding rectangle to draw into
  601. // [lprcWBounds] -- (UNUSED) bounding rectangle for the metafile
  602. // [pfnContinue] -- function to call while drawing
  603. // [dwContinue] -- parameter to [pfnContinue]
  604. //
  605. // Returns: HRESULT
  606. //
  607. // Derivation: IOlePresObj
  608. //
  609. // Algorithm: Sets the viewport and metafile boundaries, then plays
  610. // the metafile
  611. //
  612. // History: dd-mmm-yy Author Comment
  613. // 14-May-94 DavePl Created
  614. //
  615. //--------------------------------------------------------------------------
  616. STDMETHODIMP CEMfObject::Draw(THIS_ void * /* UNUSED pvAspect */,
  617. HDC /* UNUSED hicTargetDev */,
  618. HDC hdcDraw,
  619. LPCRECTL lprcBounds,
  620. LPCRECTL /* UNUSED lprcWBounds */,
  621. int (CALLBACK * pfnContinue)(ULONG_PTR),
  622. ULONG_PTR dwContinue)
  623. {
  624. VDATEHEAP();
  625. m_error = NOERROR;
  626. int iOldDc;
  627. RECT rlBounds;
  628. // We receive a RECTL, and must pass in a RECT. 16-bit used to
  629. // manually copy the fields over, but we know that in Win32 they
  630. // really are the same structure. Assert to be sure.
  631. Assert(sizeof(RECT) == sizeof(RECTL));
  632. Assert(lprcBounds);
  633. // We must have an EMF handle before we can even begin
  634. if (!M_HPRES())
  635. {
  636. return OLE_E_BLANK;
  637. }
  638. // Make a copy of the incoming bounding rectangle
  639. memcpy(&rlBounds, lprcBounds, sizeof(RECT));
  640. m_nRecord = EMF_RECORD_COUNT;
  641. // Determine whether or not we are drawing into another
  642. // metafile
  643. m_fMetaDC = OleIsDcMeta (hdcDraw);
  644. // Save the current state of the DC
  645. if (0 == (iOldDc = SaveDC (hdcDraw)))
  646. {
  647. return E_OUTOFMEMORY;
  648. }
  649. m_pfnContinue = pfnContinue;
  650. m_dwContinue = dwContinue;
  651. LEVERIFY( EnumEnhMetaFile(hdcDraw, m_hPres, EMfCallbackFuncForDraw, this, (RECT *) lprcBounds) );
  652. LEVERIFY( RestoreDC (hdcDraw, iOldDc) );
  653. return m_error;
  654. }
  655. //+-------------------------------------------------------------------------
  656. //
  657. // Function: EMfCallBackFuncForDraw
  658. //
  659. // Synopsis: callback function for drawing metafiles -- call's the caller's
  660. // draw method (via a passed in this pointer)
  661. //
  662. // Effects:
  663. //
  664. // Arguments: [hdc] -- the device context
  665. // [lpHTable] -- pointer to the MF handle table
  666. // [lpEMFR] -- pointer to metafile record
  667. // [nObj] -- number of objects
  668. //
  669. // Requires:
  670. //
  671. // Returns: non-zero to continue, zero stops the drawing
  672. //
  673. // History: dd-mmm-yy Author Comment
  674. // 12-May-94 DavePl Created
  675. //
  676. //--------------------------------------------------------------------------
  677. int CALLBACK EMfCallbackFuncForDraw(HDC hdc,
  678. HANDLETABLE FAR* lpHTable,
  679. const ENHMETARECORD FAR* lpEMFR,
  680. int nObj,
  681. LPARAM lpobj)
  682. {
  683. VDATEHEAP();
  684. // Warning: this casts an LPARAM (a long) to a pointer, but
  685. // it's the "approved" way of doing this...
  686. return ((CEMfObject *) lpobj)->CallbackFuncForDraw(hdc,
  687. lpHTable,
  688. lpEMFR,
  689. nObj,
  690. lpobj);
  691. }
  692. //+-------------------------------------------------------------------------
  693. //
  694. // Member: CEMfObject::CallbackFuncForDraw
  695. //
  696. // Synopsis: Draws the metafile
  697. //
  698. // Effects:
  699. //
  700. // Arguments: [hdc] -- the device context
  701. // [lpHTable] -- pointer to the MF handle table
  702. // [lpEMFR] -- pointer to metafile record
  703. // [nObj] -- number of objects
  704. //
  705. // Requires:
  706. //
  707. // Returns: non-zero to continue, zero stops the drawing
  708. //
  709. // History: dd-mmm-yy Author Comment
  710. // 12-May-94 DavePl Created
  711. //
  712. //--------------------------------------------------------------------------
  713. int CALLBACK CEMfObject::CallbackFuncForDraw(HDC hdc,
  714. LPHANDLETABLE lpHTable,
  715. const ENHMETARECORD * lpEMFR,
  716. int nObj,
  717. LPARAM /* UNUSED lpobj*/)
  718. {
  719. // Count down the record count. When the count reaches zero,
  720. // it is time to call the "continue" function
  721. if (0 == --m_nRecord)
  722. {
  723. m_nRecord = EMF_RECORD_COUNT;
  724. if (m_pfnContinue && !((*(m_pfnContinue))(m_dwContinue)))
  725. {
  726. m_error = E_ABORT;
  727. return FALSE;
  728. }
  729. }
  730. LEVERIFY( PlayEnhMetaFileRecord (hdc, lpHTable, lpEMFR, (unsigned) nObj) );
  731. return TRUE;
  732. }
  733. //+-------------------------------------------------------------------------
  734. //
  735. // Member: CEMfObject::Load
  736. //
  737. // Synopsis: Loads an enhanced metafile object from the given stream
  738. //
  739. // Arguments: [lpstream] -- the stream from which to load
  740. // [fReadHeaderOnly] -- if TRUE, then only the header is
  741. // read
  742. // Returns: HRESULT
  743. //
  744. // Derivation: IOlePresObj
  745. //
  746. // History: dd-mmm-yy Author Comment
  747. // 12-May-94 DavePl Created
  748. //
  749. //--------------------------------------------------------------------------
  750. STDMETHODIMP CEMfObject::Load(LPSTREAM lpstream, BOOL fReadHeaderOnly)
  751. {
  752. VDATEHEAP();
  753. DWORD dwBuf[4];
  754. HRESULT hr;
  755. /* read dwCompression, width, height, size of data */
  756. hr = StRead(lpstream, dwBuf, 4*sizeof(DWORD));
  757. if (FAILED(hr))
  758. {
  759. return hr;
  760. }
  761. m_lWidth = (LONG) dwBuf[1];
  762. m_lHeight = (LONG) dwBuf[2];
  763. m_dwSize = dwBuf[3];
  764. if (!m_dwSize || fReadHeaderOnly)
  765. {
  766. return NOERROR;
  767. }
  768. // Read the EMF from the stream and create a handle to it. Note
  769. // that the size will be adjusted to reflect the size of the
  770. // in-memory EMF, which may well differ from the the persistent
  771. // form (which is a MF with an EMF embedded as a comment).
  772. return UtGetHEMFFromEMFStm(lpstream, &m_dwSize, &m_hPres);
  773. }
  774. //+-------------------------------------------------------------------------
  775. //
  776. // Member: CEMfObjectn
  777. //
  778. // Synopsis: Saves the metafile to the given stream
  779. //
  780. // Arguments: [lpstream] -- the stream to save to
  781. //
  782. // Returns: HRESULT
  783. //
  784. // Derivation: IOlePresObj
  785. //
  786. // History: dd-mmm-yy Author Comment
  787. // 12-May-94 DavePl Created
  788. //
  789. //--------------------------------------------------------------------------
  790. STDMETHODIMP CEMfObject::Save(LPSTREAM lpstream)
  791. {
  792. VDATEHEAP();
  793. HRESULT hr;
  794. DWORD dwBuf[4];
  795. DWORD dwPersistSize;
  796. // The EMF could have been provided during this session, which would imply
  797. // that the resultant size of the converted EMF has no bearing on the size
  798. // of the original EMF we have been using. Thus, we must update the size
  799. // for the persistent form.
  800. // If we are a blank presentation, there's no need to calculate
  801. // anything: our size is just 0
  802. if (IsBlank() || m_hPres == NULL)
  803. {
  804. dwPersistSize = 0;
  805. }
  806. else
  807. {
  808. HDC hdcTemp = CreateCompatibleDC(NULL);
  809. if (NULL == hdcTemp)
  810. {
  811. return HRESULT_FROM_WIN32(GetLastError());
  812. }
  813. dwPersistSize = GetWinMetaFileBits(m_hPres, 0, NULL, MM_ANISOTROPIC, hdcTemp);
  814. if (0 == dwPersistSize)
  815. {
  816. LEVERIFY( DeleteDC(hdcTemp) );
  817. return HRESULT_FROM_WIN32(GetLastError());
  818. }
  819. Verify(DeleteDC(hdcTemp));
  820. }
  821. /* write dwCompression, width, height, size of data */
  822. dwBuf[0] = 0L;
  823. dwBuf[1] = (DWORD) m_lWidth;
  824. dwBuf[2] = (DWORD) m_lHeight;
  825. dwBuf[3] = dwPersistSize;
  826. hr = StWrite(lpstream, dwBuf, sizeof(dwBuf));
  827. if (FAILED(hr))
  828. {
  829. return hr;
  830. }
  831. // if blank object, don't write any more; no error.
  832. if (IsBlank() || m_hPres == NULL)
  833. {
  834. StSetSize(lpstream, 0, TRUE);
  835. return NOERROR;
  836. }
  837. return UtHEMFToEMFStm(m_hPres,
  838. dwPersistSize,
  839. lpstream,
  840. WRITE_AS_WMF);
  841. }
  842. //+-------------------------------------------------------------------------
  843. //
  844. // Member: CEMfObject::IsBlank
  845. //
  846. // Synopsis: Returns whether or not the enhanced metafile is blank
  847. //
  848. // Arguments: void
  849. //
  850. // Returns: TRUE/FALSE
  851. //
  852. // Derivation: IOlePresObj
  853. //
  854. // History: dd-mmm-yy Author Comment
  855. // 12-May-94 DavePl Created
  856. //
  857. //--------------------------------------------------------------------------
  858. BOOL CEMfObject::IsBlank(void)
  859. {
  860. VDATEHEAP();
  861. return (m_dwSize ? FALSE : TRUE);
  862. }
  863. //+-------------------------------------------------------------------------
  864. //
  865. // Member: CEMfObject::LoadHPRES (private)
  866. //
  867. // Synopsis: Loads the presentation from the cache's stream and returns
  868. // a handle to it
  869. //
  870. // Returns: HANDLE to the metafile
  871. //
  872. // History: dd-mmm-yy Author Comment
  873. // 12-May-94 DavePl Created
  874. //
  875. //--------------------------------------------------------------------------
  876. INTERNAL_(HENHMETAFILE) CEMfObject::LoadHPRES(void)
  877. {
  878. VDATEHEAP();
  879. LPSTREAM pstm = m_pCacheNode->GetStm(TRUE /*fSeekToPresBits*/,
  880. STGM_READ);
  881. if (pstm)
  882. {
  883. // In case ::Load() fails, NULL the handle first
  884. m_hPres = NULL;
  885. LEVERIFY( SUCCEEDED(Load(pstm, FALSE /* fHeaderOnly*/)) );
  886. pstm->Release();
  887. }
  888. return m_hPres;
  889. }
  890. //+-------------------------------------------------------------------------
  891. //
  892. // Member: CEMfObject::DiscardHPRES
  893. //
  894. // Synopsis: deletes the stored metafile
  895. //
  896. // Derivation: IOlePresObj
  897. //
  898. // History: dd-mmm-yy Author Comment
  899. // 12-May-94 DavePl Created
  900. //
  901. //--------------------------------------------------------------------------
  902. void CEMfObject::DiscardHPRES(void)
  903. {
  904. VDATEHEAP();
  905. if (m_hPres)
  906. {
  907. LEVERIFY( DeleteEnhMetaFile(m_hPres) );
  908. m_hPres = NULL;
  909. }
  910. }
  911. //+-------------------------------------------------------------------------
  912. //
  913. // Member: CEMfObject::GetCopyOfHPRES (private)
  914. //
  915. // Synopsis: makes a copy of the enhanced metafile (if one is present),
  916. // otherwise just loads it from the stream (but doesn't store
  917. // it in [this] object)
  918. //
  919. // Arguments: void
  920. //
  921. // Returns: HENHMETAFILE to the enhanced metafile
  922. //
  923. // History: dd-mmm-yy Author Comment
  924. // 12-May-94 DavePl Created
  925. //
  926. //--------------------------------------------------------------------------
  927. INTERNAL_(HENHMETAFILE) CEMfObject::GetCopyOfHPRES(void)
  928. {
  929. VDATEHEAP();
  930. HENHMETAFILE hPres;
  931. // Make a copy if the presentation data is already loaded
  932. if (m_hPres)
  933. {
  934. return CopyEnhMetaFile(m_hPres, NULL);
  935. }
  936. // Load the presentation data now and return the same handle.
  937. // No need to copy the data. If the caller wants the m_hPres to be
  938. // set s/he would call LoadHPRES() directly.
  939. LEVERIFY( LoadHPRES() );
  940. hPres = m_hPres; // Grab the handle from the member var
  941. m_hPres = NULL; // (re-) Clear out the member var
  942. return hPres;
  943. }
  944. //+-------------------------------------------------------------------------
  945. //
  946. // Member: CEMfObject::GetColorSet
  947. //
  948. // Synopsis: Retrieves the logical palette associated with the EMF
  949. //
  950. // Effects:
  951. //
  952. // Arguments: [pvAspect] -- the drawing aspect
  953. // [hicTargetDev] -- target device
  954. // [ppColorSet] -- where to put the logical palette pointer
  955. //
  956. // Returns: HRESULT
  957. //
  958. // Derivation: IOlePresObj
  959. //
  960. // History: dd-mmm-yy Author Comment
  961. // 18-May-94 DavePl Created
  962. //
  963. //--------------------------------------------------------------------------
  964. STDMETHODIMP CEMfObject::GetColorSet(LPVOID /* UNUSED pvAspect */,
  965. HDC /* UNUSED hicTargetDev */,
  966. LPLOGPALETTE * ppColorSet)
  967. {
  968. VDATEHEAP();
  969. VDATEPTROUT(ppColorSet, LPLOGPALETTE);
  970. m_pColorSet = *ppColorSet = NULL;
  971. if (IsBlank() || !M_HPRES())
  972. {
  973. return OLE_E_BLANK;
  974. }
  975. HENHMETAFILE hEMF = M_HPRES();
  976. // Get the count of palette entries
  977. UINT cColors = GetEnhMetaFilePaletteEntries(hEMF, 0, NULL);
  978. // If no palette entries, return a NULL LOGPALETTE
  979. if (0 == cColors)
  980. {
  981. return S_FALSE;
  982. }
  983. // REVIEW (davepl) A quick fix until we figure out what happens, or if
  984. // it is possible, for a EMF to have more than 32767 colors
  985. LEWARN( cColors > USHRT_MAX, "EMF has more colors than LOGPALETTE allows" );
  986. if (cColors > USHRT_MAX)
  987. {
  988. cColors = USHRT_MAX;
  989. }
  990. // Calculate the size of the variably-sized LOGPALLETE structure
  991. UINT uPalSize = cColors * sizeof(PALETTEENTRY) + 2 * sizeof(WORD);
  992. // Allocate the LOGPALETTE structure
  993. m_pColorSet = (LPLOGPALETTE) PubMemAlloc(uPalSize);
  994. if( NULL == m_pColorSet)
  995. {
  996. m_error = E_OUTOFMEMORY;
  997. return FALSE;
  998. }
  999. // Get the actual color entries
  1000. m_pColorSet->palVersion = 0x300;
  1001. m_pColorSet->palNumEntries = (WORD) cColors;
  1002. UINT result = GetEnhMetaFilePaletteEntries(
  1003. hEMF,
  1004. cColors,
  1005. &(m_pColorSet->palPalEntry[0]));
  1006. // If it failed, clean up and bail
  1007. if (cColors != result)
  1008. {
  1009. PubMemFree(m_pColorSet);
  1010. m_pColorSet = NULL;
  1011. return HRESULT_FROM_WIN32(GDI_ERROR);
  1012. }
  1013. // We succeeded, so set the OUT ptr and return
  1014. *ppColorSet = m_pColorSet;
  1015. return NOERROR;
  1016. }
  1017. //+-------------------------------------------------------------------------
  1018. //
  1019. // Member: CEMfObject::GetExtent
  1020. //
  1021. // Synopsis: Retrieves the extents of the enhanced metafile
  1022. //
  1023. // Arguments: [dwDrawAspect] -- the drawing aspect we're interested in
  1024. // [lpsizel] -- where to put the extent info
  1025. //
  1026. // Returns: NOERROR, DV_E_DVASPECT, OLE_E_BLANK
  1027. //
  1028. // Derivation: IOlePresObj
  1029. //
  1030. // History: dd-mmm-yy Author Comment
  1031. // 18-May-94 DavePl Created
  1032. //
  1033. //--------------------------------------------------------------------------
  1034. STDMETHODIMP CEMfObject::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
  1035. {
  1036. VDATEHEAP();
  1037. if (!(dwDrawAspect & m_dwAspect))
  1038. {
  1039. return DV_E_DVASPECT;
  1040. }
  1041. if (IsBlank())
  1042. {
  1043. return OLE_E_BLANK;
  1044. }
  1045. lpsizel->cx = m_lWidth;
  1046. lpsizel->cy = m_lHeight;
  1047. return NOERROR;
  1048. }
  1049. //+-------------------------------------------------------------------------
  1050. //
  1051. // Member: CEMfObject::Dump, public (_DEBUG only)
  1052. //
  1053. // Synopsis: return a string containing the contents of the data members
  1054. //
  1055. // Effects:
  1056. //
  1057. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  1058. // [ulFlag] - flag determining prefix of all newlines of the
  1059. // out character array (default is 0 - no prefix)
  1060. // [nIndentLevel] - will add a indent prefix after the other prefix
  1061. // for ALL newlines (including those with no prefix)
  1062. //
  1063. // Requires:
  1064. //
  1065. // Returns: HRESULT
  1066. //
  1067. // Signals:
  1068. //
  1069. // Modifies: [ppszDump] - argument
  1070. //
  1071. // Derivation:
  1072. //
  1073. // Algorithm: use dbgstream to create a string containing information on the
  1074. // content of data structures
  1075. //
  1076. // History: dd-mmm-yy Author Comment
  1077. // 01-Feb-95 t-ScottH author
  1078. //
  1079. // Notes:
  1080. //
  1081. //--------------------------------------------------------------------------
  1082. #ifdef _DEBUG
  1083. HRESULT CEMfObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  1084. {
  1085. int i;
  1086. char *pszPrefix;
  1087. char *pszHRESULT;
  1088. char *pszDVASPECT;
  1089. dbgstream dstrPrefix;
  1090. dbgstream dstrDump(500);
  1091. // determine prefix of newlines
  1092. if ( ulFlag & DEB_VERBOSE )
  1093. {
  1094. dstrPrefix << this << " _VB ";
  1095. }
  1096. // determine indentation prefix for all newlines
  1097. for (i = 0; i < nIndentLevel; i++)
  1098. {
  1099. dstrPrefix << DUMPTAB;
  1100. }
  1101. pszPrefix = dstrPrefix.str();
  1102. // put data members in stream
  1103. dstrDump << pszPrefix << "No. of References = " << m_ulRefs << endl;
  1104. dstrDump << pszPrefix << "Handle Enhanced Metafile = " << m_hPres << endl;
  1105. dstrDump << pszPrefix << "IsMetaDeviceContext? = ";
  1106. if (m_fMetaDC == TRUE)
  1107. {
  1108. dstrDump << "TRUE" << endl;
  1109. }
  1110. else
  1111. {
  1112. dstrDump << "FALSE" << endl;
  1113. }
  1114. dstrDump << pszPrefix << "No. of Records in Metafile = " << m_nRecord << endl;
  1115. pszHRESULT = DumpHRESULT(m_error);
  1116. dstrDump << pszPrefix << "Error code = " << pszHRESULT << endl;
  1117. CoTaskMemFree(pszHRESULT);
  1118. dstrDump << pszPrefix << "pLOGPALETTE (Color set palette) = " << m_pColorSet << endl;
  1119. dstrDump << pszPrefix << "Continue = " << ((ULONG) m_dwContinue) << endl;
  1120. dstrDump << pszPrefix << "fp Continue = " << m_pfnContinue<< endl;
  1121. pszDVASPECT = DumpDVASPECTFlags(m_dwAspect);
  1122. dstrDump << pszPrefix << "Aspect flags = " << pszDVASPECT << endl;
  1123. CoTaskMemFree(pszDVASPECT);
  1124. dstrDump << pszPrefix << "Size = " << m_dwSize << endl;
  1125. dstrDump << pszPrefix << "Width = " << m_lWidth << endl;
  1126. dstrDump << pszPrefix << "Height = " << m_lHeight << endl;
  1127. dstrDump << pszPrefix << "pCacheNode = " << m_pCacheNode << endl;
  1128. // cleanup and provide pointer to character array
  1129. *ppszDump = dstrDump.str();
  1130. if (*ppszDump == NULL)
  1131. {
  1132. *ppszDump = UtDupStringA(szDumpErrorMessage);
  1133. }
  1134. CoTaskMemFree(pszPrefix);
  1135. return NOERROR;
  1136. }
  1137. #endif // _DEBUG
  1138. //+-------------------------------------------------------------------------
  1139. //
  1140. // Function: DumpCEMfObject, public (_DEBUG only)
  1141. //
  1142. // Synopsis: calls the CEMfObject::Dump method, takes care of errors and
  1143. // returns the zero terminated string
  1144. //
  1145. // Effects:
  1146. //
  1147. // Arguments: [pEMFO] - pointer to CEMfObject
  1148. // [ulFlag] - flag determining prefix of all newlines of the
  1149. // out character array (default is 0 - no prefix)
  1150. // [nIndentLevel] - will add a indent prefix after the other prefix
  1151. // for ALL newlines (including those with no prefix)
  1152. //
  1153. // Requires:
  1154. //
  1155. // Returns: character array of structure dump or error (null terminated)
  1156. //
  1157. // Signals:
  1158. //
  1159. // Modifies:
  1160. //
  1161. // Algorithm:
  1162. //
  1163. // History: dd-mmm-yy Author Comment
  1164. // 01-Feb-95 t-ScottH author
  1165. //
  1166. // Notes:
  1167. //
  1168. //--------------------------------------------------------------------------
  1169. #ifdef _DEBUG
  1170. char *DumpCEMfObject(CEMfObject *pEMFO, ULONG ulFlag, int nIndentLevel)
  1171. {
  1172. HRESULT hresult;
  1173. char *pszDump;
  1174. if (pEMFO == NULL)
  1175. {
  1176. return UtDupStringA(szDumpBadPtr);
  1177. }
  1178. hresult = pEMFO->Dump(&pszDump, ulFlag, nIndentLevel);
  1179. if (hresult != NOERROR)
  1180. {
  1181. CoTaskMemFree(pszDump);
  1182. return DumpHRESULT(hresult);
  1183. }
  1184. return pszDump;
  1185. }
  1186. #endif // _DEBUG
  1187. //+-------------------------------------------------------------------------
  1188. //
  1189. // Function: UtGetHEMFFromEMFStm
  1190. //
  1191. // Synopsis: Reads an enhanced metafile from a stream into memory,
  1192. // creates the enhanced metafile from the raw data, and
  1193. // returns a handle to it.
  1194. //
  1195. // Arguments: [lpstream] -- stream containing the EMF
  1196. // [dwSize] -- data size within stream
  1197. // [fConvert] -- FALSE for metafile, TRUE for PICT
  1198. //
  1199. // Requires: lpstream positioned at start of data
  1200. //
  1201. // Returns: HRESULT
  1202. //
  1203. // History: 15-May-94 DavePl Created
  1204. //
  1205. //--------------------------------------------------------------------------
  1206. FARINTERNAL UtGetHEMFFromEMFStm(LPSTREAM lpstream,
  1207. DWORD * pdwSize,
  1208. HENHMETAFILE * lphPres)
  1209. {
  1210. VDATEHEAP();
  1211. BYTE *pbEMFData = NULL;
  1212. HRESULT hr = NOERROR;
  1213. // initialize this in case of error return
  1214. *lphPres = NULL;
  1215. // allocate a global handle for the data
  1216. pbEMFData = (BYTE *) GlobalAlloc(GMEM_FIXED, *pdwSize);
  1217. if (NULL == pbEMFData)
  1218. {
  1219. return E_OUTOFMEMORY;
  1220. }
  1221. // read the stream into the bit storage
  1222. hr = StRead(lpstream, pbEMFData, *pdwSize);
  1223. if (FAILED(hr))
  1224. {
  1225. LEVERIFY( NULL == GlobalFree((HGLOBAL) pbEMFData) );
  1226. return hr;
  1227. }
  1228. // Create an in-memory EMF based on the raw bits
  1229. HDC hdcTemp = CreateCompatibleDC(NULL);
  1230. if (NULL == hdcTemp)
  1231. {
  1232. LEVERIFY( NULL == GlobalFree((HGLOBAL) pbEMFData) );
  1233. return E_FAIL;
  1234. }
  1235. *lphPres = SetWinMetaFileBits(*pdwSize, pbEMFData, hdcTemp, NULL);
  1236. LEVERIFY( DeleteDC(hdcTemp) );
  1237. // In any case, we can free the bit buffer
  1238. LEVERIFY( NULL == GlobalFree((HGLOBAL) pbEMFData) );
  1239. // If the SetEnhM... failed, set the error code
  1240. if (*lphPres == NULL)
  1241. {
  1242. hr = HRESULT_FROM_WIN32(GetLastError());
  1243. }
  1244. // We need to update the size of the in-memory EMF, as it
  1245. // could differ from out persistent MF form.
  1246. *pdwSize = GetEnhMetaFileBits(*lphPres, NULL, NULL);
  1247. if (0 == *pdwSize)
  1248. {
  1249. hr = HRESULT_FROM_WIN32(GetLastError());
  1250. }
  1251. return hr;
  1252. }
  1253. //+-------------------------------------------------------------------------
  1254. //
  1255. // Function: UtHEMFToEMFStm
  1256. //
  1257. // Synopsis: Takes a handle to an enhanced metafile and serializes it
  1258. // to the supplied stream. It can be serialized as either
  1259. // a standard or enhanced metafile.
  1260. //
  1261. // Arguments: [lphEMF] -- ptr to the EMF handle
  1262. // [dwSize] -- size of the EMF bits
  1263. // [lpstream] -- the stream to write to
  1264. // [fWriteAsWMF] -- write as WMF, not EMF
  1265. //
  1266. // Returns: HRESULT
  1267. //
  1268. // History: 15-May-94 DavePl Created
  1269. //
  1270. // Notes: This fn is used to serialize EMFs as MFs in the cache node
  1271. // save case, which will allow 16-bit DLLs to read them back.
  1272. // A EMF converted to MF contains the original EMF as an
  1273. // embedded comment record, so no loss is taken in the
  1274. // EMF -> MF -> EMF conversion case.
  1275. //
  1276. // The incoming dwSize must be large enough to accomodate the
  1277. // WMF (w/embedded EMF) in the standard metafile save case.
  1278. //
  1279. //--------------------------------------------------------------------------
  1280. FARINTERNAL UtHEMFToEMFStm(HENHMETAFILE hEMF,
  1281. DWORD dwSize,
  1282. LPSTREAM lpstream,
  1283. EMFWRITETYPE emfwType
  1284. )
  1285. {
  1286. VDATEHEAP();
  1287. HRESULT hr;
  1288. Assert(emfwType == WRITE_AS_EMF || emfwType == WRITE_AS_WMF);
  1289. // If we don't have a handle, there's nothing to do.
  1290. if (hEMF == NULL)
  1291. {
  1292. return OLE_E_BLANK;
  1293. }
  1294. void *lpBits;
  1295. lpBits = PrivMemAlloc(dwSize);
  1296. if (NULL == lpBits)
  1297. {
  1298. return E_OUTOFMEMORY;
  1299. }
  1300. if (emfwType == WRITE_AS_WMF)
  1301. {
  1302. // WMF WRITE CASE
  1303. // Get the raw bits of the metafile that we are going to
  1304. // write out
  1305. HDC hdcTemp = CreateCompatibleDC(NULL);
  1306. if (NULL == hdcTemp)
  1307. {
  1308. hr = E_FAIL;
  1309. goto errRtn;
  1310. }
  1311. if (0 == GetWinMetaFileBits(hEMF, dwSize, (BYTE *) lpBits, MM_ANISOTROPIC, hdcTemp))
  1312. {
  1313. hr = HRESULT_FROM_WIN32(GetLastError());
  1314. LEVERIFY( DeleteDC(hdcTemp) );
  1315. goto errRtn;
  1316. }
  1317. LEVERIFY( DeleteDC(hdcTemp) );
  1318. // write the metafile bits out to the stream
  1319. }
  1320. else
  1321. {
  1322. // EMF WRITE CASE
  1323. if (0 == GetEnhMetaFileBits(hEMF, dwSize, (BYTE *) lpBits))
  1324. {
  1325. hr = HRESULT_FROM_WIN32(GetLastError());
  1326. goto errRtn;
  1327. }
  1328. }
  1329. hr = StWrite(lpstream, lpBits, dwSize);
  1330. errRtn:
  1331. // free the metafile bits
  1332. PrivMemFree(lpBits);
  1333. // set the stream size
  1334. if (SUCCEEDED(hr))
  1335. {
  1336. hr = StSetSize(lpstream, 0, TRUE);
  1337. }
  1338. return hr;
  1339. }
  1340. //+-------------------------------------------------------------------------
  1341. //
  1342. // Function: UtGetHEMFFromContentsStm
  1343. //
  1344. // Synopsis: Pulls EMF data from a stream and creates a handle to
  1345. // the resultant in-memory EMF
  1346. //
  1347. // Arguments: [pstm] -- the stream to read from
  1348. // [phdata] -- the handle to create on
  1349. //
  1350. // Returns: (void)
  1351. //
  1352. // History: 10-Jul-94 DavePl Created
  1353. //
  1354. //
  1355. //--------------------------------------------------------------------------
  1356. void UtGetHEMFFromContentsStm(LPSTREAM pstm, HANDLE * phdata)
  1357. {
  1358. *phdata = NULL;
  1359. DWORD dwSize;
  1360. ENHMETAHEADER * pHdr;
  1361. // Pull the size of the metafile header from the stream
  1362. if (FAILED(StRead(pstm, &dwSize, sizeof(DWORD))))
  1363. {
  1364. return;
  1365. }
  1366. // The header must be at least as large as the byte
  1367. // offset to the nBytes member of the ENHMETAHEADER struct.
  1368. if (dwSize < offsetof(ENHMETAHEADER, nBytes))
  1369. {
  1370. return;
  1371. }
  1372. // Allocate enough memory for the header struct
  1373. pHdr = (ENHMETAHEADER *) PrivMemAlloc(dwSize);
  1374. if (NULL == pHdr)
  1375. {
  1376. return;
  1377. }
  1378. // Read the header structure into our buffer
  1379. if (FAILED(StRead(pstm, pHdr, dwSize)))
  1380. {
  1381. PrivMemFree(pHdr);
  1382. return;
  1383. }
  1384. // All we care about in the header is the size of the
  1385. // metafile bits, so cache that and free the header buffer
  1386. dwSize = pHdr->nBytes;
  1387. PrivMemFree(pHdr);
  1388. // Allocate memory to read the raw EMF bits into
  1389. BYTE * lpBytes = (BYTE *) PrivMemAlloc(dwSize);
  1390. if (NULL == lpBytes)
  1391. {
  1392. return;
  1393. }
  1394. // Read the raw bits into the buffer...
  1395. if (FAILED(StRead(pstm, lpBytes, dwSize)))
  1396. {
  1397. PrivMemFree(lpBytes);
  1398. return;
  1399. }
  1400. // Create an in-memory EMF based on those bits
  1401. HENHMETAFILE hEmf = SetEnhMetaFileBits(dwSize, lpBytes);
  1402. PrivMemFree(lpBytes);
  1403. if (NULL == hEmf)
  1404. {
  1405. return;
  1406. }
  1407. *phdata = hEmf;
  1408. return;
  1409. }