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.

1370 lines
40 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. {
  558. error = HRESULT_FROM_WIN32(GetLastError());
  559. goto errRtn;
  560. }
  561. // REVIEW, shouldn't we check the returned size?
  562. // REVIEW, what should we do about enhanced metafiles? If we
  563. // convert and write those out (which have more features that 32 bit
  564. // apps might use,) then you can't read the same document on a win16
  565. // machine....
  566. GetMetaFileBitsEx((HMETAFILE)*lphMF, dwSize, lpBits);
  567. // write the metafile bits out to the stream
  568. error = StWrite(lpstream, lpBits, dwSize);
  569. GlobalUnlock(hBits);
  570. errRtn:
  571. // free the metafile bits
  572. GlobalFree(hBits);
  573. #else
  574. if (!(hBits = GetMetaFileBits(*lphMF)))
  575. {
  576. error = ResultFromScode(E_OUTOFMEMORY);
  577. goto errRtn;
  578. }
  579. if (lpBits = GlobalLock(hBits))
  580. {
  581. error = StWrite(lpstream, lpBits, dwSize);
  582. GlobalUnlock(hBits);
  583. }
  584. else
  585. error = ResultFromScode(E_OUTOFMEMORY);
  586. if (hBits)
  587. *lphMF = SetMetaFileBits(hBits);
  588. errRtn:
  589. #endif // WIN32
  590. #endif // _MAC
  591. // set the stream size
  592. if (error == NOERROR)
  593. StSetSize(lpstream, 0, TRUE);
  594. return(error);
  595. }
  596. //+----------------------------------------------------------------------------
  597. //
  598. // Function:
  599. // wPreparePlaceableMFHeader, static
  600. //
  601. // Synopsis:
  602. // Initializes a PLACEABLEMETAHEADER.
  603. //
  604. // Arguments:
  605. // [lpplac_mfh] -- pointer to the PLACEABLEMETAHEADER to initialize
  606. // [lWidth] -- Width of the metafile
  607. // REVIEW, in what units?
  608. // REVIEW, why is this not unsigned?
  609. // [lHeight] -- Height of the metafile
  610. // REVIEW, in what units?
  611. // REVIEW, why is this not unsigned?
  612. //
  613. // Notes:
  614. //
  615. // History:
  616. // 12/08/93 - ChrisWe - made static
  617. //
  618. //-----------------------------------------------------------------------------
  619. static INTERNAL_(void) wPreparePlaceableMFHeader(
  620. PLACEABLEMETAHEADER FAR* lpplac_mfh, LONG lWidth, LONG lHeight)
  621. {
  622. VDATEHEAP();
  623. WORD FAR* lpw; // roves over the words included in the checksum
  624. lpplac_mfh->key = PMF_KEY;
  625. lpplac_mfh->hmf = 0;
  626. lpplac_mfh->inch = 576; // REVIEW, where's this magic number from?
  627. lpplac_mfh->bbox.left = 0;
  628. lpplac_mfh->bbox.top = 0;
  629. lpplac_mfh->bbox.right = (WORD) (lWidth * lpplac_mfh->inch) / 2540;
  630. // REVIEW, more magic
  631. lpplac_mfh->bbox.bottom = (WORD) (lHeight * lpplac_mfh->inch) / 2540;
  632. // REVIEW, more magic
  633. lpplac_mfh->reserved = NULL;
  634. // Compute the checksum of the 10 words that precede the checksum field.
  635. // It is calculated by XORing zero with those 10 words.
  636. for(lpplac_mfh->checksum = 0, lpw = (WORD FAR*)lpplac_mfh;
  637. lpw < (WORD FAR*)&lpplac_mfh->checksum; ++lpw)
  638. lpplac_mfh->checksum ^= *lpw;
  639. }
  640. FARINTERNAL UtHMFToPlaceableMFStm(HANDLE FAR* lphMF, DWORD dwSize,
  641. LONG lWidth, LONG lHeight, LPSTREAM pstm)
  642. {
  643. VDATEHEAP();
  644. PLACEABLEMETAHEADER plac_mfh;
  645. HRESULT error;
  646. wPreparePlaceableMFHeader(&plac_mfh, lWidth, lHeight);
  647. // write the placeable header to the stream
  648. if (error = pstm->Write(&plac_mfh, sizeof(plac_mfh), NULL))
  649. return(error);
  650. // write the rest of the METAFILE to the stream
  651. return UtHMFToMFStm(lphMF, dwSize, pstm);
  652. }
  653. FARINTERNAL UtMFStmToPlaceableMFStm(LPSTREAM pstmMF, DWORD dwSize,
  654. LONG lWidth, LONG lHeight, LPSTREAM pstmPMF)
  655. {
  656. VDATEHEAP();
  657. PLACEABLEMETAHEADER plac_mfh;
  658. HRESULT error;
  659. ULARGE_INTEGER ularge_int; // indicates how much data to copy
  660. wPreparePlaceableMFHeader(&plac_mfh, lWidth, lHeight);
  661. // write the placeable header to the stream
  662. if (error = pstmPMF->Write(&plac_mfh, sizeof(plac_mfh), NULL))
  663. return(error);
  664. // copy the METAFILE data from one stream to the other
  665. ULISet32(ularge_int, dwSize);
  666. if ((error = pstmMF->CopyTo(pstmPMF, ularge_int, NULL, NULL)) ==
  667. NOERROR)
  668. StSetSize(pstmPMF, 0, TRUE);
  669. return(error);
  670. }
  671. //+-------------------------------------------------------------------------
  672. //
  673. // Function: UtWriteOlePresStmHeader, private
  674. //
  675. // Synopsis: Write the presentation stream header
  676. //
  677. // Effects:
  678. //
  679. // Arguments: [lpstream] -- destination stream
  680. // [pforetc] -- FORMATETC for this presentation
  681. // [dwAdvf] -- advise flags for the presentation
  682. //
  683. // Requires:
  684. //
  685. // Returns: HRESULT
  686. //
  687. // Modifies:
  688. //
  689. // Algorithm:
  690. //
  691. // History: 11-May-94 AlexT Added function header, translate to
  692. // ANSI before saving ptd
  693. //
  694. // Notes: This function can fail in low memory for presentations with
  695. // non-NULL ptds (since we allocate memory to do the conversion
  696. // to the persistent format). NtIssue #2789
  697. //
  698. //--------------------------------------------------------------------------
  699. FARINTERNAL UtWriteOlePresStmHeader(LPSTREAM lpstream, LPFORMATETC pforetc,
  700. DWORD dwAdvf)
  701. {
  702. VDATEHEAP();
  703. HRESULT error;
  704. OLEPRESSTMHDR opsh;
  705. // write clip format
  706. // REVIEW, change name of this function?
  707. if (error = WriteClipformatStm(lpstream, pforetc->cfFormat))
  708. return(error);
  709. // write target device info
  710. if (pforetc->ptd)
  711. {
  712. DVTDINFO dvtdInfo;
  713. DVTARGETDEVICE *ptdA;
  714. error = UtGetDvtd32Info(pforetc->ptd, &dvtdInfo);
  715. if (FAILED(error))
  716. {
  717. return(error);
  718. }
  719. ptdA = (DVTARGETDEVICE *) PrivMemAlloc(dvtdInfo.cbConvertSize);
  720. if (NULL == ptdA)
  721. {
  722. return(E_OUTOFMEMORY);
  723. }
  724. error = UtConvertDvtd32toDvtd16(pforetc->ptd, &dvtdInfo, ptdA);
  725. if (SUCCEEDED(error))
  726. {
  727. error = StWrite(lpstream, ptdA, ptdA->tdSize);
  728. }
  729. PrivMemFree(ptdA);
  730. if (FAILED(error))
  731. {
  732. return(error);
  733. }
  734. }
  735. else
  736. {
  737. // if ptd is null then write 4 as size.
  738. // REVIEW, what is that the sizeof()?
  739. DWORD dwNullPtdLength = 4;
  740. if (error = StWrite(lpstream, &dwNullPtdLength, sizeof(DWORD)))
  741. return(error);
  742. }
  743. opsh.dwAspect = pforetc->dwAspect;
  744. opsh.dwLindex = pforetc->lindex;
  745. opsh.dwAdvf = dwAdvf;
  746. // write DVASPECT, lindex, advise flags
  747. return StWrite(lpstream, &opsh, sizeof(opsh));
  748. }
  749. //+-------------------------------------------------------------------------
  750. //
  751. // Function: UtReadOlePresStmHeader
  752. //
  753. // Synopsis: Reads in a presentation stream header
  754. //
  755. // Arguments: [pstm] -- source stream
  756. // [pforetc] -- FORMATETC to be filled in
  757. // [pdwAdvf] -- advise flags to be filled in
  758. // [pfConvert] -- Mac conversion required, to be filled in
  759. //
  760. // Requires:
  761. //
  762. // Returns: HRESULT
  763. //
  764. // Modifies:
  765. //
  766. // Algorithm:
  767. //
  768. // History: 11-May-94 AlexT Added function header, translate ptd
  769. // from ANSI when loading
  770. //
  771. // Notes:
  772. //
  773. //--------------------------------------------------------------------------
  774. FARINTERNAL UtReadOlePresStmHeader(LPSTREAM pstm, LPFORMATETC pforetc,
  775. DWORD FAR* pdwAdvf, BOOL FAR* pfConvert)
  776. {
  777. VDATEHEAP();
  778. HRESULT error;
  779. DWORD dwRead;
  780. OLEPRESSTMHDR opsh;
  781. // initialize this for error return cases
  782. // Check for NULL ptr, as caller may not need this information
  783. if (pfConvert)
  784. {
  785. *pfConvert = FALSE;
  786. }
  787. // there's no target device information yet
  788. pforetc->ptd = NULL;
  789. // REVIEW, rename this function to indicate its origin?
  790. error = ReadClipformatStm(pstm, &dwRead);
  791. if (error == NOERROR)
  792. pforetc->cfFormat = (CLIPFORMAT)dwRead;
  793. else
  794. {
  795. #ifndef _MAC
  796. if (GetScode(error) == OLE_S_MAC_CLIPFORMAT)
  797. {
  798. // check whether the clipformat is "pict"
  799. // REVIEW, what's this cuteness?
  800. if (dwRead != *((DWORD *)"TCIP"))
  801. return(error);
  802. if (pfConvert)
  803. *pfConvert = TRUE;
  804. else
  805. return ResultFromScode(DV_E_CLIPFORMAT);
  806. pforetc->cfFormat = CF_METAFILEPICT;
  807. }
  808. else
  809. #endif
  810. return(error);
  811. }
  812. // set the proper tymed
  813. if (pforetc->cfFormat == CF_METAFILEPICT)
  814. {
  815. pforetc->tymed = TYMED_MFPICT;
  816. }
  817. else if (pforetc->cfFormat == CF_ENHMETAFILE)
  818. {
  819. pforetc->tymed = TYMED_ENHMF;
  820. }
  821. else if (pforetc->cfFormat == CF_BITMAP)
  822. {
  823. AssertSz(0, "We don't read/save CF_BITMAP anymore");
  824. return ResultFromScode(DV_E_CLIPFORMAT);
  825. }
  826. else if (pforetc->cfFormat == NULL)
  827. {
  828. pforetc->tymed = TYMED_NULL;
  829. }
  830. else
  831. {
  832. pforetc->tymed = TYMED_HGLOBAL;
  833. }
  834. // Read targetdevice info.
  835. if (error = StRead(pstm, &dwRead, sizeof(dwRead)))
  836. return(error);
  837. // if the tdSize of ptd is non-null and is > 4, then go ahead read the
  838. // remaining data of the target device info
  839. if (dwRead > 4)
  840. {
  841. DVTARGETDEVICE *ptdA;
  842. DVTDINFO dvtdInfo;
  843. ptdA = (DVTARGETDEVICE *) PrivMemAlloc(dwRead);
  844. if (NULL == ptdA)
  845. {
  846. return ResultFromScode(E_OUTOFMEMORY);
  847. }
  848. ptdA->tdSize = dwRead;
  849. error = StRead(pstm, ((BYTE*)ptdA) + sizeof(dwRead),
  850. dwRead - sizeof(dwRead));
  851. if (SUCCEEDED(error))
  852. {
  853. error = UtGetDvtd16Info(ptdA, &dvtdInfo);
  854. if (SUCCEEDED(error))
  855. {
  856. pforetc->ptd = (DVTARGETDEVICE *) PubMemAlloc(dvtdInfo.cbConvertSize);
  857. if (NULL == pforetc->ptd)
  858. {
  859. error = E_OUTOFMEMORY;
  860. }
  861. else
  862. {
  863. error = UtConvertDvtd16toDvtd32(ptdA, &dvtdInfo, pforetc->ptd);
  864. }
  865. }
  866. }
  867. PrivMemFree(ptdA);
  868. if (FAILED(error))
  869. {
  870. goto errRtn;
  871. }
  872. }
  873. else
  874. pforetc->ptd = NULL;
  875. // Read DVASPECT, lindex, advise flags
  876. if ((error = StRead(pstm, &opsh, sizeof(opsh))) != NOERROR)
  877. goto errRtn;
  878. pforetc->dwAspect = opsh.dwAspect;
  879. pforetc->lindex = opsh.dwLindex;
  880. if (pdwAdvf)
  881. *pdwAdvf = opsh.dwAdvf;
  882. return NOERROR;
  883. errRtn:
  884. if (pforetc->ptd)
  885. {
  886. PubMemFree(pforetc->ptd);
  887. pforetc->ptd = NULL;
  888. }
  889. return(error);
  890. }
  891. FARINTERNAL UtOlePresStmToContentsStm(LPSTORAGE pstg, LPOLESTR lpszPresStm,
  892. BOOL fDeletePresStm, UINT FAR* puiStatus)
  893. {
  894. VDATEHEAP();
  895. LPSTREAM pstmOlePres;
  896. LPSTREAM pstmContents = NULL;
  897. HRESULT error;
  898. FORMATETC foretc;
  899. HDIBFILEHDR hdfh;
  900. // there's no status yet
  901. *puiStatus = 0;
  902. // POSTPPC:
  903. //
  904. // This function needs to be rewritten to correctly handle the case described in
  905. // the comments below (rather than just skipping out of the function if the contents
  906. // stream already exists). The best course of action will probably be to convert
  907. // DIBs->Metafiles and Metafiles->DIBs in the needed cases.
  908. // The code inside the #ifdef below is used to determine if the contents
  909. // stream has already been created (which is the case for an object that has
  910. // been converted to a bitmap) because in the case of an object that has been
  911. // converted to a static DIB and the object has a METAFILE presentation stream
  912. // we already have a cachenode created as a DIB and we will read the contents
  913. // stream after this call to get the DIB data. However, this function sees
  914. // the metafile presentation, and converts it into the contents stream (which
  915. // when then try to load as a DIB) and bad things happen (it doesn't work). If
  916. // the stream already exists, then we bail out of this function.
  917. if (pstg->CreateStream(OLE_CONTENTS_STREAM,(STGM_READWRITE | STGM_SHARE_EXCLUSIVE), NULL,
  918. 0, &pstmContents) != NOERROR)
  919. {
  920. return NOERROR;
  921. }
  922. // created stream, it must not have existed
  923. pstmContents->Release();
  924. pstg->DestroyElement(OLE_CONTENTS_STREAM);
  925. if ((error = pstg->OpenStream(lpszPresStm, NULL,
  926. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstmOlePres)) !=
  927. NOERROR)
  928. {
  929. // we can't open the source stream
  930. *puiStatus |= CONVERT_NOSOURCE;
  931. // check whether "CONTENTS" stream exits
  932. if (pstg->OpenStream(OLE_CONTENTS_STREAM, NULL,
  933. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
  934. &pstmContents) != NOERROR)
  935. {
  936. // we can't open the destination stream either
  937. // REVIEW, since we can't open the source, who cares?
  938. // REVIEW, is there a cheaper way to test existence
  939. // other than opening?
  940. *puiStatus |= CONVERT_NODESTINATION;
  941. }
  942. else
  943. pstmContents->Release();
  944. return(error);
  945. }
  946. foretc.ptd = NULL;
  947. if (error = UtReadOlePresStmHeader(pstmOlePres, &foretc, NULL, NULL))
  948. goto errRtn;
  949. if (error = pstmOlePres->Read(&hdfh, sizeof(hdfh), 0))
  950. goto errRtn;
  951. AssertSz(hdfh.dwCompression == 0,
  952. "Non-zero compression not supported");
  953. if (error = OpenOrCreateStream(pstg, OLE_CONTENTS_STREAM,
  954. &pstmContents))
  955. {
  956. *puiStatus |= CONVERT_NODESTINATION;
  957. goto errRtn;
  958. }
  959. if (foretc.dwAspect == DVASPECT_ICON)
  960. {
  961. *puiStatus |= CONVERT_SOURCEISICON;
  962. fDeletePresStm = FALSE;
  963. error = NOERROR;
  964. goto errRtn;
  965. }
  966. if (foretc.cfFormat == CF_DIB)
  967. error = UtDIBStmToDIBFileStm(pstmOlePres, hdfh.dwSize,
  968. pstmContents);
  969. else if (foretc.cfFormat == CF_METAFILEPICT)
  970. error = UtMFStmToPlaceableMFStm(pstmOlePres,
  971. hdfh.dwSize, hdfh.dwWidth, hdfh.dwHeight,
  972. pstmContents);
  973. else
  974. error = ResultFromScode(DV_E_CLIPFORMAT);
  975. errRtn:
  976. if (pstmOlePres)
  977. pstmOlePres->Release();
  978. if (pstmContents)
  979. pstmContents->Release();
  980. if (foretc.ptd)
  981. PubMemFree(foretc.ptd);
  982. if (error == NOERROR)
  983. {
  984. if (fDeletePresStm && lpszPresStm)
  985. pstg->DestroyElement(lpszPresStm);
  986. }
  987. else
  988. {
  989. pstg->DestroyElement(OLE_CONTENTS_STREAM);
  990. }
  991. return(error);
  992. }
  993. FARINTERNAL UtOlePresStmToContentsStm(LPSTORAGE pstg, LPOLESTR lpszPresStm,
  994. LPSTREAM pstmContents, UINT FAR* puiStatus)
  995. {
  996. HRESULT error = S_OK;
  997. LPSTREAM pstmOlePres = NULL;
  998. FORMATETC foretc;
  999. HDIBFILEHDR hdfh;
  1000. // there's no status yet
  1001. *puiStatus = 0;
  1002. if ((error = pstg->OpenStream(lpszPresStm, NULL,
  1003. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstmOlePres)) !=
  1004. NOERROR)
  1005. {
  1006. // we can't open the source stream
  1007. *puiStatus |= CONVERT_NOSOURCE;
  1008. return(error);
  1009. }
  1010. foretc.ptd = NULL;
  1011. if (error = UtReadOlePresStmHeader(pstmOlePres, &foretc, NULL, NULL))
  1012. goto errRtn;
  1013. if (error = pstmOlePres->Read(&hdfh, sizeof(hdfh), 0))
  1014. goto errRtn;
  1015. AssertSz(hdfh.dwCompression == 0,
  1016. "Non-zero compression not supported");
  1017. if (foretc.dwAspect == DVASPECT_ICON)
  1018. {
  1019. *puiStatus |= CONVERT_SOURCEISICON;
  1020. error = NOERROR;
  1021. goto errRtn;
  1022. }
  1023. if (foretc.cfFormat == CF_DIB)
  1024. error = UtDIBStmToDIBFileStm(pstmOlePres, hdfh.dwSize,
  1025. pstmContents);
  1026. else if (foretc.cfFormat == CF_METAFILEPICT)
  1027. error = UtMFStmToPlaceableMFStm(pstmOlePres,
  1028. hdfh.dwSize, hdfh.dwWidth, hdfh.dwHeight,
  1029. pstmContents);
  1030. else
  1031. error = ResultFromScode(DV_E_CLIPFORMAT);
  1032. errRtn:
  1033. if (pstmOlePres)
  1034. pstmOlePres->Release();
  1035. return error;
  1036. }
  1037. FARINTERNAL_(HANDLE) UtGetHPRESFromNative(LPSTORAGE pstg, LPSTREAM pstm, CLIPFORMAT cfFormat,
  1038. BOOL fOle10Native)
  1039. {
  1040. VDATEHEAP();
  1041. BOOL fReleaseStm = !pstm;
  1042. HGLOBAL hdata = NULL;
  1043. if ((cfFormat != CF_METAFILEPICT) &&
  1044. (cfFormat != CF_DIB) &&
  1045. (cfFormat != CF_ENHMETAFILE))
  1046. {
  1047. return(NULL);
  1048. }
  1049. if (fOle10Native)
  1050. {
  1051. DWORD dwSize;
  1052. if(!pstm)
  1053. {
  1054. if (pstg->OpenStream(OLE10_NATIVE_STREAM, NULL,
  1055. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
  1056. &pstm) != NOERROR)
  1057. return(NULL);
  1058. }
  1059. if (pstm->Read(&dwSize, sizeof(DWORD), NULL) == NOERROR)
  1060. {
  1061. // is it PBrush native data?
  1062. if (cfFormat == CF_DIB)
  1063. UtGetHDIBFromDIBFileStm(pstm, &hdata);
  1064. else
  1065. {
  1066. // MSDraw native data or PaintBrush
  1067. //
  1068. UtGetHMFPICTFromMSDrawNativeStm(pstm, dwSize,
  1069. &hdata);
  1070. }
  1071. }
  1072. }
  1073. else
  1074. {
  1075. if(!pstm)
  1076. {
  1077. if (pstg->OpenStream(OLE_CONTENTS_STREAM, NULL,
  1078. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0,
  1079. &pstm) != NOERROR)
  1080. return(NULL);
  1081. }
  1082. if (cfFormat == CF_DIB)
  1083. {
  1084. UtGetHDIBFromDIBFileStm(pstm, &hdata);
  1085. }
  1086. else if (cfFormat == CF_METAFILEPICT)
  1087. {
  1088. UtGetHMFPICTFromPlaceableMFStm(pstm, &hdata);
  1089. }
  1090. else
  1091. {
  1092. UtGetHEMFFromContentsStm(pstm, &hdata);
  1093. }
  1094. }
  1095. if(fReleaseStm)
  1096. pstm->Release();
  1097. return(hdata);
  1098. }