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.

1367 lines
38 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File:
  4. // convert.cpp
  5. //
  6. // Contents:
  7. // This module contains the code to read/write DIB, metafile,
  8. // placeable metafiles, olepres stream, etc... This module also
  9. // contains routines for converting from one format to other.
  10. //
  11. // Classes:
  12. //
  13. // Functions:
  14. //
  15. // History:
  16. // 15-Feb-94 alexgo fixed a bug in loading placeable metafiles
  17. // from a storage (incorrect size calculation).
  18. // 25-Jan-94 alexgo first pass at converting to Cairo-style
  19. // memory allocations.
  20. // 01/11/93 - alexgo - added VDATEHEAP macros to every function
  21. // 12/08/93 - ChrisWe - fixed wPrepareBitmapHeader not to use
  22. // (LPOLESTR) cast
  23. // 12/07/93 - ChrisWe - make default params to StSetSize explicit
  24. // 12/02/93 - ChrisWe - more formatting; fixed UtHMFToMFStm,
  25. // 32 bit version, which was doing questionable things
  26. // with the hBits handle; got rid of the OLESTR
  27. // uses in favor of (void *) or (BYTE *) as appropriate
  28. // 11/29/93 - ChrisWe - move CONVERT_SOURCEISICON, returned
  29. // by UtOlePresStmToContentsStm(), to utils.h
  30. // 11/28/93 - ChrisWe - begin file inspection and cleanup
  31. // 06/28/93 - SriniK - created
  32. //
  33. //-----------------------------------------------------------------------------
  34. #include <le2int.h>
  35. #pragma SEG(ole2)
  36. NAME_SEG(convert)
  37. ASSERTDATA
  38. #ifndef _MAC
  39. FARINTERNAL_(HMETAFILE) QD2GDI(HANDLE hBits);
  40. #endif
  41. void UtGetHEMFFromContentsStm(LPSTREAM lpstm, HANDLE * phdata);
  42. /************************ FILE FORMATS **********************************
  43. Normal Metafile (memory or disk based):
  44. ------------ ---------------
  45. | METAHEADER | Metafile bits |
  46. ------------ ---------------
  47. Placeable Metafile:
  48. --------------------- -----------------
  49. | PLACEABLEMETAHEADER | Normal metafile |
  50. --------------------- -----------------
  51. Memory Based DIB:
  52. ------------------ --------------- ----------
  53. | BITMAPINFOHEADER | RGBQUAD array | DIB bits |
  54. ------------------ --------------- ----------
  55. DIB file format:
  56. ------------------ ------------------
  57. | BITMAPFILEHEADER | Memory based DIB |
  58. ------------------ ------------------
  59. Ole10NativeStream Format:
  60. -------- ----------------------
  61. | dwSize | Object's Native data |
  62. -------- ----------------------
  63. PBrush Native data format:
  64. -----------------
  65. | Dib File format |
  66. -----------------
  67. MSDraw Native data format:
  68. --------------------- ------------- ------------- -----------------
  69. | mapping mode (WORD) | xExt (WORD) | yExt (WORD) | Normal metafile |
  70. --------------------- ------------- ------------- -----------------
  71. *****************************************************************************/
  72. FARINTERNAL UtGetHGLOBALFromStm(LPSTREAM lpstream, DWORD dwSize,
  73. HANDLE FAR* lphPres)
  74. {
  75. VDATEHEAP();
  76. HANDLE hBits = NULL;
  77. void FAR *lpBits = NULL;
  78. HRESULT error;
  79. // initialize this for error return cases
  80. *lphPres = NULL;
  81. // allocate a new handle
  82. if (!(hBits = GlobalAlloc(GMEM_MOVEABLE, dwSize))
  83. || !(lpBits = (BYTE *)GlobalLock(hBits)))
  84. {
  85. error = ResultFromScode(E_OUTOFMEMORY);
  86. goto errRtn;
  87. }
  88. // read the stream into the allocated memory
  89. if (error = StRead(lpstream, lpBits, dwSize))
  90. goto errRtn;
  91. // if we got this far, return new handle
  92. *lphPres = hBits;
  93. errRtn:
  94. // unlock the handle, if it was successfully locked
  95. if (lpBits)
  96. GlobalUnlock(hBits);
  97. // free the handle if there was an error
  98. if ((error != NOERROR) && hBits)
  99. GlobalFree(hBits);
  100. return(error);
  101. }
  102. #ifndef _MAC
  103. FARINTERNAL UtGetHDIBFromDIBFileStm(LPSTREAM pstm, HANDLE FAR* lphdata)
  104. {
  105. VDATEHEAP();
  106. BITMAPFILEHEADER bfh;
  107. DWORD dwSize; // the size of the data to read
  108. HRESULT error;
  109. // read the bitmap file header
  110. if (error = pstm->Read(&bfh, sizeof(BITMAPFILEHEADER), NULL))
  111. {
  112. *lphdata = NULL;
  113. return(error);
  114. }
  115. // calculate the size of the DIB to read
  116. dwSize = bfh.bfSize - sizeof(BITMAPFILEHEADER);
  117. // read the DIB
  118. return(UtGetHGLOBALFromStm(pstm, dwSize, lphdata));
  119. }
  120. FARINTERNAL_(HANDLE) UtGetHMFPICT(HMETAFILE hMF, BOOL fDeleteOnError,
  121. DWORD xExt, DWORD yExt)
  122. {
  123. VDATEHEAP();
  124. HANDLE hmfp; // handle to the new METAFILEPICT
  125. LPMETAFILEPICT lpmfp; // pointer to the new METAFILEPICT
  126. // if no METAFILE, nothing to do
  127. if (hMF == NULL)
  128. return(NULL);
  129. // allocate a new handle
  130. if (!(hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT))))
  131. goto errRtn;
  132. // lock the handle
  133. if (!(lpmfp = (LPMETAFILEPICT)GlobalLock(hmfp)))
  134. goto errRtn;
  135. // make the METAFILEPICT
  136. lpmfp->hMF = hMF;
  137. lpmfp->xExt = (int)xExt;
  138. lpmfp->yExt = (int)yExt;
  139. lpmfp->mm = MM_ANISOTROPIC;
  140. GlobalUnlock(hmfp);
  141. return(hmfp);
  142. errRtn:
  143. if (hmfp)
  144. GlobalFree(hmfp);
  145. if (fDeleteOnError)
  146. DeleteMetaFile(hMF);
  147. return(NULL);
  148. }
  149. #endif // _MAC
  150. //+-------------------------------------------------------------------------
  151. //
  152. // Function: UtGetHMFFromMFStm
  153. //
  154. // Synopsis:
  155. //
  156. // Effects:
  157. //
  158. // Arguments: [lpstream] -- stream containing metafile or PICT
  159. // [dwSize] -- data size within stream
  160. // [fConvert] -- FALSE for metafile, TRUE for PICT
  161. // [lphPres] -- placeholder for output metafile
  162. //
  163. // Requires: lpstream positioned at start of data
  164. //
  165. // Returns: HRESULT
  166. //
  167. // Modifies:
  168. //
  169. // Algorithm:
  170. //
  171. // History: 29-Apr-94 AlexT Add comment block, enabled Mac conversion
  172. //
  173. // Notes:
  174. //
  175. //--------------------------------------------------------------------------
  176. FARINTERNAL UtGetHMFFromMFStm(LPSTREAM lpstream, DWORD dwSize,
  177. BOOL fConvert, HANDLE FAR* lphPres)
  178. {
  179. #ifdef WIN32
  180. LEDebugOut((DEB_ITRACE, "%p _IN UtGetHMFFromMFStm (%p, %d, %d, %p)\n",
  181. NULL, lpstream, dwSize, fConvert, lphPres));
  182. VDATEHEAP();
  183. BYTE *pbMFData = NULL;
  184. METAHEADER MetaHdr;
  185. HRESULT hrError;
  186. // initialize this in case of error return
  187. *lphPres = NULL;
  188. // allocate a global handle for the data (since QD2GDI needs a
  189. // handle)
  190. pbMFData = (BYTE *) GlobalAlloc(GMEM_FIXED, dwSize);
  191. if (NULL == pbMFData)
  192. {
  193. hrError = ResultFromScode(E_OUTOFMEMORY);
  194. goto errRtn;
  195. }
  196. // read the stream into the bit storage
  197. ULONG cbRead;
  198. hrError = lpstream->Read(pbMFData, dwSize, &cbRead);
  199. if (FAILED(hrError))
  200. {
  201. return(hrError);
  202. }
  203. // As TOC is being written at the end of presentation, it is essential
  204. // to place the seek pointer at the end of presentation data. Hence,
  205. // seek past the extra meta header written by UtHMFToMFStm ignoring error
  206. lpstream->Read(&MetaHdr, sizeof(MetaHdr), NULL);
  207. // hrError = StRead(lpstream, pbMFData, dwSize);
  208. if (hrError != NOERROR)
  209. {
  210. goto errRtn;
  211. }
  212. if (fConvert)
  213. {
  214. // It's a Mac PICT
  215. *lphPres = QD2GDI((HGLOBAL) pbMFData);
  216. }
  217. else
  218. {
  219. // It's a Windows metafile
  220. *lphPres = SetMetaFileBitsEx(dwSize, pbMFData);
  221. }
  222. if (*lphPres == NULL)
  223. hrError = ResultFromScode(E_OUTOFMEMORY);
  224. errRtn:
  225. if (NULL != pbMFData)
  226. {
  227. GlobalFree(pbMFData);
  228. }
  229. LEDebugOut((DEB_ITRACE, "%p OUT UtGetHMFFromMFStm ( %lx ) [ %p ]\n",
  230. NULL, hrError, *lphPres));
  231. return(hrError);
  232. #else
  233. HANDLE hBits; // handle to the new METAFILE
  234. void FAR* lpBits = NULL;
  235. HRESULT error;
  236. // initialize this in case of error return
  237. *lphPres = NULL;
  238. // allocate a new handle, and lock the bits
  239. if (!(hBits = GlobalAlloc(GMEM_MOVEABLE, dwSize))
  240. || !(lpBits = GlobalLock(hBits)))
  241. {
  242. error = ResultFromScode(E_OUTOFMEMORY);
  243. goto errRtn;
  244. }
  245. // read the stream into the bit storage
  246. error = StRead(lpstream, lpBits, dwSize);
  247. GlobalUnlock(hBits);
  248. if (error)
  249. goto errRtn;
  250. if (!fConvert)
  251. *lphPres = SetMetaFileBits(hBits);
  252. else
  253. {
  254. if (*lphPres = QD2GDI(hBits))
  255. {
  256. // Need to free this handle upon success
  257. GlobalFree(hBits);
  258. hBits = NULL;
  259. }
  260. }
  261. if (!*lphPres)
  262. error = ResultFromScode(E_OUTOFMEMORY);
  263. errRtn:
  264. if (error && hBits)
  265. GlobalFree(hBits);
  266. return(error);
  267. #endif // WIN32
  268. }
  269. FARINTERNAL UtGetSizeAndExtentsFromPlaceableMFStm(LPSTREAM pstm,
  270. DWORD FAR* pdwSize, LONG FAR* plWidth, LONG FAR* plHeight)
  271. {
  272. VDATEHEAP();
  273. HRESULT error;
  274. LARGE_INTEGER large_int; // used to set the seek pointer
  275. ULARGE_INTEGER ularge_int; // retrieves the new seek position
  276. LONG xExt; // the x extent of the metafile
  277. LONG yExt; // the y extent of the metafile
  278. METAHEADER mfh;
  279. PLACEABLEMETAHEADER plac_mfh;
  280. // read the placeable metafile header
  281. if (error = pstm->Read(&plac_mfh, sizeof(plac_mfh), NULL))
  282. return(error);
  283. // check the magic number in the header
  284. if (plac_mfh.key != PMF_KEY)
  285. return ResultFromScode(E_FAIL);
  286. // remember the seek pointer
  287. LISet32(large_int, 0);
  288. if (error = pstm->Seek(large_int, STREAM_SEEK_CUR, &ularge_int))
  289. return(error);
  290. // read metafile header
  291. if (error = pstm->Read(&mfh, sizeof(mfh), NULL))
  292. return(error);
  293. // seek back to the begining of metafile header
  294. LISet32(large_int, ularge_int.LowPart);
  295. if (error = pstm->Seek(large_int, STREAM_SEEK_SET, NULL))
  296. return(error);
  297. // calculate the extents of the metafile
  298. xExt = (plac_mfh.bbox.right - plac_mfh.bbox.left);// metafile units
  299. yExt = (plac_mfh.bbox.bottom - plac_mfh.bbox.top);// metafile units
  300. // REVIEW, why aren't there constants for this?
  301. xExt = (xExt * 2540) / plac_mfh.inch; // HIMETRIC units
  302. yExt = (yExt * 2540) / plac_mfh.inch; // HIMETRIC units
  303. if (pdwSize)
  304. {
  305. #ifdef WIN16
  306. //this code seems to work OK on Win16
  307. *pdwSize = 2 * (mfh.mtSize + mfh.mtHeaderSize);
  308. // REVIEW NT: review METAHEADER
  309. #else //WIN32
  310. //mt.Size is the size in words of the metafile.
  311. //this fixes bug 6739 (static objects can't be copied
  312. //or loaded from a file).
  313. *pdwSize = sizeof(WORD) * mfh.mtSize;
  314. #endif //WIN16
  315. }
  316. if (plWidth)
  317. *plWidth = xExt;
  318. if (plHeight)
  319. *plHeight = yExt;
  320. return NOERROR;
  321. }
  322. FARINTERNAL UtGetHMFPICTFromPlaceableMFStm(LPSTREAM pstm, HANDLE FAR* lphdata)
  323. {
  324. VDATEHEAP();
  325. HRESULT error; // error state so far
  326. DWORD dwSize; // size of the METAFILE we have to read from the stream
  327. LONG xExt; // x extent of the METAFILE we have to read from the stream
  328. LONG yExt; // y extent of the METAFILE we have to read from the stream
  329. HMETAFILE hMF; // handle to the METAFILE read from the stream
  330. if (lphdata == NULL)
  331. return ResultFromScode(E_INVALIDARG);
  332. // initialize this in case of error return
  333. *lphdata = NULL;
  334. // get the size of the METAFILE
  335. if (error = UtGetSizeAndExtentsFromPlaceableMFStm(pstm, &dwSize,
  336. &xExt, &yExt))
  337. return(error);
  338. // fetch the METAFILE
  339. if (error = UtGetHMFFromMFStm(pstm, dwSize, FALSE /*fConvert*/,
  340. (HANDLE FAR *)&hMF))
  341. return(error);
  342. // convert to a METAFILEPICT
  343. if (!(*lphdata = UtGetHMFPICT(hMF, TRUE /*fDeleteOnError*/, xExt,
  344. yExt)))
  345. return ResultFromScode(E_OUTOFMEMORY);
  346. return NOERROR;
  347. }
  348. /****************************************************************************/
  349. /***************** Write routines *********************/
  350. /****************************************************************************/
  351. #ifndef _MAC
  352. //+----------------------------------------------------------------------------
  353. //
  354. // Function:
  355. // iFindDIBits
  356. //
  357. // Synopsis:
  358. // Returns offset from beginning of BITMAPINFOHEADER to the bits
  359. //
  360. // Arguments:
  361. // [lpbih] -- pointer to the BITMAPINFOHEADER
  362. //
  363. // History:
  364. // 09/21/98 - DavidShi
  365. //
  366. //-----------------------------------------------------------------------------
  367. FARINTERNAL_(int) iFindDIBits (LPBITMAPINFOHEADER lpbih)
  368. {
  369. int iPalSize; // size of palette info
  370. int iNumColors=0; // number of colors in DIB
  371. //
  372. // Find the number of colors
  373. //
  374. switch (lpbih->biBitCount)
  375. {
  376. case 1:
  377. iNumColors = 2;
  378. break;
  379. case 4:
  380. iNumColors = 16;
  381. break;
  382. case 8:
  383. iNumColors = 256;
  384. break;
  385. }
  386. if (lpbih->biSize >= sizeof(BITMAPINFOHEADER))
  387. {
  388. if (lpbih->biClrUsed)
  389. {
  390. iNumColors = (int)lpbih->biClrUsed;
  391. }
  392. }
  393. //
  394. // Calculate the size of the color table.
  395. //
  396. if (lpbih->biSize < sizeof(BITMAPINFOHEADER))
  397. {
  398. iPalSize = iNumColors * sizeof(RGBTRIPLE);
  399. }
  400. else if (lpbih->biCompression==BI_BITFIELDS)
  401. {
  402. if (lpbih->biSize < sizeof(BITMAPV4HEADER))
  403. {
  404. iPalSize = 3*sizeof(DWORD);
  405. }
  406. else
  407. iPalSize = 0;
  408. }
  409. else
  410. {
  411. iPalSize = iNumColors * sizeof(RGBQUAD);
  412. }
  413. return lpbih->biSize + iPalSize;
  414. }
  415. //+----------------------------------------------------------------------------
  416. //
  417. // Function:
  418. // wPrepareBitmapHeader, static
  419. //
  420. // Synopsis:
  421. // Initializes the content of a BITMAPFILEHEADER. Forces bitmap
  422. // bits to immediately follow the header.
  423. //
  424. // Arguments:
  425. // [lpbfh] -- pointer to the BITMAPFILEHEADER to initialize
  426. // [lpbih] -- pointer to DIB
  427. // [dwSize] -- the size of the file; obtained by dividing
  428. // the size of the file by 4 (see win32 documentation.)
  429. //
  430. // History:
  431. // 12/08/93 - ChrisWe - made static
  432. //
  433. //-----------------------------------------------------------------------------
  434. static INTERNAL_(void) wPrepareBitmapFileHeader(LPBITMAPFILEHEADER lpbfh,
  435. LPBITMAPINFOHEADER lpbih,
  436. DWORD dwSize )
  437. {
  438. VDATEHEAP();
  439. // NOTE THESE ARE NOT SUPPOSED TO BE UNICODE
  440. // see win32s documentation
  441. ((char *)(&lpbfh->bfType))[0] = 'B';
  442. ((char *)(&lpbfh->bfType))[1] = 'M';
  443. lpbfh->bfSize = dwSize + sizeof(BITMAPFILEHEADER);
  444. lpbfh->bfReserved1 = 0;
  445. lpbfh->bfReserved2 = 0;
  446. lpbfh->bfOffBits = sizeof(BITMAPFILEHEADER)+iFindDIBits (lpbih);
  447. }
  448. FARINTERNAL UtHDIBToDIBFileStm(HANDLE hdata, DWORD dwSize, LPSTREAM pstm)
  449. {
  450. VDATEHEAP();
  451. HRESULT error;
  452. BITMAPFILEHEADER bfh;
  453. LPBITMAPINFOHEADER pbih;
  454. if (!(pbih = (LPBITMAPINFOHEADER)GlobalLock (hdata)))
  455. return E_OUTOFMEMORY;
  456. wPrepareBitmapFileHeader(&bfh, pbih, dwSize);
  457. GlobalUnlock (hdata);
  458. if (error = pstm->Write(&bfh, sizeof(bfh), NULL))
  459. return(error);
  460. return UtHGLOBALtoStm(hdata, dwSize, pstm);
  461. }
  462. FARINTERNAL UtDIBStmToDIBFileStm(LPSTREAM pstmDIB, DWORD dwSize,
  463. LPSTREAM pstmDIBFile)
  464. {
  465. VDATEHEAP();
  466. HRESULT error;
  467. BITMAPFILEHEADER bfh;
  468. BITMAPINFOHEADER bih;
  469. ULARGE_INTEGER ularge_int; // indicates how much to copy
  470. LARGE_INTEGER large_int;
  471. error = pstmDIB->Read (&bih, sizeof(bih), NULL);
  472. LISet32(large_int, 0);
  473. wPrepareBitmapFileHeader(&bfh, &bih, dwSize);
  474. if (error = pstmDIBFile->Write(&bfh, sizeof(bfh), NULL))
  475. return(error);
  476. if (error = pstmDIBFile->Write(&bih, sizeof(bih), NULL))
  477. return(error);
  478. ULISet32(ularge_int, (dwSize - sizeof(bih)));
  479. if ((error = pstmDIB->CopyTo(pstmDIBFile, ularge_int, NULL,
  480. NULL)) == NOERROR)
  481. StSetSize(pstmDIBFile, 0, TRUE);
  482. return(error);
  483. }
  484. // REVIEW, move these to utils.h so that gen.cpp and mf.cpp can use them for
  485. // the same purposes
  486. // REVIEW, add some more comments; is HDIBFILEHDR a windows structure?
  487. struct tagHDIBFILEHDR
  488. {
  489. DWORD dwCompression;
  490. DWORD dwWidth;
  491. DWORD dwHeight;
  492. DWORD dwSize;
  493. };
  494. typedef struct tagHDIBFILEHDR HDIBFILEHDR;
  495. struct tagOLEPRESSTMHDR
  496. {
  497. DWORD dwAspect;
  498. DWORD dwLindex;
  499. DWORD dwAdvf;
  500. };
  501. typedef struct tagOLEPRESSTMHDR OLEPRESSTMHDR;
  502. FARINTERNAL UtHDIBFileToOlePresStm(HANDLE hdata, LPSTREAM pstm)
  503. {
  504. VDATEHEAP();
  505. HRESULT error;
  506. HDIBFILEHDR hdfh;
  507. LPBITMAPFILEHEADER lpbfh;
  508. LPBITMAPINFOHEADER lpbmi;
  509. if (!(lpbfh = (LPBITMAPFILEHEADER)GlobalLock(hdata)))
  510. return ResultFromScode(E_OUTOFMEMORY);
  511. lpbmi = (LPBITMAPINFOHEADER)(((BYTE *)lpbfh) +
  512. sizeof(BITMAPFILEHEADER));
  513. hdfh.dwCompression = 0;
  514. // REVIEW, these casts are hosed
  515. UtGetDibExtents(lpbmi, (LPLONG)&hdfh.dwWidth, (LPLONG)&hdfh.dwHeight);
  516. hdfh.dwSize = lpbfh->bfSize - sizeof(BITMAPFILEHEADER);
  517. // write compesssion, Width, Height, size
  518. if (error = pstm->Write(&hdfh, sizeof(hdfh), 0))
  519. goto errRtn;
  520. // write the BITMAPINFOHEADER
  521. // REVIEW, does this size include the data?
  522. if ((error = pstm->Write(lpbmi, hdfh.dwSize, NULL)) == NOERROR)
  523. StSetSize(pstm, 0, TRUE);
  524. errRtn:
  525. GlobalUnlock(hdata);
  526. return(error);
  527. }
  528. #endif // _MAC
  529. FARINTERNAL UtHMFToMFStm(HANDLE FAR* lphMF, DWORD dwSize, LPSTREAM lpstream)
  530. {
  531. VDATEHEAP();
  532. HRESULT error;
  533. // if there's no handle, there's nothing to do
  534. if (*lphMF == 0)
  535. return ResultFromScode(OLE_E_BLANK);
  536. #ifdef _MAC
  537. AssertSz(GetHandleSize((Handle)*lphMF) == dwSize,
  538. "pic hdl size not correct");
  539. HLock( (HANDLE)*lphMF );
  540. error = StWrite(lpstream, * (*lphMF), dwSize);
  541. // Eric: We should be unlocking, right?
  542. HUnlock((HANDLE)(*lphMF));
  543. if (error != NOERROR)
  544. AssertSz(0, "StWrite failure" );
  545. #else
  546. HANDLE hBits = NULL;
  547. void *lpBits;
  548. #ifdef WIN32
  549. // allocate memory to hold the METAFILE bits
  550. // Bug 18346 - OLE16 use to get the Handle size of the Metafile which was a METAHEADER bigger than the
  551. // actual Metafile. Need to write out this much more worth of data so 16 bit dlls can read the Picture.
  552. dwSize += sizeof(METAHEADER);
  553. hBits = GlobalAlloc(GPTR, dwSize);
  554. if (hBits == NULL)
  555. return ResultFromScode(E_OUTOFMEMORY);
  556. if (!(lpBits = GlobalLock(hBits)))
  557. goto errRtn;
  558. // REVIEW, shouldn't we check the returned size?
  559. // REVIEW, what should we do about enhanced metafiles? If we
  560. // convert and write those out (which have more features that 32 bit
  561. // apps might use,) then you can't read the same document on a win16
  562. // machine....
  563. GetMetaFileBitsEx((HMETAFILE)*lphMF, dwSize, lpBits);
  564. // write the metafile bits out to the stream
  565. error = StWrite(lpstream, lpBits, dwSize);
  566. GlobalUnlock(hBits);
  567. errRtn:
  568. // free the metafile bits
  569. GlobalFree(hBits);
  570. #else
  571. if (!(hBits = GetMetaFileBits(*lphMF)))
  572. {
  573. error = ResultFromScode(E_OUTOFMEMORY);
  574. goto errRtn;
  575. }
  576. if (lpBits = GlobalLock(hBits))
  577. {
  578. error = StWrite(lpstream, lpBits, dwSize);
  579. GlobalUnlock(hBits);
  580. }
  581. else
  582. error = ResultFromScode(E_OUTOFMEMORY);
  583. if (hBits)
  584. *lphMF = SetMetaFileBits(hBits);
  585. errRtn:
  586. #endif // WIN32
  587. #endif // _MAC
  588. // set the stream size
  589. if (error == NOERROR)
  590. StSetSize(lpstream, 0, TRUE);
  591. return(error);
  592. }
  593. //+----------------------------------------------------------------------------
  594. //
  595. // Function:
  596. // wPreparePlaceableMFHeader, static
  597. //
  598. // Synopsis:
  599. // Initializes a PLACEABLEMETAHEADER.
  600. //
  601. // Arguments:
  602. // [lpplac_mfh] -- pointer to the PLACEABLEMETAHEADER to initialize
  603. // [lWidth] -- Width of the metafile
  604. // REVIEW, in what units?
  605. // REVIEW, why is this not unsigned?
  606. // [lHeight] -- Height of the metafile
  607. // REVIEW, in what units?
  608. // REVIEW, why is this not unsigned?
  609. //
  610. // Notes:
  611. //
  612. // History:
  613. // 12/08/93 - ChrisWe - made static
  614. //
  615. //-----------------------------------------------------------------------------
  616. static INTERNAL_(void) wPreparePlaceableMFHeader(
  617. PLACEABLEMETAHEADER FAR* lpplac_mfh, LONG lWidth, LONG lHeight)
  618. {
  619. VDATEHEAP();
  620. WORD FAR* lpw; // roves over the words included in the checksum
  621. lpplac_mfh->key = PMF_KEY;
  622. lpplac_mfh->hmf = 0;
  623. lpplac_mfh->inch = 576; // REVIEW, where's this magic number from?
  624. lpplac_mfh->bbox.left = 0;
  625. lpplac_mfh->bbox.top = 0;
  626. lpplac_mfh->bbox.right = (int) ((lWidth * lpplac_mfh->inch) / 2540);
  627. // REVIEW, more magic
  628. lpplac_mfh->bbox.bottom = (int) ((lHeight * lpplac_mfh->inch) / 2540);
  629. // REVIEW, more magic
  630. lpplac_mfh->reserved = NULL;
  631. // Compute the checksum of the 10 words that precede the checksum field.
  632. // It is calculated by XORing zero with those 10 words.
  633. for(lpplac_mfh->checksum = 0, lpw = (WORD FAR*)lpplac_mfh;
  634. lpw < (WORD FAR*)&lpplac_mfh->checksum; ++lpw)
  635. lpplac_mfh->checksum ^= *lpw;
  636. }
  637. FARINTERNAL UtHMFToPlaceableMFStm(HANDLE FAR* lphMF, DWORD dwSize,
  638. LONG lWidth, LONG lHeight, LPSTREAM pstm)
  639. {
  640. VDATEHEAP();
  641. PLACEABLEMETAHEADER plac_mfh;
  642. HRESULT error;
  643. wPreparePlaceableMFHeader(&plac_mfh, lWidth, lHeight);
  644. // write the placeable header to the stream
  645. if (error = pstm->Write(&plac_mfh, sizeof(plac_mfh), NULL))
  646. return(error);
  647. // write the rest of the METAFILE to the stream
  648. return UtHMFToMFStm(lphMF, dwSize, pstm);
  649. }
  650. FARINTERNAL UtMFStmToPlaceableMFStm(LPSTREAM pstmMF, DWORD dwSize,
  651. LONG lWidth, LONG lHeight, LPSTREAM pstmPMF)
  652. {
  653. VDATEHEAP();
  654. PLACEABLEMETAHEADER plac_mfh;
  655. HRESULT error;
  656. ULARGE_INTEGER ularge_int; // indicates how much data to copy
  657. wPreparePlaceableMFHeader(&plac_mfh, lWidth, lHeight);
  658. // write the placeable header to the stream
  659. if (error = pstmPMF->Write(&plac_mfh, sizeof(plac_mfh), NULL))
  660. return(error);
  661. // copy the METAFILE data from one stream to the other
  662. ULISet32(ularge_int, dwSize);
  663. if ((error = pstmMF->CopyTo(pstmPMF, ularge_int, NULL, NULL)) ==
  664. NOERROR)
  665. StSetSize(pstmPMF, 0, TRUE);
  666. return(error);
  667. }
  668. //+-------------------------------------------------------------------------
  669. //
  670. // Function: UtWriteOlePresStmHeader, private
  671. //
  672. // Synopsis: Write the presentation stream header
  673. //
  674. // Effects:
  675. //
  676. // Arguments: [lpstream] -- destination stream
  677. // [pforetc] -- FORMATETC for this presentation
  678. // [dwAdvf] -- advise flags for the presentation
  679. //
  680. // Requires:
  681. //
  682. // Returns: HRESULT
  683. //
  684. // Modifies:
  685. //
  686. // Algorithm:
  687. //
  688. // History: 11-May-94 AlexT Added function header, translate to
  689. // ANSI before saving ptd
  690. //
  691. // Notes: This function can fail in low memory for presentations with
  692. // non-NULL ptds (since we allocate memory to do the conversion
  693. // to the persistent format). NtIssue #2789
  694. //
  695. //--------------------------------------------------------------------------
  696. FARINTERNAL UtWriteOlePresStmHeader(LPSTREAM lpstream, LPFORMATETC pforetc,
  697. DWORD dwAdvf)
  698. {
  699. VDATEHEAP();
  700. HRESULT error;
  701. OLEPRESSTMHDR opsh;
  702. // write clip format
  703. // REVIEW, change name of this function?
  704. if (error = WriteClipformatStm(lpstream, pforetc->cfFormat))
  705. return(error);
  706. // write target device info
  707. if (pforetc->ptd)
  708. {
  709. DVTDINFO dvtdInfo;
  710. DVTARGETDEVICE *ptdA;
  711. error = UtGetDvtd32Info(pforetc->ptd, &dvtdInfo);
  712. if (FAILED(error))
  713. {
  714. return(error);
  715. }
  716. ptdA = (DVTARGETDEVICE *) PrivMemAlloc(dvtdInfo.cbConvertSize);
  717. if (NULL == ptdA)
  718. {
  719. return(E_OUTOFMEMORY);
  720. }
  721. error = UtConvertDvtd32toDvtd16(pforetc->ptd, &dvtdInfo, ptdA);
  722. if (SUCCEEDED(error))
  723. {
  724. error = StWrite(lpstream, ptdA, ptdA->tdSize);
  725. }
  726. PrivMemFree(ptdA);
  727. if (FAILED(error))
  728. {
  729. return(error);
  730. }
  731. }
  732. else
  733. {
  734. // if ptd is null then write 4 as size.
  735. // REVIEW, what is that the sizeof()?
  736. DWORD dwNullPtdLength = 4;
  737. if (error = StWrite(lpstream, &dwNullPtdLength, sizeof(DWORD)))
  738. return(error);
  739. }
  740. opsh.dwAspect = pforetc->dwAspect;
  741. opsh.dwLindex = pforetc->lindex;
  742. opsh.dwAdvf = dwAdvf;
  743. // write DVASPECT, lindex, advise flags
  744. return StWrite(lpstream, &opsh, sizeof(opsh));
  745. }
  746. //+-------------------------------------------------------------------------
  747. //
  748. // Function: UtReadOlePresStmHeader
  749. //
  750. // Synopsis: Reads in a presentation stream header
  751. //
  752. // Arguments: [pstm] -- source stream
  753. // [pforetc] -- FORMATETC to be filled in
  754. // [pdwAdvf] -- advise flags to be filled in
  755. // [pfConvert] -- Mac conversion required, to be filled in
  756. //
  757. // Requires:
  758. //
  759. // Returns: HRESULT
  760. //
  761. // Modifies:
  762. //
  763. // Algorithm:
  764. //
  765. // History: 11-May-94 AlexT Added function header, translate ptd
  766. // from ANSI when loading
  767. //
  768. // Notes:
  769. //
  770. //--------------------------------------------------------------------------
  771. FARINTERNAL UtReadOlePresStmHeader(LPSTREAM pstm, LPFORMATETC pforetc,
  772. DWORD FAR* pdwAdvf, BOOL FAR* pfConvert)
  773. {
  774. VDATEHEAP();
  775. HRESULT error;
  776. DWORD dwRead;
  777. OLEPRESSTMHDR opsh;
  778. // initialize this for error return cases
  779. // Check for NULL ptr, as caller may not need this information
  780. if (pfConvert)
  781. {
  782. *pfConvert = FALSE;
  783. }
  784. // there's no target device information yet
  785. pforetc->ptd = NULL;
  786. // REVIEW, rename this function to indicate its origin?
  787. error = ReadClipformatStm(pstm, &dwRead);
  788. if (error == NOERROR)
  789. pforetc->cfFormat = (CLIPFORMAT)dwRead;
  790. else
  791. {
  792. #ifndef _MAC
  793. if (GetScode(error) == OLE_S_MAC_CLIPFORMAT)
  794. {
  795. // check whether the clipformat is "pict"
  796. // REVIEW, what's this cuteness?
  797. if (dwRead != *((DWORD *)"TCIP"))
  798. return(error);
  799. if (pfConvert)
  800. *pfConvert = TRUE;
  801. else
  802. return ResultFromScode(DV_E_CLIPFORMAT);
  803. pforetc->cfFormat = CF_METAFILEPICT;
  804. }
  805. else
  806. #endif
  807. return(error);
  808. }
  809. // set the proper tymed
  810. if (pforetc->cfFormat == CF_METAFILEPICT)
  811. {
  812. pforetc->tymed = TYMED_MFPICT;
  813. }
  814. else if (pforetc->cfFormat == CF_ENHMETAFILE)
  815. {
  816. pforetc->tymed = TYMED_ENHMF;
  817. }
  818. else if (pforetc->cfFormat == CF_BITMAP)
  819. {
  820. AssertSz(0, "We don't read/save CF_BITMAP anymore");
  821. return ResultFromScode(DV_E_CLIPFORMAT);
  822. }
  823. else if (pforetc->cfFormat == NULL)
  824. {
  825. pforetc->tymed = TYMED_NULL;
  826. }
  827. else
  828. {
  829. pforetc->tymed = TYMED_HGLOBAL;
  830. }
  831. // Read targetdevice info.
  832. if (error = StRead(pstm, &dwRead, sizeof(dwRead)))
  833. return(error);
  834. // if the tdSize of ptd is non-null and is > 4, then go ahead read the
  835. // remaining data of the target device info
  836. if (dwRead > 4)
  837. {
  838. DVTARGETDEVICE *ptdA;
  839. DVTDINFO dvtdInfo;
  840. ptdA = (DVTARGETDEVICE *) PrivMemAlloc(dwRead);
  841. if (NULL == ptdA)
  842. {
  843. return ResultFromScode(E_OUTOFMEMORY);
  844. }
  845. ptdA->tdSize = dwRead;
  846. error = StRead(pstm, ((BYTE*)ptdA) + sizeof(dwRead),
  847. dwRead - sizeof(dwRead));
  848. if (SUCCEEDED(error))
  849. {
  850. error = UtGetDvtd16Info(ptdA, &dvtdInfo);
  851. if (SUCCEEDED(error))
  852. {
  853. pforetc->ptd = (DVTARGETDEVICE *) PubMemAlloc(dvtdInfo.cbConvertSize);
  854. if (NULL == pforetc->ptd)
  855. {
  856. error = E_OUTOFMEMORY;
  857. }
  858. else
  859. {
  860. error = UtConvertDvtd16toDvtd32(ptdA, &dvtdInfo, pforetc->ptd);
  861. }
  862. }
  863. }
  864. PrivMemFree(ptdA);
  865. if (FAILED(error))
  866. {
  867. goto errRtn;
  868. }
  869. }
  870. else
  871. pforetc->ptd = NULL;
  872. // Read DVASPECT, lindex, advise flags
  873. if ((error = StRead(pstm, &opsh, sizeof(opsh))) != NOERROR)
  874. goto errRtn;
  875. pforetc->dwAspect = opsh.dwAspect;
  876. pforetc->lindex = opsh.dwLindex;
  877. if (pdwAdvf)
  878. *pdwAdvf = opsh.dwAdvf;
  879. return NOERROR;
  880. errRtn:
  881. if (pforetc->ptd)
  882. {
  883. PubMemFree(pforetc->ptd);
  884. pforetc->ptd = NULL;
  885. }
  886. return(error);
  887. }
  888. FARINTERNAL UtOlePresStmToContentsStm(LPSTORAGE pstg, LPOLESTR lpszPresStm,
  889. BOOL fDeletePresStm, UINT FAR* puiStatus)
  890. {
  891. VDATEHEAP();
  892. LPSTREAM pstmOlePres;
  893. LPSTREAM pstmContents = NULL;
  894. HRESULT error;
  895. FORMATETC foretc;
  896. HDIBFILEHDR hdfh;
  897. // there's no status yet
  898. *puiStatus = 0;
  899. // POSTPPC:
  900. //
  901. // This function needs to be rewritten to correctly handle the case described in
  902. // the comments below (rather than just skipping out of the function if the contents
  903. // stream already exists). The best course of action will probably be to convert
  904. // DIBs->Metafiles and Metafiles->DIBs in the needed cases.
  905. // The code inside the #ifdef below is used to determine if the contents
  906. // stream has already been created (which is the case for an object that has
  907. // been converted to a bitmap) because in the case of an object that has been
  908. // converted to a static DIB and the object has a METAFILE presentation stream
  909. // we already have a cachenode created as a DIB and we will read the contents
  910. // stream after this call to get the DIB data. However, this function sees
  911. // the metafile presentation, and converts it into the contents stream (which
  912. // when then try to load as a DIB) and bad things happen (it doesn't work). If
  913. // the stream already exists, then we bail out of this function.
  914. if (pstg->CreateStream(OLE_CONTENTS_STREAM,(STGM_READWRITE | STGM_SHARE_EXCLUSIVE), NULL,
  915. 0, &pstmContents) != NOERROR)
  916. {
  917. return NOERROR;
  918. }
  919. // created stream, it must not have existed
  920. pstmContents->Release();
  921. pstg->DestroyElement(OLE_CONTENTS_STREAM);
  922. if ((error = pstg->OpenStream(lpszPresStm, NULL,
  923. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstmOlePres)) !=
  924. NOERROR)
  925. {
  926. // we can't open the source stream
  927. *puiStatus |= CONVERT_NOSOURCE;
  928. // check whether "CONTENTS" stream exits
  929. if (pstg->OpenStream(OLE_CONTENTS_STREAM, NULL,
  930. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
  931. &pstmContents) != NOERROR)
  932. {
  933. // we can't open the destination stream either
  934. // REVIEW, since we can't open the source, who cares?
  935. // REVIEW, is there a cheaper way to test existence
  936. // other than opening?
  937. *puiStatus |= CONVERT_NODESTINATION;
  938. }
  939. else
  940. pstmContents->Release();
  941. return(error);
  942. }
  943. foretc.ptd = NULL;
  944. if (error = UtReadOlePresStmHeader(pstmOlePres, &foretc, NULL, NULL))
  945. goto errRtn;
  946. if (error = pstmOlePres->Read(&hdfh, sizeof(hdfh), 0))
  947. goto errRtn;
  948. AssertSz(hdfh.dwCompression == 0,
  949. "Non-zero compression not supported");
  950. if (error = OpenOrCreateStream(pstg, OLE_CONTENTS_STREAM,
  951. &pstmContents))
  952. {
  953. *puiStatus |= CONVERT_NODESTINATION;
  954. goto errRtn;
  955. }
  956. if (foretc.dwAspect == DVASPECT_ICON)
  957. {
  958. *puiStatus |= CONVERT_SOURCEISICON;
  959. fDeletePresStm = FALSE;
  960. error = NOERROR;
  961. goto errRtn;
  962. }
  963. if (foretc.cfFormat == CF_DIB)
  964. error = UtDIBStmToDIBFileStm(pstmOlePres, hdfh.dwSize,
  965. pstmContents);
  966. else if (foretc.cfFormat == CF_METAFILEPICT)
  967. error = UtMFStmToPlaceableMFStm(pstmOlePres,
  968. hdfh.dwSize, hdfh.dwWidth, hdfh.dwHeight,
  969. pstmContents);
  970. else
  971. error = ResultFromScode(DV_E_CLIPFORMAT);
  972. errRtn:
  973. if (pstmOlePres)
  974. pstmOlePres->Release();
  975. if (pstmContents)
  976. pstmContents->Release();
  977. if (foretc.ptd)
  978. PubMemFree(foretc.ptd);
  979. if (error == NOERROR)
  980. {
  981. if (fDeletePresStm && lpszPresStm)
  982. pstg->DestroyElement(lpszPresStm);
  983. }
  984. else
  985. {
  986. pstg->DestroyElement(OLE_CONTENTS_STREAM);
  987. }
  988. return(error);
  989. }
  990. FARINTERNAL UtOlePresStmToContentsStm(LPSTORAGE pstg, LPOLESTR lpszPresStm,
  991. LPSTREAM pstmContents, UINT FAR* puiStatus)
  992. {
  993. HRESULT error = S_OK;
  994. LPSTREAM pstmOlePres = NULL;
  995. FORMATETC foretc;
  996. HDIBFILEHDR hdfh;
  997. // there's no status yet
  998. *puiStatus = 0;
  999. if ((error = pstg->OpenStream(lpszPresStm, NULL,
  1000. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstmOlePres)) !=
  1001. NOERROR)
  1002. {
  1003. // we can't open the source stream
  1004. *puiStatus |= CONVERT_NOSOURCE;
  1005. return(error);
  1006. }
  1007. foretc.ptd = NULL;
  1008. if (error = UtReadOlePresStmHeader(pstmOlePres, &foretc, NULL, NULL))
  1009. goto errRtn;
  1010. if (error = pstmOlePres->Read(&hdfh, sizeof(hdfh), 0))
  1011. goto errRtn;
  1012. AssertSz(hdfh.dwCompression == 0,
  1013. "Non-zero compression not supported");
  1014. if (foretc.dwAspect == DVASPECT_ICON)
  1015. {
  1016. *puiStatus |= CONVERT_SOURCEISICON;
  1017. error = NOERROR;
  1018. goto errRtn;
  1019. }
  1020. if (foretc.cfFormat == CF_DIB)
  1021. error = UtDIBStmToDIBFileStm(pstmOlePres, hdfh.dwSize,
  1022. pstmContents);
  1023. else if (foretc.cfFormat == CF_METAFILEPICT)
  1024. error = UtMFStmToPlaceableMFStm(pstmOlePres,
  1025. hdfh.dwSize, hdfh.dwWidth, hdfh.dwHeight,
  1026. pstmContents);
  1027. else
  1028. error = ResultFromScode(DV_E_CLIPFORMAT);
  1029. errRtn:
  1030. if (pstmOlePres)
  1031. pstmOlePres->Release();
  1032. return error;
  1033. }
  1034. FARINTERNAL_(HANDLE) UtGetHPRESFromNative(LPSTORAGE pstg, LPSTREAM pstm, CLIPFORMAT cfFormat,
  1035. BOOL fOle10Native)
  1036. {
  1037. VDATEHEAP();
  1038. BOOL fReleaseStm = !pstm;
  1039. HGLOBAL hdata = NULL;
  1040. if ((cfFormat != CF_METAFILEPICT) &&
  1041. (cfFormat != CF_DIB) &&
  1042. (cfFormat != CF_ENHMETAFILE))
  1043. {
  1044. return(NULL);
  1045. }
  1046. if (fOle10Native)
  1047. {
  1048. DWORD dwSize;
  1049. if(!pstm)
  1050. {
  1051. if (pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
  1052. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
  1053. &pstm) != NOERROR)
  1054. return(NULL);
  1055. }
  1056. if (pstm->Read(&dwSize, sizeof(DWORD), NULL) == NOERROR)
  1057. {
  1058. // is it PBrush native data?
  1059. if (cfFormat == CF_DIB)
  1060. UtGetHDIBFromDIBFileStm(pstm, &hdata);
  1061. else
  1062. {
  1063. // MSDraw native data or PaintBrush
  1064. //
  1065. UtGetHMFPICTFromMSDrawNativeStm(pstm, dwSize,
  1066. &hdata);
  1067. }
  1068. }
  1069. }
  1070. else
  1071. {
  1072. if(!pstm)
  1073. {
  1074. if (pstg->OpenStream(OLE_CONTENTS_STREAM, NULL,
  1075. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
  1076. &pstm) != NOERROR)
  1077. return(NULL);
  1078. }
  1079. if (cfFormat == CF_DIB)
  1080. {
  1081. UtGetHDIBFromDIBFileStm(pstm, &hdata);
  1082. }
  1083. else if (cfFormat == CF_METAFILEPICT)
  1084. {
  1085. UtGetHMFPICTFromPlaceableMFStm(pstm, &hdata);
  1086. }
  1087. else
  1088. {
  1089. UtGetHEMFFromContentsStm(pstm, &hdata);
  1090. }
  1091. }
  1092. if(fReleaseStm)
  1093. pstm->Release();
  1094. return(hdata);
  1095. }