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.

3365 lines
102 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: metafile.cxx
  3. *
  4. * Includes enhanced metafile API functions.
  5. *
  6. * Created: 17-July-1991 10:10:36
  7. * Author: Hock San Lee [hockl]
  8. *
  9. * Copyright (c) 1991-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #define NO_STRICT
  12. extern "C" {
  13. #if defined(_GDIPLUS_)
  14. #include <gpprefix.h>
  15. #endif
  16. #include <string.h>
  17. #include <stdio.h>
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #include <stddef.h>
  22. #include <windows.h> // GDI function declarations.
  23. #include <winspool.h>
  24. #include "nlsconv.h" // UNICODE helpers
  25. #include "firewall.h"
  26. #define __CPLUSPLUS
  27. #include <winspool.h>
  28. #include <w32gdip.h>
  29. #include "ntgdistr.h"
  30. #include "winddi.h"
  31. #include "hmgshare.h"
  32. #include "icm.h"
  33. #include "local.h" // Local object support.
  34. #include "gdiicm.h"
  35. #include "metadef.h" // Metafile record type constants.
  36. #include "metarec.h"
  37. #include "mf16.h"
  38. #include "ntgdi.h"
  39. #include "glsup.h"
  40. }
  41. #include "rectl.hxx"
  42. #include "mfdc.hxx" // Metafile DC declarations.
  43. #include "mfrec.hxx" // Metafile record class declarations.
  44. WORD GetWordCheckSum(UINT cbData, PWORD pwData);
  45. DWORD GetDWordCheckSum(UINT cbData, PDWORD pdwData);
  46. UINT InternalGetEnhMetaFileDescription(HENHMETAFILE hemf, UINT cchBuffer, LPSTR lpDescription, BOOL bUnicode);
  47. RECTL rclNull = { 0, 0, -1, -1 };
  48. RECTL rclInfinity = {NEG_INFINITY,NEG_INFINITY,POS_INFINITY,POS_INFINITY};
  49. extern XFORM xformIdentity;
  50. typedef UINT (*LPFNCONVERT) (PVOID, PBYTE, UINT, PBYTE, INT, HDC, UINT) ;
  51. extern "C" BOOL SetSizeDevice(HDC hdc, int cxVirtualDevice, int cyVirtualDevice);
  52. /******************************Public*Routine******************************\
  53. * HDC APIENTRY CreateEnhMetaFileA(
  54. * HDC hDCRef OPTIONAL,
  55. * LPSTR pszFilename OPTIONAL,
  56. * LPRECT lpRect OPTIONAL,
  57. * LPSTR lpDescription OPTIONAL);
  58. *
  59. * The CreateEnhMetaFile function creates an enhanced metafile device context.
  60. *
  61. * Client side stub. Allocates a client side LDC as well.
  62. *
  63. * Note that it calls the server only after all client side stuff has
  64. * succeeded, we don't want to ask the server to clean up.
  65. *
  66. * The LDC is actually a reference info DC for the metafile. The pmdc
  67. * in the handle table is a pointer to the metafile DC object.
  68. *
  69. * Parameter Description
  70. * lpFilename Points to the filename for the metafile. If NULL, the metafile
  71. * will be memory based with no backing store.
  72. *
  73. * Return Value
  74. * The return value identifies an enhanced metafile device context if the
  75. * function is successful. Otherwise, it is zero.
  76. *
  77. * Note that it returns a HDC, not a HENHMETAFILE!
  78. *
  79. * History:
  80. * Wed Jul 17 10:10:36 1991 -by- Hock San Lee [hockl]
  81. * Wrote it.
  82. \**************************************************************************/
  83. extern "C" HDC APIENTRY CreateEnhMetaFileA
  84. (
  85. HDC hDCRef,
  86. LPCSTR pszFilename,
  87. CONST RECT *lpRect,
  88. LPCSTR lpDescription
  89. )
  90. {
  91. UINT cch;
  92. HDC hdcRet;
  93. WCHAR awchFilename[MAX_PATH];
  94. PWCH pwchFilename = (PWCH) NULL;
  95. PWCH pwchDescription = (PWCH) NULL;
  96. if (pszFilename != (LPSTR) NULL)
  97. {
  98. cch = strlen(pszFilename) + 1;
  99. if (cch > MAX_PATH)
  100. {
  101. ERROR_ASSERT(FALSE, "CreateEnhMetaFileA filename too long");
  102. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  103. return((HDC) 0);
  104. }
  105. vToUnicodeN(pwchFilename = awchFilename, MAX_PATH, pszFilename, cch);
  106. }
  107. if (lpDescription != (LPSTR) NULL)
  108. {
  109. // Compute the length of the description string including the NULL
  110. // characters.
  111. for (cch = 0;
  112. lpDescription[cch] != (CHAR) 0 || lpDescription[cch+1] != (CHAR) 0;
  113. cch++)
  114. ; // NULL expression
  115. cch += 2;
  116. pwchDescription = (PWCH) LocalAlloc(LMEM_FIXED, cch*sizeof(WCHAR));
  117. if (pwchDescription == (PWCH) NULL)
  118. {
  119. VERIFYGDI(FALSE, "CreateEnhMetaFileA out of memory\n");
  120. return((HDC) 0);
  121. }
  122. vToUnicodeN(pwchDescription, cch, lpDescription, cch);
  123. }
  124. hdcRet = CreateEnhMetaFileW(hDCRef, pwchFilename, lpRect, pwchDescription);
  125. if (pwchDescription)
  126. {
  127. if (LocalFree((HANDLE) pwchDescription))
  128. {
  129. ASSERTGDI(FALSE, "LocalFree failed");
  130. }
  131. }
  132. return(hdcRet);
  133. }
  134. extern "C" HDC APIENTRY CreateEnhMetaFileW
  135. (
  136. HDC hDCRef,
  137. LPCWSTR pwszFilename,
  138. CONST RECT *lpRect,
  139. LPCWSTR lpDescription
  140. )
  141. {
  142. HDC hdcNew = NULL;
  143. PLDC pldc = NULL;
  144. PMDC pmdc;
  145. PUTS("CreateEnhMetaFileW\n");
  146. // Get the server to create a DC.
  147. // If hDCRef is supplied then clone it for the reference DC.
  148. // Otherwise, use the display as the reference info DC for the metafile.
  149. hdcNew = NtGdiCreateMetafileDC(hDCRef);
  150. // now create the client version
  151. if (hdcNew)
  152. {
  153. // if this fails, it deletes hdcNew
  154. pldc = pldcCreate(hdcNew,LO_METADC);
  155. }
  156. // Handle errors.
  157. if (!pldc)
  158. {
  159. ERROR_ASSERT(FALSE, "CreateEnhMetaFileW failed");
  160. return((HDC) 0);
  161. }
  162. ASSERTGDI(LO_TYPE(hdcNew) == LO_ALTDC_TYPE,"CreateEnhMetafile - invalid type\n");
  163. // Create the metafile DC object.
  164. if (!(pmdc = pmdcAllocMDC(hdcNew, pwszFilename, lpDescription, NULL)))
  165. goto CreateEnhMetaFileW_error;
  166. pldc->pvPMDC = (PVOID)pmdc;
  167. // Add the Frame Rect if one was specified; if not it will be fixed up
  168. // by CloseEnhMetaFile.
  169. if (lpRect)
  170. {
  171. if (((PERECTL) lpRect)->bEmpty())
  172. {
  173. ERROR_ASSERT(FALSE, "CreateEnhMetaFileW invalid frame rect");
  174. GdiSetLastError(ERROR_INVALID_PARAMETER);
  175. goto CreateEnhMetaFileW_error;
  176. }
  177. else
  178. pmdc->mrmf.rclFrame = *(PRECTL) lpRect;
  179. }
  180. // Enable bounds accumlation in the reference DC.
  181. (void) SetBoundsRectAlt(hdcNew, (LPRECT) NULL,
  182. (UINT) (DCB_WINDOWMGR | DCB_RESET | DCB_ENABLE));
  183. // Return the result.
  184. ASSERTGDI(hdcNew != (HDC) NULL, "CreateEnhMetaFileW: bad HDC value");
  185. return(hdcNew);
  186. // Cleanup for errors.
  187. CreateEnhMetaFileW_error:
  188. if (pmdc)
  189. {
  190. pmdc->fl |= MDC_FATALERROR;
  191. vFreeMDC(pmdc);
  192. pldc->pvPMDC = NULL;
  193. }
  194. if (!InternalDeleteDC(hdcNew, LO_METADC))
  195. {
  196. ASSERTGDI(FALSE, "InternalDeleteDC failed");
  197. }
  198. ERROR_ASSERT(FALSE, "CreateEnhMetaFileW failed");
  199. return((HDC) 0);
  200. }
  201. /******************************Public*Routine******************************\
  202. * AssociateEnhMetaFile()
  203. *
  204. * Associate an EnhMetaFile with this DC. This is similar to CreateEnhMetaFile
  205. * but in this case it just converts the dc. UnassociateEnhMetaFile must be
  206. * used on this DC before it can be deleted. CloseMetaFile can not be use.
  207. * This is currently only for use by spooled printing using enhanced metafiles.
  208. *
  209. * This is called at start doc and after each EndPage to set up the next page.
  210. *
  211. * History:
  212. * 19-Jan-1995 -by- Eric Kutter [erick]
  213. * Wrote it.
  214. \**************************************************************************/
  215. extern "C" BOOL APIENTRY AssociateEnhMetaFile(
  216. HDC hdc)
  217. {
  218. ULONG ulSrvDC;
  219. PMDC pmdc;
  220. BOOL bIcmOn = FALSE;
  221. PUTS("CreateEnhMetaFileW\n");
  222. // Get the server to create a DC.
  223. // If hDCRef is supplied then clone it for the reference DC.
  224. // Otherwise, use the display as the reference info DC for the metafile.
  225. PLDC pldc;
  226. DC_PLDC(hdc,pldc,FALSE);
  227. // Handle errors.
  228. EMFSpoolData *pEMFSpool = (EMFSpoolData *) pldc->hEMFSpool;
  229. if (pldc->iType == LO_METADC || pEMFSpool == NULL)
  230. {
  231. ERROR_ASSERT(FALSE, "CreateEnhMetaFileW failed");
  232. return(FALSE);
  233. }
  234. // Create the metafile DC object.
  235. if (!(pmdc = pmdcAllocMDC(hdc, NULL, L"Print test\0", (HANDLE) pEMFSpool)))
  236. {
  237. ERROR_ASSERT(FALSE, "CreateEnhMetaFileW failed");
  238. return(FALSE);
  239. }
  240. // Before, we switch this DC to Metafile DC, turn-off ICM.
  241. if (SetICMMode(hdc,ICM_QUERY) == ICM_ON)
  242. {
  243. SetICMMode(hdc,ICM_OFF);
  244. bIcmOn = TRUE;
  245. }
  246. MakeInfoDC(hdc,TRUE);
  247. ASSERTGDI(pldc->iType == LO_DC,"AssociateEnhMetaFile not LO_DC\n");
  248. pldc->pvPMDC = (PVOID)pmdc;
  249. pldc->iType = LO_METADC;
  250. pmdc->mrmf.rclFrame.left = 0;
  251. pmdc->mrmf.rclFrame.top = 0;
  252. pmdc->mrmf.rclFrame.right = GetDeviceCaps( hdc, HORZSIZE ) * 100;
  253. pmdc->mrmf.rclFrame.bottom = GetDeviceCaps( hdc, VERTSIZE ) * 100;
  254. // Enable bounds accumlation in the reference DC.
  255. SetBoundsRectAlt(hdc, NULL,(UINT) (DCB_WINDOWMGR | DCB_RESET | DCB_ENABLE));
  256. // if ICM is originally turned on, turn on it for LO_METADC.
  257. if (bIcmOn)
  258. {
  259. SetICMMode(hdc,ICM_ON);
  260. }
  261. // Save state of the DC in the EnhMetaFile
  262. return (PutDCStateInMetafile( hdc ));
  263. }
  264. /******************************Public*Routine******************************\
  265. * HENHMETAFILE CloseEnhMetaFile(hDC)
  266. * HDC hDC;
  267. *
  268. * The CloseEnhMetaFile function closes the enhanced metafile device context
  269. * and creates an enhanced metafile handle that can be used with other
  270. * enhanced metafile calls.
  271. *
  272. * Parameter Description
  273. * hDC Identifies the enhanced metafile device context to be closed.
  274. *
  275. * Return Value
  276. * The return value identifies the enhanced metafile if the function is
  277. * successful. Otherwise, it is 0.
  278. *
  279. * History:
  280. * Wed Jul 17 10:10:36 1991 -by- Hock San Lee [hockl]
  281. * Wrote it.
  282. \**************************************************************************/
  283. extern "C" HENHMETAFILE APIENTRY CloseEnhMetaFile(HDC hdc)
  284. {
  285. PMDC pmdc;
  286. HENHMETAFILE hemf = NULL;
  287. PUTS("CloseEnhMetaFile\n");
  288. // Validate the metafile DC handle.
  289. PLDC pldc;
  290. DC_PLDC(hdc,pldc,hemf);
  291. // Handle errors.
  292. if (pldc->iType != LO_METADC)
  293. return(hemf);
  294. // Cleanup temp brush or pen created for SetDCBrushColor and SetDCPenColor
  295. if (pldc->oldSetDCBrushColorBrush)
  296. {
  297. DeleteObject(pldc->oldSetDCBrushColorBrush);
  298. pldc->oldSetDCBrushColorBrush = 0;
  299. }
  300. if (pldc->oldSetDCPenColorPen)
  301. {
  302. DeleteObject(pldc->oldSetDCPenColorPen);
  303. pldc->oldSetDCPenColorPen = 0;
  304. }
  305. pmdc = (PMDC)pldc->pvPMDC;
  306. // If the metafile contains GL records, tell OpenGL that things are done
  307. if (pmdc->mrmf.bOpenGL)
  308. {
  309. if (!GlmfCloseMetaFile(hdc))
  310. {
  311. WARNING("GlmfCloseMetaFile failed\n");
  312. }
  313. }
  314. // Check for fatal errors.
  315. if (pmdc->bFatalError())
  316. goto CloseEnhMetaFile_cleanup;
  317. // Make sure that save and restore DCs are balanced. Always restore back to 1.
  318. // Don't need to check if it fails since not much we can do anyways. Also,
  319. // we would need to make an extra server call to see if it is already at 1.
  320. RestoreDC(hdc,1);
  321. // Write out the EOF metafile record. This would force the previous
  322. // bounds record to be commited. The EOF metafile record includes the
  323. // metafile palette if logical palettes are used.
  324. pmdc->mrmf.nPalEntries = pmdc->iPalEntries;
  325. if (!MF_EOF(hdc,pmdc->iPalEntries,pmdc->pPalEntries))
  326. goto CloseEnhMetaFile_cleanup;
  327. // Finally flush the bounds to the metafile header. We cannot flush the
  328. // bounds if we have not committed the previous bounds record yet.
  329. // Therefore, we do this after the last EMREOF record.
  330. pmdc->vFlushBounds();
  331. // If there was no initial metafile Frame defined in CreateEnhMetaFile then
  332. // the Bounds converted to 0.01 mm will be the Frame.
  333. if (((PERECTL) &pmdc->mrmf.rclFrame)->bEmpty())
  334. {
  335. pmdc->mrmf.rclFrame.left = MulDiv((int) (100 * pmdc->mrmf.rclBounds.left),
  336. (int) pmdc->mrmf.szlMillimeters.cx,
  337. (int) pmdc->mrmf.szlDevice.cx);
  338. pmdc->mrmf.rclFrame.right = MulDiv((int) (100 * pmdc->mrmf.rclBounds.right),
  339. (int) pmdc->mrmf.szlMillimeters.cx,
  340. (int) pmdc->mrmf.szlDevice.cx);
  341. pmdc->mrmf.rclFrame.top = MulDiv((int) (100 * pmdc->mrmf.rclBounds.top),
  342. (int) pmdc->mrmf.szlMillimeters.cy,
  343. (int) pmdc->mrmf.szlDevice.cy);
  344. pmdc->mrmf.rclFrame.bottom = MulDiv((int) (100 * pmdc->mrmf.rclBounds.bottom),
  345. (int) pmdc->mrmf.szlMillimeters.cy,
  346. (int) pmdc->mrmf.szlDevice.cy);
  347. }
  348. // Flush the buffer and write out the latest header record.
  349. ASSERTGDI((ULONG) pmdc->mrmf.nHandles <= pmdc->cmhe,
  350. "CloseEnhMetaFile: Bad nHandles");
  351. if (pmdc->bIsDiskFile())
  352. {
  353. ULONG nWritten ;
  354. // Flush the memory buffer.
  355. if (!pmdc->bFlush())
  356. goto CloseEnhMetaFile_cleanup;
  357. // Flush the header record.
  358. if (SetFilePointer(pmdc->hFile, 0L, (PLONG) NULL, FILE_BEGIN) != 0L)
  359. goto CloseEnhMetaFile_cleanup;
  360. if (!WriteFile(pmdc->hFile, &pmdc->mrmf, sizeof(ENHMETAHEADER),
  361. &nWritten, (LPOVERLAPPED) NULL)
  362. || nWritten != sizeof(ENHMETAHEADER))
  363. goto CloseEnhMetaFile_cleanup;
  364. // Close the file.
  365. if (!CloseHandle(pmdc->hFile))
  366. {
  367. ASSERTGDI(FALSE, "CloseHandle failed");
  368. }
  369. pmdc->hFile = INVALID_HANDLE_VALUE;
  370. }
  371. else
  372. {
  373. // Flush the header record.
  374. PENHMETAHEADER pmrmf = (PENHMETAHEADER) pmdc->GetPtr(0, sizeof(ENHMETAHEADER));
  375. if(pmrmf)
  376. {
  377. *pmrmf = pmdc->mrmf;
  378. pmdc->ReleasePtr(pmrmf);
  379. }
  380. else
  381. {
  382. WARNING("CloseEnhMetaFile() Failed to get ENHMETAHEADER pointer\n");
  383. goto CloseEnhMetaFile_cleanup;
  384. }
  385. // Realloc memory metafile to exact size
  386. if (!pmdc->ReallocMem(pmdc->iMem))
  387. {
  388. ASSERTGDI(FALSE, "ReallocMem failed");
  389. }
  390. }
  391. // Fixup the checksum if we are embedding a Windows metafile.
  392. // This is called by SetWinMetaFileBits only.
  393. if (pmdc->fl & MDC_CHECKSUM)
  394. {
  395. DWORD nChecksum;
  396. PEMRGDICOMMENT_WINDOWS_METAFILE pemrWinMF;
  397. ASSERTGDI(!pmdc->bIsDiskFile(),
  398. "CloseEnhMetaFile: Expects only mem files for Checksum");
  399. PENHMETAHEADER pmrmf = (PENHMETAHEADER) pmdc->GetPtr(0, pmdc->iMem);
  400. if(pmrmf)
  401. {
  402. nChecksum = GetDWordCheckSum((UINT) pmdc->iMem, (PDWORD) pmrmf);
  403. pemrWinMF = (PEMRGDICOMMENT_WINDOWS_METAFILE) ((PBYTE) pmrmf + pmrmf->nSize);
  404. ASSERTGDI(((PMRGDICOMMENT) pemrWinMF)->bIsWindowsMetaFile(),
  405. "CloseEnhMetaFile: record should be comment");
  406. pemrWinMF->nChecksum = (DWORD) 0 - nChecksum;
  407. ASSERTGDI(!GetDWordCheckSum((UINT)pmdc->iMem, (PDWORD) pmrmf),
  408. "CloseEnhMetaFile Checksum failed");
  409. pmdc->ReleasePtr(pmrmf);
  410. }
  411. else
  412. {
  413. WARNING("CloseEnhMetaFile() Failed to get metafile data pointer\n");
  414. goto CloseEnhMetaFile_cleanup;
  415. }
  416. }
  417. // Allocate and initialize a MF.
  418. if (pmdc->bIsDiskFile())
  419. {
  420. hemf = GetEnhMetaFileW(pmdc->wszPathname);
  421. }
  422. else
  423. {
  424. if (pmdc->bIsEMFSpool())
  425. {
  426. // Just in case - we should never get here during EMF spooling
  427. WARNING("CloseEnhMetaFile: called during EMF spooling\n");
  428. hemf = pmdc->CompleteEMFData(TRUE);
  429. }
  430. else
  431. {
  432. PENHMETAHEADER pmrmf = (PENHMETAHEADER) pmdc->GetPtr(0, pmdc->iMem);
  433. if(pmrmf)
  434. {
  435. hemf = SetEnhMetaFileBitsAlt((HLOCAL) pmrmf, NULL, NULL, 0);
  436. pmdc->ReleasePtr(pmrmf);
  437. }
  438. else
  439. {
  440. WARNING("CloseEnhMetaFile: failed to get emf data\n");
  441. goto CloseEnhMetaFile_cleanup;
  442. }
  443. }
  444. if (hemf)
  445. pmdc->hData = NULL; // don't free it below because it has been transfered
  446. }
  447. CloseEnhMetaFile_cleanup:
  448. // Delete the disk metafile if we had an error.
  449. if (hemf == (HENHMETAFILE) 0)
  450. pmdc->fl |= MDC_FATALERROR;
  451. // Delete the MDC and free objects and resources.
  452. vFreeMDC(pmdc);
  453. // Delete the reference info DC last because we need the local handle in
  454. // vFreeMDC.
  455. if (!InternalDeleteDC(hdc, LO_METADC))
  456. {
  457. ASSERTGDI(FALSE, "InternalDeleteDC failed");
  458. }
  459. ERROR_ASSERT(hemf != (HENHMETAFILE) 0, "CloseEnhMetaFile failed");
  460. return(hemf);
  461. }
  462. /******************************Public*Routine******************************\
  463. * UnassociateEnhMetaFile()
  464. *
  465. * This should only be called if AssociateEnhMetaFile() is first called on
  466. * this DC. This is similar to CloseEnhMetaFile in that it returns an
  467. * enhanced metafile, but it does not delete the DC, it just converts it back
  468. * to a direct DC. This is currently intended only for use with enhanced
  469. * metafile spooling.
  470. *
  471. * History:
  472. * 20-Jan-1995 -by- Eric Kutter [erick]
  473. * Wrote it.
  474. \**************************************************************************/
  475. extern "C" HENHMETAFILE UnassociateEnhMetaFile(HDC hdc, BOOL bKeepEMF)
  476. {
  477. PMDC pmdc;
  478. HENHMETAFILE hemf = NULL;
  479. BOOL bIcmOn = FALSE;
  480. PENHMETAHEADER pmrmf = NULL;
  481. PUTS("UnassociateEnhMetaFile\n");
  482. // Validate the metafile DC handle.
  483. PLDC pldc;
  484. DC_PLDC(hdc,pldc,hemf);
  485. // Handle errors.
  486. if (pldc->iType != LO_METADC)
  487. {
  488. // We need to exit cleanly in this case because we could hit it, if at
  489. // end page time we suceed in unasociating a metafile but then fail before
  490. // we can reassociate a new metafile.
  491. WARNING("UnassociateEnhMetaFileW - not a metafile\n");
  492. return((HENHMETAFILE)0);
  493. }
  494. // Cleanup temp brush or pen created for SetDCBrushColor and SetDCPenColor
  495. if (pldc->oldSetDCBrushColorBrush)
  496. {
  497. DeleteObject(pldc->oldSetDCBrushColorBrush);
  498. pldc->oldSetDCBrushColorBrush = 0;
  499. }
  500. if (pldc->oldSetDCPenColorPen)
  501. {
  502. DeleteObject(pldc->oldSetDCPenColorPen);
  503. pldc->oldSetDCPenColorPen = 0;
  504. }
  505. pmdc = (PMDC)pldc->pvPMDC;
  506. // if there is no pmdc, there was a failure during the recording. Still
  507. // need to unassociate the meta file but don't want to do any of the other
  508. // cleanup.
  509. //
  510. if (pmdc == NULL || !pmdc->bIsEMFSpool())
  511. {
  512. WARNING("UnassociateEnhMetaFile: pmdc is NULL or no EMFSpoolData\n");
  513. MakeInfoDC(hdc,FALSE);
  514. return((HENHMETAFILE)0);
  515. }
  516. // If the metafile contains GL records, tell OpenGL that things are done
  517. if (pmdc->mrmf.bOpenGL)
  518. {
  519. if (!GlmfCloseMetaFile(hdc))
  520. {
  521. WARNING("GlmfCloseMetaFile failed\n");
  522. }
  523. }
  524. // Before, we switch this back to original state, turn-off ICM.
  525. if (SetICMMode(hdc,ICM_QUERY) == ICM_ON)
  526. {
  527. SetICMMode(hdc,ICM_OFF);
  528. bIcmOn = TRUE;
  529. }
  530. MakeInfoDC(hdc,FALSE);
  531. // Check for fatal errors.
  532. if (pmdc->bFatalError())
  533. goto UnassociateEnhMetaFile_cleanup;
  534. // Write out the EOF metafile record. This would force the previous
  535. // bounds record to be commited. The EOF metafile record includes the
  536. // metafile palette if logical palettes are used.
  537. pmdc->mrmf.nPalEntries = pmdc->iPalEntries;
  538. if (!MF_EOF(hdc,pmdc->iPalEntries,pmdc->pPalEntries))
  539. goto UnassociateEnhMetaFile_cleanup;
  540. // Finally flush the bounds to the metafile header. We cannot flush the
  541. // bounds if we have not committed the previous bounds record yet.
  542. // Therefore, we do this after the last EMREOF record.
  543. pmdc->vFlushBounds();
  544. // If there was no initial metafile Frame defined in CreateEnhMetaFile then
  545. // the Bounds converted to 0.01 mm will be the Frame.
  546. if (((PERECTL) &pmdc->mrmf.rclFrame)->bEmpty())
  547. {
  548. pmdc->mrmf.rclFrame.left = MulDiv((int) (100 * pmdc->mrmf.rclBounds.left),
  549. (int) pmdc->mrmf.szlMillimeters.cx,
  550. (int) pmdc->mrmf.szlDevice.cx);
  551. pmdc->mrmf.rclFrame.right = MulDiv((int) (100 * pmdc->mrmf.rclBounds.right),
  552. (int) pmdc->mrmf.szlMillimeters.cx,
  553. (int) pmdc->mrmf.szlDevice.cx);
  554. pmdc->mrmf.rclFrame.top = MulDiv((int) (100 * pmdc->mrmf.rclBounds.top),
  555. (int) pmdc->mrmf.szlMillimeters.cy,
  556. (int) pmdc->mrmf.szlDevice.cy);
  557. pmdc->mrmf.rclFrame.bottom = MulDiv((int) (100 * pmdc->mrmf.rclBounds.bottom),
  558. (int) pmdc->mrmf.szlMillimeters.cy,
  559. (int) pmdc->mrmf.szlDevice.cy);
  560. }
  561. // Flush the buffer and write out the latest header record.
  562. ASSERTGDI((ULONG) pmdc->mrmf.nHandles <= pmdc->cmhe,
  563. "UnassociateEnhMetaFile: Bad nHandles");
  564. // Flush the header record.
  565. {
  566. pmrmf = (PENHMETAHEADER) pmdc->GetPtr(0, sizeof(ENHMETAHEADER));
  567. if(pmrmf)
  568. {
  569. *pmrmf = pmdc->mrmf;
  570. pmdc->ReleasePtr(pmrmf);
  571. }
  572. else
  573. {
  574. WARNING("UnassociateEnhMetaFile() failed to get ENHMETAHEADER\n");
  575. goto UnassociateEnhMetaFile_cleanup;
  576. }
  577. }
  578. // Realloc memory metafile to exact size
  579. if (!pmdc->ReallocMem(pmdc->iMem))
  580. {
  581. ASSERTGDI(FALSE, "ReallocMem failed");
  582. }
  583. // Fixup the checksum if we are embedding a Windows metafile.
  584. // This is called by SetWinMetaFileBits only.
  585. if (pmdc->fl & MDC_CHECKSUM)
  586. {
  587. DWORD nChecksum;
  588. PEMRGDICOMMENT_WINDOWS_METAFILE pemrWinMF;
  589. ASSERTGDI(!pmdc->bIsDiskFile(),
  590. "UnassociateMetaFile: Expects only mem files for Checksum");
  591. pmrmf = (PENHMETAHEADER) pmdc->GetPtr(0, pmdc->iMem);
  592. if(pmrmf)
  593. {
  594. nChecksum = GetDWordCheckSum((UINT) pmdc->iMem, (PDWORD) pmrmf);
  595. pemrWinMF = (PEMRGDICOMMENT_WINDOWS_METAFILE) ((PBYTE) pmrmf + pmrmf->nSize);
  596. ASSERTGDI(((PMRGDICOMMENT) pemrWinMF)->bIsWindowsMetaFile(),
  597. "UnassociatePrintMetaFile: record should be comment");
  598. pemrWinMF->nChecksum = (DWORD) 0 - nChecksum;
  599. ASSERTGDI(!GetDWordCheckSum((UINT)pmdc->iMem, (PDWORD) pmrmf),
  600. "UnassociatePrintMetaFile Checksum failed");
  601. pmdc->ReleasePtr(pmrmf);
  602. }
  603. else
  604. {
  605. WARNING("UnassociateMetaFile() failed to get metafile data\n");
  606. goto UnassociateEnhMetaFile_cleanup;
  607. }
  608. }
  609. // Allocate and initialize a MF.
  610. if (hemf = pmdc->CompleteEMFData(bKeepEMF))
  611. pmdc->hData = NULL; // don't free it below because it has been transfered
  612. ASSERTGDI(pldc->iType == LO_METADC,"UnassociateEnhMetaFile not LO_METADC\n");
  613. UnassociateEnhMetaFile_cleanup:
  614. pldc->iType = LO_DC;
  615. // Delete the disk metafile if we had an error.
  616. if (hemf == (HENHMETAFILE) 0)
  617. pmdc->fl |= MDC_FATALERROR;
  618. // Delete the MDC and free objects and resources.
  619. vFreeMDC(pmdc);
  620. pldc->pvPMDC = NULL;
  621. // if ICM is originally turned on, turn on it for LO_METADC.
  622. if (bIcmOn)
  623. {
  624. SetICMMode(hdc,ICM_ON);
  625. }
  626. return(hemf);
  627. }
  628. /******************************Public*Routine******************************\
  629. * HENHMETAFILE CopyEnhMetaFile(hSrcMetaFile, lpFilename)
  630. * HENHMETAFILE hSrcMetaFile;
  631. * LPSTR lpFilename;
  632. *
  633. * The CopyEnhMetaFile function copies the source metafile. If lpFilename is a
  634. * valid filename, the source is copies to a disk metafile. If lpFilename is
  635. * NULL, the source is copied to a memory metafile.
  636. *
  637. * Parameter Description
  638. * hSrcMetaFile Identifies the source metafile.
  639. * lpFilename Points to a filename of the file that is to receive the
  640. * metafile. If NULL the source is copied to a memory metafile.
  641. *
  642. * Return Value
  643. * The return value identifies the new enhanced metafile. Zero is returned if
  644. * an error occurred.
  645. *
  646. * History:
  647. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  648. * Wrote it.
  649. \**************************************************************************/
  650. extern "C" HENHMETAFILE APIENTRY CopyEnhMetaFileA(HENHMETAFILE hemf, LPCSTR psz)
  651. {
  652. UINT cch;
  653. WCHAR awch[MAX_PATH];
  654. if (psz != (LPSTR) NULL)
  655. {
  656. cch = strlen(psz) + 1;
  657. if (cch > MAX_PATH)
  658. {
  659. ERROR_ASSERT(FALSE, "CopyEnhMetaFileA filename too long");
  660. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  661. return((HENHMETAFILE)0);
  662. }
  663. vToUnicodeN(awch, MAX_PATH, psz, cch);
  664. return(CopyEnhMetaFileW(hemf, awch));
  665. }
  666. else
  667. return(CopyEnhMetaFileW(hemf, (LPWSTR) NULL));
  668. }
  669. extern "C" HENHMETAFILE APIENTRY CopyEnhMetaFileW(HENHMETAFILE hemf, LPCWSTR pwsz)
  670. {
  671. PMF pmf;
  672. HENHMETAFILE hmf = NULL;
  673. PUTS("CopyEnhMetaFileW\n");
  674. // Validate the metafile handle.
  675. if (!(pmf = GET_PMF(hemf)))
  676. return(hmf);
  677. PENHMETAHEADER pmrmf = pmf->emfc.GetEMFHeader();
  678. if(!pmrmf)
  679. {
  680. WARNING("CopyEnhMetaFile: unable to get header info\n");
  681. return(hmf);
  682. }
  683. PBYTE pb = (PBYTE) pmf->emfc.ObtainPtr(0, pmrmf->nBytes);
  684. if(!pb)
  685. {
  686. WARNING("CopyEnhMetaFile: unable to get header info\n");
  687. return(hmf);
  688. }
  689. if (pwsz)
  690. {
  691. HANDLE hFile = INVALID_HANDLE_VALUE;
  692. HANDLE hFileMap = NULL;
  693. HANDLE hMem = NULL;
  694. // It's a disk metafile.
  695. // Create the disk file.
  696. if ((hFile = CreateFileW(pwsz, // Filename
  697. GENERIC_WRITE|GENERIC_READ, // Write access
  698. 0L, // Non-shared
  699. (LPSECURITY_ATTRIBUTES) NULL, // No security
  700. CREATE_ALWAYS, // Always create
  701. FILE_ATTRIBUTE_NORMAL, // normal attributes
  702. (HANDLE) 0)) // no template file
  703. == INVALID_HANDLE_VALUE)
  704. {
  705. ERROR_ASSERT(FALSE, "CopyEnhMetaFile: CreateFile failed");
  706. goto CopyEnhMetaFile_file_cleanup;
  707. }
  708. // Map the disk file.
  709. if (!(hFileMap = CreateFileMappingW(hFile,
  710. (LPSECURITY_ATTRIBUTES) NULL,
  711. PAGE_READWRITE,
  712. 0L,
  713. pmrmf->nBytes,
  714. (LPWSTR) NULL)))
  715. {
  716. ERROR_ASSERT(FALSE, "CopyEnhMetaFile: CreateFileMapping failed");
  717. goto CopyEnhMetaFile_file_cleanup;
  718. }
  719. if (!(hMem = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0)))
  720. {
  721. ERROR_ASSERT(FALSE, "CopyEnhMetaFile: MapViewOfFile failed");
  722. goto CopyEnhMetaFile_file_cleanup;
  723. }
  724. // Copy the bits.
  725. RtlCopyMemory((PBYTE) hMem, pb, pmrmf->nBytes);
  726. CopyEnhMetaFile_file_cleanup:
  727. if (hMem)
  728. {
  729. if (!UnmapViewOfFile(hMem))
  730. {
  731. ASSERTGDI(FALSE, "UmmapViewOfFile failed");
  732. }
  733. }
  734. if (hFileMap)
  735. {
  736. if (!CloseHandle(hFileMap))
  737. {
  738. ASSERTGDI(FALSE, "CloseHandle failed");
  739. }
  740. }
  741. if (hFile != INVALID_HANDLE_VALUE)
  742. {
  743. if (!CloseHandle(hFile))
  744. {
  745. ASSERTGDI(FALSE, "CloseHandle failed");
  746. }
  747. }
  748. // Return a hemf if success.
  749. hmf = (hMem ? GetEnhMetaFileW(pwsz) : (HENHMETAFILE) 0);
  750. }
  751. else
  752. {
  753. // It's a memory metafile.
  754. // This is identical to SetEnhMetaFileBits.
  755. hmf = SetEnhMetaFileBits((UINT)pmrmf->nBytes, pb);
  756. }
  757. if(pb)
  758. pmf->emfc.ReleasePtr(pb);
  759. return(hmf);
  760. }
  761. /******************************Public*Routine******************************\
  762. * BOOL DeleteEnhMetaFile(hEMF)
  763. * HENHMETAFILE hEMF;
  764. *
  765. * The DeleteEnhMetaFile function invalidates the given metafile handle. If hemf
  766. * refered to a memory metafile, the metafile contents are lost. If hemf refered
  767. * to a disk-based metafile, the metafile contents are retained and access to
  768. * the metafile can be reestablished by retrieving a new handle using the
  769. * GetEnhMetaFile function.
  770. *
  771. * Parameter Description
  772. * hemf Identifies the enhanced metafile.
  773. *
  774. * Return Value
  775. * The return value is TRUE if the handle has been invalidated. Otherwise it is
  776. * FALSE.
  777. *
  778. * History:
  779. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  780. * Wrote it.
  781. \**************************************************************************/
  782. extern "C" BOOL APIENTRY DeleteEnhMetaFile(HENHMETAFILE hemf)
  783. {
  784. PMF pmf;
  785. PUTS("DeleteEnhMetaFile\n");
  786. // Validate the metafile handle.
  787. if (!(pmf = GET_PMF(hemf)))
  788. return(FALSE);
  789. // Free the metafile and its handle.
  790. vFreeMF(pmf);
  791. return(bDeleteHmf(hemf));
  792. }
  793. BOOL InternalDeleteEnhMetaFile(HENHMETAFILE hemf, BOOL bAllocBuffer)
  794. /*++
  795. Function Description: This is an internal definition of DeleteEnhMetaFile which is
  796. used in the printing playback code (object.c). The flag bAllocBuffer
  797. if used to indicate if the buffer associated with hemf needs to be
  798. freed. This is used while passing read only memory mapped buffers to
  799. SetEnhMetaFileBitsAlt.
  800. Parameters: hemf -- emf handle to be deleted
  801. bAllocBuffer -- flag to releasing hemf buffers.
  802. Return Values: TRUE if successful;
  803. FALSE otherwise
  804. --*/
  805. {
  806. PMF pmf;
  807. PUTS("DeleteEnhMetaFile\n");
  808. // Validate the metafile handle.
  809. if (!(pmf = GET_PMF(hemf)))
  810. return(FALSE);
  811. // Free the metafile and its handle.
  812. vFreeMFAlt(pmf, bAllocBuffer);
  813. return(bDeleteHmf(hemf));
  814. }
  815. /******************************Public*Routine******************************\
  816. * HENHMETAFILE GetEnhMetaFile(lpFilename)
  817. * LPSTR lpFilename;
  818. *
  819. * The GetEnhMetaFile function creates a handle for the enhanced metafile
  820. * named by the lpFilename parameter.
  821. *
  822. * Parameter Description
  823. * lpFilename Points to the null-terminated character filename that specifies
  824. * the enhanced metafile. The metafile must already exist.
  825. *
  826. * Return Value
  827. * The return value identifies an enhanced metafile if the function is
  828. * successful. Otherwise, it is 0.
  829. *
  830. * History:
  831. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  832. * Wrote it.
  833. \**************************************************************************/
  834. extern "C" HENHMETAFILE APIENTRY GetEnhMetaFileA(LPCSTR psz)
  835. {
  836. UINT cch;
  837. WCHAR awch[MAX_PATH];
  838. cch = strlen(psz) + 1;
  839. if (cch > MAX_PATH)
  840. {
  841. ERROR_ASSERT(FALSE, "GetEnhMetaFileA filename too long");
  842. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  843. return ((HENHMETAFILE)0);
  844. }
  845. vToUnicodeN(awch, MAX_PATH, psz, cch);
  846. return(GetEnhMetaFileW(awch));
  847. }
  848. extern "C" HENHMETAFILE APIENTRY GetEnhMetaFileW(LPCWSTR pwsz)
  849. {
  850. PMF pmf;
  851. HENHMETAFILE hmf;
  852. PUTS("GetEnhMetaFileW\n");
  853. // Allocate and initialize a MF.
  854. if (!(pmf = pmfAllocMF(0, (PDWORD) NULL, pwsz, NULL, 0, 0)))
  855. return((HENHMETAFILE) 0);
  856. // Allocate a local handle.
  857. hmf = hmfCreate(pmf);
  858. if (hmf == NULL)
  859. {
  860. vFreeMF(pmf);
  861. }
  862. // Return the metafile handle.
  863. return(hmf);
  864. }
  865. /******************************Public*Routine******************************\
  866. * BOOL PlayEnhMetaFile(hDC, hEMF, lpRect)
  867. * HDC hDC;
  868. * HENHMETAFILE hEMF;
  869. * LPRECT lpRect;
  870. *
  871. * The PlayEnhMetaFile function plays the contents of the specified metafile to
  872. * the given device context. The metafile can be played any number of times.
  873. *
  874. * Parameter Description
  875. * hDC Identifies the device context of the output device.
  876. * hEMF Identifies the metafile.
  877. *
  878. * Return Value
  879. * The return value is TRUE if the function is successful. Otherwise, it is
  880. * FALSE.
  881. *
  882. * History:
  883. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  884. * Wrote it.
  885. \**************************************************************************/
  886. extern "C" BOOL APIENTRY PlayEnhMetaFile(HDC hdc, HENHMETAFILE hemf, CONST RECT *lpRect)
  887. {
  888. PUTS("PlayEnhMetaFile\n");
  889. // Make sure that hdc is given. bInternalPlayEMF expects it to be given
  890. // in PlayEnhMetaFile.
  891. if (hdc == (HDC) 0)
  892. {
  893. GdiSetLastError(ERROR_INVALID_PARAMETER);
  894. return(FALSE);
  895. }
  896. return(bInternalPlayEMF(hdc, hemf, (ENHMFENUMPROC) NULL, (LPVOID) NULL, (PRECTL) lpRect));
  897. }
  898. /******************************Public*Routine******************************\
  899. * BOOL EnumEnhMetaFile(hDC, hemf, lpMetaFunc, lpData, lpRect)
  900. * HDC hDC;
  901. * HENHMETAFILE hemf;
  902. * ENHMFENUMPROC lpMetaFunc;
  903. * LPVOID lpData;
  904. * LPRECT lpRect;
  905. *
  906. * The EnumEnhMetaFile function enumerates the GDI calls within the metafile
  907. * identified by the hemf parameter. The EnumEnhMetaFile function retrieves each
  908. * GDI call within the metafile and passes it to the function pointed to by the
  909. * lpMetaFunc parameter. This callback function, an application-supplied
  910. * function, can process each GDI call as desired. Enumeration continues until
  911. * there are no more GDI calls or the callback function returns FALSE.
  912. *
  913. * Parameter Description
  914. * hDC Identifies the device context to be passed to MetaFunc.
  915. * hemf Identifies the metafile.
  916. * lpMetaFunc Is the address of the callback function. See the following
  917. * Comments section for details.
  918. * lpData Points to the callback-function data.
  919. * lpRect Points to a %RECT% structure the contains the coordinates of the
  920. * upper-left and lower-right corners of the bounding rectangle for
  921. * the output area in logical units. Points on the edges are
  922. * included in the output area. If <hdc> is 0, this is ignored.
  923. *
  924. * Return Value
  925. * The return value is TRUE if the callback function enumerates all the GDI
  926. * calls in a metafile. Otherwise, it returns FALSE.
  927. *
  928. * Comments
  929. * The callback function must be declared as an APIENTRY, so that the correct
  930. * calling conventions will be used.
  931. *
  932. * Callback Function
  933. * BOOL APIENTRY MetaFunc(hDC, lpHTable, lpMFR, nObj, lpData)
  934. * HDC hDC;
  935. * LPHANDLETABLE lpHTable;
  936. * LPENHMETARECORD lpMFR;
  937. * LONG nObj;
  938. * LPVOID lpData;
  939. *
  940. * This function may have any name, MetaFunc is just an example.
  941. *
  942. * Parameter Description
  943. * hDC Identifies the device context that was passed to EnumEnhMetaFile.
  944. * lpHTable Points to a table of handles associated with the objects (pens,
  945. * brushes, and so on) in the metafile.
  946. * lpMFR Points to a metafile record contained in the metafile.
  947. * nObj Specifies the number of objects with associated handles in the
  948. * handle table.
  949. * lpData Points to the application-supplied data.
  950. *
  951. * Return Value
  952. * The function can carry out any desired task. It must return TRUE to continue
  953. * enumeration, or FALSE to stop it.
  954. *
  955. * History:
  956. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  957. * Wrote it.
  958. \**************************************************************************/
  959. extern "C" BOOL APIENTRY EnumEnhMetaFile(HDC hdc, HENHMETAFILE hemf, ENHMFENUMPROC pfn, LPVOID pv, CONST RECT *lpRect)
  960. {
  961. PUTS("EnumEnhMetaFile\n");
  962. // Make sure that the callback function is given. bInternalPlayEMF expects
  963. // it to be given in EnumEnhMetaFile.
  964. if (pfn == (ENHMFENUMPROC) NULL)
  965. {
  966. GdiSetLastError(ERROR_INVALID_PARAMETER);
  967. return(FALSE);
  968. }
  969. return(bInternalPlayEMF(hdc, hemf, pfn, pv, (PRECTL) lpRect));
  970. }
  971. BOOL bInternalPlayEMF(HDC hdc, HENHMETAFILE hemf, ENHMFENUMPROC pfn, LPVOID pv, CONST RECTL *prcl)
  972. {
  973. BOOL bRet = FALSE;
  974. BOOL bBailout = TRUE;
  975. PMF pmf;
  976. ULONG ii, iPos;
  977. PDC_ATTR pDcAttr;
  978. FLONG flPlayMetaFile;
  979. PLDC pldc = (PLDC) NULL;
  980. PVOID pvUser;
  981. DWORD dwLayout = GDI_ERROR;
  982. PENHMETARECORD pemr = NULL;
  983. //
  984. // validate hdc, get user mode dc attr pointer
  985. //
  986. PSHARED_GET_VALIDATE(pvUser,hdc,DC_TYPE);
  987. pDcAttr = (PDC_ATTR)pvUser;
  988. BOOL bGlmf = FALSE;
  989. BOOL bInGlsBlock = FALSE;
  990. PUTS("bInternalPlayEMF\n");
  991. // Validate the metafile handle.
  992. if (!(pmf = GET_PMF(hemf)))
  993. return(bRet);
  994. PENHMETAHEADER pmrmf = pmf->emfc.GetEMFHeader();
  995. if(!pmrmf)
  996. {
  997. WARNING("bInternalPlayEMF: unable to get header info\n");
  998. return(FALSE);
  999. }
  1000. // Store hemf in the handle table.
  1001. pmf->pht->objectHandle[0] = hemf;
  1002. // Initialize metafile save level to 1.
  1003. pmf->cLevel = 1;
  1004. // Initialize the public comment indicator to FALSE.
  1005. // This is set by MRMETAFILE::bPlay and cleared by MREOF::bPlay when embedding.
  1006. pmf->bBeginGroup = FALSE;
  1007. // Initialize default clipping.
  1008. pmf->erclClipBox = rclInfinity;
  1009. // Load OpenGL if the metafile contains GL records
  1010. DWORD headerSize = pmrmf->nSize;
  1011. if (pmrmf->offDescription)
  1012. {
  1013. if(!pmf->bValidBoundedSize(pmf,pmrmf->offDescription))
  1014. {
  1015. EMFVALFAIL(("bInternalPlayEMF: offDescription (%08x) validation failed\n", pmrmf->offDescription));
  1016. return(FALSE);
  1017. }
  1018. if(pmrmf->nDescription * sizeof(WCHAR) < pmrmf->nDescription)
  1019. {
  1020. EMFVALFAIL(("bInternalPlayEMF: nDescription (%08x) * sizeof(WCHAR) arithmetic overflow\n", pmrmf->nDescription));
  1021. return(FALSE);
  1022. }
  1023. if(!pmf->bValidBoundedSize(pmf,pmrmf->nDescription * sizeof(WCHAR)))
  1024. {
  1025. EMFVALFAIL(("bInternalPlayEMF: nDescription (%08x) * sizeof(WCHAR) validation failed\n", pmrmf->nDescription));
  1026. return(FALSE);
  1027. }
  1028. headerSize -= pmrmf->nDescription * sizeof(WCHAR);
  1029. }
  1030. if (headerSize >= META_HDR_SIZE_VERSION_2)
  1031. {
  1032. if (pmrmf->offPixelFormat)
  1033. {
  1034. if (!pmf->bValidBoundedSize(pmf,pmrmf->offPixelFormat))
  1035. {
  1036. EMFVALFAIL(("bInternalPlayEMF: offPixelFormat (%08x) validation failed\n", pmrmf->offPixelFormat));
  1037. return(FALSE);
  1038. }
  1039. }
  1040. }
  1041. if (headerSize >= META_HDR_SIZE_VERSION_2 &&
  1042. pmrmf->bOpenGL &&
  1043. !LoadOpenGL())
  1044. {
  1045. return FALSE;
  1046. }
  1047. // If DC is not given in EnumEnhMetaFile, we will only enumerate the records.
  1048. if (hdc != (HDC) 0)
  1049. {
  1050. // Make sure that the output rectangle is given.
  1051. if (prcl == (PRECTL) NULL)
  1052. {
  1053. ERROR_ASSERT(FALSE, "bInternalPlayEMF: no output rectangle is given\n");
  1054. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1055. return(bRet);
  1056. }
  1057. // Save DC states before we play.
  1058. if (!SaveDC(hdc))
  1059. return(bRet);
  1060. // find the LDC if we have one
  1061. if (pDcAttr != NULL)
  1062. {
  1063. flPlayMetaFile = pDcAttr->ulDirty_ & DC_PLAYMETAFILE;
  1064. if (flPlayMetaFile)
  1065. {
  1066. PUTS("CommonEnumMetaFile: DC_PLAYMETAFILE bit is set!\n");
  1067. }
  1068. pDcAttr->ulDirty_ |= DC_PLAYMETAFILE;
  1069. }
  1070. else
  1071. {
  1072. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1073. return(FALSE);
  1074. }
  1075. //
  1076. // Turn of mirroring if any.
  1077. //
  1078. dwLayout = SetLayout(hdc, 0);
  1079. // The metafile is to be played in the advanced graphics mode only.
  1080. if (!SetGraphicsMode(hdc, GM_ADVANCED))
  1081. goto bInternalPlayEMF_cleanup;
  1082. // Combine the initial destination clipping region into the meta region
  1083. // (hrgnMeta) and reset the destination clipping region before we play.
  1084. // The meta region defines the clipping areas for the metafile picture
  1085. // and is different from those defined in the metafile.
  1086. // The clip region is reset to default in SetMetaRgn.
  1087. if (SetMetaRgn(hdc) == RGN_ERROR)
  1088. goto bInternalPlayEMF_cleanup;
  1089. // Reset DC (without Restore).
  1090. if (!bMetaResetDC(hdc))
  1091. goto bInternalPlayEMF_cleanup;
  1092. // if it use to be mirrored then change the Arc direction default.
  1093. if ((dwLayout != GDI_ERROR) && (dwLayout & LAYOUT_RTL))
  1094. SetArcDirection(hdc, AD_CLOCKWISE);
  1095. // Transform setup.
  1096. //
  1097. // To display the metafile picture in the given output rectangle, we need
  1098. // to scale the picture frame of the metafile to the output rectangle.
  1099. //
  1100. // picture frame output rectangle
  1101. //
  1102. // (a,b) (e,f)
  1103. // +-------+ +--------------+
  1104. // | ***** | | |
  1105. // | * | | ********** |
  1106. // | * | | * |
  1107. // | * | | * |
  1108. // +-------+ | * |
  1109. // (c,d) | * |
  1110. // | * |
  1111. // | * |
  1112. // | |
  1113. // +--------------+
  1114. // (g,h)
  1115. //
  1116. // The base playback transform (M) can be computed as follows:
  1117. //
  1118. // M = S . T .S . T . W .P
  1119. // (m,n) (-a,-b) (u,v) (e,f) p p
  1120. //
  1121. // where
  1122. //
  1123. // S scales the metafile picture from source device units to
  1124. // (m,n) the picture frame units (.01 mm).
  1125. //
  1126. // T translates the picture frame to the origin.
  1127. // (-a,-b)
  1128. //
  1129. // S scales the metafile picture extents to that of the logical
  1130. // (u,v) output rectangle where
  1131. // u = (g - e) / (c - a), and
  1132. // v = (h - f) / (d - b).
  1133. //
  1134. // T translates the scaled picture to the logical output
  1135. // (e,f) rectangle origin.
  1136. //
  1137. // W .P is the world and page transforms of the destination DC that
  1138. // p p determine the final placement and shape of the picture in
  1139. // in device space. We assume the combined world and page
  1140. // transform is given by the XFORM {w x y z s t}.
  1141. //
  1142. // M can be reduced as follows:
  1143. //
  1144. // [m 0 0] [ 1 0 0] [u 0 0] [1 0 0] [w x 0]
  1145. // M = [0 n 0]. [ 0 1 0]. [0 v 0]. [0 1 0]. [y z 0]
  1146. // [0 0 1] [-a -b 1] [0 0 1] [e f 1] [s t 1]
  1147. //
  1148. // [muw mux 0]
  1149. // = [nvy nvz 0]
  1150. // [(-au+e)w+(-bv+f)y+s (-au+e)x+(-bv+f)z+t 1]
  1151. //
  1152. FLOAT u, v, mu, nv, aue, bvf;
  1153. XFORM xform;
  1154. POINT ptOrg;
  1155. // Verify that the picture frame is valid.
  1156. if (pmrmf->rclFrame.right < pmrmf->rclFrame.left
  1157. || pmrmf->rclFrame.bottom < pmrmf->rclFrame.top)
  1158. {
  1159. ERROR_ASSERT(FALSE, "bInternalPlayEMF: Picture frame is null\n");
  1160. GdiSetLastError(ERROR_INVALID_DATA);
  1161. goto bInternalPlayEMF_cleanup;
  1162. }
  1163. if (headerSize >= META_HDR_SIZE_VERSION_2 &&
  1164. pmrmf->bOpenGL)
  1165. {
  1166. PBYTE pb = (PBYTE) pmf->emfc.ObtainPtr(0, pmrmf->nBytes);
  1167. if(pb)
  1168. {
  1169. // WINBUG 365038 4-10-2001 pravins Investigate GlmfInitPlayback usage
  1170. // Do we have to send the whole metafile to opengl init?
  1171. bGlmf = GlmfInitPlayback(hdc, (PENHMETAHEADER) pb, (LPRECTL)prcl);
  1172. pmf->emfc.ReleasePtr(pb);
  1173. }
  1174. if(!bGlmf) goto bInternalPlayEMF_cleanup;
  1175. }
  1176. // prcl is incl-incl.
  1177. if (pmrmf->rclFrame.right == pmrmf->rclFrame.left)
  1178. u = (FLOAT) (prcl->right - prcl->left + 1); // handle special case
  1179. else
  1180. u = (FLOAT) (prcl->right - prcl->left) /
  1181. (FLOAT) (pmrmf->rclFrame.right - pmrmf->rclFrame.left);
  1182. if (pmrmf->rclFrame.bottom == pmrmf->rclFrame.top)
  1183. v = (FLOAT) (prcl->bottom - prcl->top + 1); // handle special case
  1184. else
  1185. v = (FLOAT) (prcl->bottom - prcl->top) /
  1186. (FLOAT) (pmrmf->rclFrame.bottom - pmrmf->rclFrame.top);
  1187. mu = (FLOAT) 100.0f * (FLOAT) pmrmf->szlMillimeters.cx /
  1188. (FLOAT) pmrmf->szlDevice.cx * u;
  1189. nv = (FLOAT) 100.0f * (FLOAT) pmrmf->szlMillimeters.cy /
  1190. (FLOAT) pmrmf->szlDevice.cy * v;
  1191. aue = (FLOAT) prcl->left - (FLOAT) pmrmf->rclFrame.left * u;
  1192. bvf = (FLOAT) prcl->top - (FLOAT) pmrmf->rclFrame.top * v;
  1193. if (!GetTransform(hdc, XFORM_WORLD_TO_DEVICE, &xform))
  1194. goto bInternalPlayEMF_cleanup;
  1195. pmf->xformBase.eM11 = mu * xform.eM11;
  1196. pmf->xformBase.eM12 = mu * xform.eM12;
  1197. pmf->xformBase.eM21 = nv * xform.eM21;
  1198. pmf->xformBase.eM22 = nv * xform.eM22;
  1199. pmf->xformBase.eDx = aue * xform.eM11 + bvf * xform.eM21 + xform.eDx;
  1200. pmf->xformBase.eDy = aue * xform.eM12 + bvf * xform.eM22 + xform.eDy;
  1201. // Reset mapmode to MM_TEXT.
  1202. if (GetMapMode(hdc) != MM_TEXT)
  1203. if (!SetMapMode(hdc, MM_TEXT))
  1204. goto bInternalPlayEMF_cleanup;
  1205. // Reset window origin.
  1206. if (!GetWindowOrgEx(hdc, &ptOrg))
  1207. goto bInternalPlayEMF_cleanup;
  1208. if (ptOrg.x != 0 || ptOrg.y != 0)
  1209. if (!SetWindowOrgEx(hdc, 0, 0, (LPPOINT) NULL))
  1210. goto bInternalPlayEMF_cleanup;
  1211. // Reset viewport origin.
  1212. if (!GetViewportOrgEx(hdc, &ptOrg))
  1213. goto bInternalPlayEMF_cleanup;
  1214. if (ptOrg.x != 0 || ptOrg.y != 0)
  1215. if (!SetViewportOrgEx(hdc, 0, 0, (LPPOINT) NULL))
  1216. goto bInternalPlayEMF_cleanup;
  1217. // Finally, set the world transform. Before we set it, check for
  1218. // identity transform since rounding errors can distort the result.
  1219. if (xform.eM12 == 0.0f && xform.eM21 == 0.0f
  1220. && pmf->xformBase.eM12 == 0.0f && pmf->xformBase.eM21 == 0.0f
  1221. && pmf->xformBase.eM11 >= 0.999f && pmf->xformBase.eM11 <= 1.001f
  1222. && pmf->xformBase.eM22 >= 0.999f && pmf->xformBase.eM22 <= 1.001f
  1223. )
  1224. {
  1225. PUTS("bInternalPlayEMF: Base xform is identity\n");
  1226. pmf->xformBase.eM11 = 1.0f;
  1227. pmf->xformBase.eM22 = 1.0f;
  1228. }
  1229. if (!SetWorldTransform(hdc, &pmf->xformBase))
  1230. goto bInternalPlayEMF_cleanup;
  1231. // Now get the clip box for bound test in the source device units.
  1232. // If the clip region is empty, we can skip playing the metafile.
  1233. // Otherwise, we need to compensate for the tranform errors by
  1234. // expanding the clip box. We will perform clip test only if the
  1235. // DC is a real DC and not a meta DC.
  1236. if (!pldc || (LO_TYPE(hdc) == LO_DC_TYPE))
  1237. {
  1238. int complexity = GetClipBox(hdc, (LPRECT) &pmf->erclClipBox);
  1239. pmf->erclClipBox.vOrder();
  1240. switch (complexity)
  1241. {
  1242. case NULLREGION:
  1243. bRet = TRUE; // fall through.
  1244. case RGN_ERROR:
  1245. goto bInternalPlayEMF_cleanup;
  1246. default:
  1247. LONG ldx; // delta to expand x
  1248. LONG ldy; // delta to expand y
  1249. FLOAT eppmmDstX, eppmmDstY, eppmmSrcX, eppmmSrcY;
  1250. // pixels per millimeter for src and dst devices
  1251. // Initialize the clip box for bound test.
  1252. eppmmDstX = (FLOAT) GetDeviceCaps(hdc, DESKTOPHORZRES) /
  1253. (FLOAT) GetDeviceCaps(hdc, HORZSIZE);
  1254. eppmmDstY = (FLOAT) GetDeviceCaps(hdc, DESKTOPVERTRES) /
  1255. (FLOAT) GetDeviceCaps(hdc, VERTSIZE);
  1256. eppmmSrcX = (FLOAT) pmrmf->szlDevice.cx /
  1257. (FLOAT) pmrmf->szlMillimeters.cx;
  1258. eppmmSrcY = (FLOAT) pmrmf->szlDevice.cy /
  1259. (FLOAT) pmrmf->szlMillimeters.cy;
  1260. ldx = eppmmDstX >= eppmmSrcX
  1261. ? 1
  1262. : (LONG) (eppmmSrcX / eppmmDstX) + 1;
  1263. ldy = eppmmDstY >= eppmmSrcY
  1264. ? 1
  1265. : (LONG) (eppmmSrcY / eppmmDstY) + 1;
  1266. pmf->erclClipBox.left -= ldx;
  1267. pmf->erclClipBox.right += ldx;
  1268. pmf->erclClipBox.top -= ldy;
  1269. pmf->erclClipBox.bottom += ldy;
  1270. break;
  1271. }
  1272. }
  1273. // Setup source resolution in the transform DC.
  1274. if (!SetVirtualResolution(pmf->hdcXform,
  1275. (int) pmrmf->szlDevice.cx,
  1276. (int) pmrmf->szlDevice.cy,
  1277. (int) pmrmf->szlMillimeters.cx,
  1278. (int) pmrmf->szlMillimeters.cy))
  1279. goto bInternalPlayEMF_cleanup;
  1280. if (pmrmf->nSize >=
  1281. META_HDR_SIZE_VERSION_3 + pmrmf->nDescription * sizeof(WCHAR))
  1282. {
  1283. if (pmrmf->szlMicrometers.cx && pmrmf->szlMicrometers.cy)
  1284. {
  1285. if (!SetSizeDevice(pmf->hdcXform,
  1286. (DWORD) pmrmf->szlMicrometers.cx,
  1287. (DWORD) pmrmf->szlMicrometers.cy))
  1288. goto bInternalPlayEMF_cleanup;
  1289. }
  1290. }
  1291. // Initialize the transform in the transform DC.
  1292. // If we use ResetDC for initialization, we need to make sure that the
  1293. // source resolution is not changed!
  1294. if (!SetMapMode(pmf->hdcXform, MM_TEXT)
  1295. || !ModifyWorldTransform(pmf->hdcXform, (LPXFORM) NULL, MWT_IDENTITY)
  1296. || !SetWindowOrgEx(pmf->hdcXform, 0, 0, (LPPOINT) NULL)
  1297. || !SetViewportOrgEx(pmf->hdcXform, 0, 0, (LPPOINT) NULL))
  1298. goto bInternalPlayEMF_cleanup;
  1299. //
  1300. // Restore the layout back.
  1301. //
  1302. if (dwLayout != GDI_ERROR) {
  1303. SetLayout(hdc, dwLayout);
  1304. dwLayout = GDI_ERROR;
  1305. }
  1306. } // if (hdc != (HDC) 0)
  1307. // Assume success.
  1308. bRet = TRUE;
  1309. bBailout = FALSE;
  1310. pldc = pldcGet(hdc);
  1311. #if 0
  1312. // EngQueryEMFInfo support junk ... we are dropping support for this entry point
  1313. if (pldc && pldc->pUMPD && (pldc->pUMPD->dwFlags & UMPDFLAG_METAFILE_DRIVER))
  1314. {
  1315. if (pldc->pUMdhpdev)
  1316. {
  1317. ((UMDHPDEV *)(pldc->pUMdhpdev))->pvEMF = (PBYTE)pmf;
  1318. }
  1319. }
  1320. #endif
  1321. // Play the records until we encounter the EMR_EOF record.
  1322. // We will do the EMR_EOF record after restoring unbalanced DC states.
  1323. iPos = 0;
  1324. while(1)
  1325. {
  1326. pemr = pmf->emfc.ObtainRecordPtr(iPos);
  1327. if(!pemr)
  1328. {
  1329. WARNING("bInternalPlayEMF: unable to get emf record\n");
  1330. bRet = FALSE;
  1331. bBailout = TRUE;
  1332. goto bInternalPlayEMF_cleanup;
  1333. }
  1334. if(!pmf->bValidBoundedSize(pemr,pemr->nSize) ||
  1335. (pemr->nSize & 3) ||
  1336. pemr->nSize > pmrmf->nBytes)
  1337. {
  1338. EMFVALFAIL(("bInternalPlayEMF: pemr->nSize > FileSize or EnhMetaHeader->nBytes or not a multiple of 4\n"));
  1339. bRet = FALSE;
  1340. bBailout = TRUE;
  1341. goto bInternalPlayEMF_cleanup;
  1342. }
  1343. if(pemr->iType == EMR_EOF)
  1344. break;
  1345. if( (hdc != 0) && !(pDcAttr->ulDirty_ & DC_PLAYMETAFILE) )
  1346. {
  1347. WARNING("bInternalPlayEMF: CancelDC called\n");
  1348. bRet = FALSE;
  1349. bBailout = TRUE;
  1350. goto bInternalPlayEMF_cleanup;
  1351. }
  1352. // If we're beginning or ending a block of GLS records then we
  1353. // need to notify the OpenGL metafile support
  1354. if (pemr->iType == EMR_GLSRECORD ||
  1355. pemr->iType == EMR_GLSBOUNDEDRECORD)
  1356. {
  1357. if (!bInGlsBlock)
  1358. {
  1359. if (!GlmfBeginGlsBlock(hdc))
  1360. {
  1361. WARNING("GlmfBeginGlsBlock failed\n");
  1362. bRet = FALSE;
  1363. }
  1364. bInGlsBlock = TRUE;
  1365. }
  1366. }
  1367. else
  1368. {
  1369. if (bInGlsBlock)
  1370. {
  1371. if (!GlmfEndGlsBlock(hdc))
  1372. {
  1373. WARNING("GlmfEndGlsBlock failed\n");
  1374. bRet = FALSE;
  1375. }
  1376. bInGlsBlock = FALSE;
  1377. }
  1378. }
  1379. if (pfn == (ENHMFENUMPROC) NULL)
  1380. {
  1381. // PlayEnhMetaFile
  1382. // If we encountered an error, we will continue playing but
  1383. // return an error.
  1384. #if 0
  1385. // EngQueryEMFInfo junk
  1386. if (pldc && pldc->pUMPD && (pldc->pUMPD->dwFlags & UMPDFLAG_METAFILE_DRIVER))
  1387. {
  1388. if (pldc->pUMdhpdev)
  1389. {
  1390. ((UMDHPDEV *)(pldc->pUMdhpdev))->pvCurrentRecord = (PBYTE)pemr;
  1391. }
  1392. }
  1393. #endif
  1394. if (!PlayEnhMetaFileRecord
  1395. (
  1396. hdc,
  1397. (LPHANDLETABLE) pmf->pht,
  1398. pemr,
  1399. (UINT) pmrmf->nHandles
  1400. )
  1401. )
  1402. {
  1403. PUTSX("PlayEnhMetaFileRecord failed: pRecord: 0x%lX\n",
  1404. (PBYTE) pemr);
  1405. ERROR_ASSERT(FALSE, "\n");
  1406. bRet = FALSE;
  1407. }
  1408. }
  1409. else
  1410. {
  1411. // EnumEnhMetaFile
  1412. if (!(*pfn)
  1413. (
  1414. hdc,
  1415. (LPHANDLETABLE) pmf->pht,
  1416. pemr,
  1417. (int) pmrmf->nHandles,
  1418. (LPARAM)pv
  1419. )
  1420. )
  1421. {
  1422. ERROR_ASSERT(FALSE, "EnumProc failed");
  1423. bRet = FALSE;
  1424. bBailout = TRUE;
  1425. goto bInternalPlayEMF_cleanup;
  1426. }
  1427. }
  1428. if ((pmf->fl & MF_FOUNDBAD))
  1429. {
  1430. bRet = FALSE;
  1431. bBailout = TRUE;
  1432. EMFVALFAIL(("bInternalPlayEMF: detected bad Meta records. Skipping all the subsequent records\n"));
  1433. goto bInternalPlayEMF_cleanup;
  1434. }
  1435. // If the metafile is corrupt with a record of size 0, we would loop forever
  1436. // negitive or zero size will be treated as an error
  1437. if (pemr->nSize > 0)
  1438. {
  1439. iPos += pemr->nSize;
  1440. }
  1441. else
  1442. {
  1443. WARNING("bInternalPlayEMF failed on a record with zero/negitive size\n");
  1444. bRet = FALSE;
  1445. bBailout = TRUE;
  1446. goto bInternalPlayEMF_cleanup;
  1447. }
  1448. if (iPos >= pmrmf->nBytes)
  1449. {
  1450. VERIFYGDI(FALSE, "bInternalPlayEMF: No EOF found\n");
  1451. bRet = FALSE;
  1452. bBailout = TRUE;
  1453. goto bInternalPlayEMF_cleanup;
  1454. }
  1455. pmf->emfc.ReleaseRecordPtr(pemr);
  1456. }
  1457. // Cleanup and return.
  1458. bInternalPlayEMF_cleanup:
  1459. //
  1460. // Restore the layout back.
  1461. //
  1462. if (dwLayout != GDI_ERROR) {
  1463. SetLayout(hdc, dwLayout);
  1464. }
  1465. // Restore any remaining metafile saved states if necessary.
  1466. if (pmf->cLevel > 1)
  1467. {
  1468. EMRRESTOREDC emrrdc;
  1469. WARNING("bInternalPlayEMF: fixing up unbalanced Save/Restore DCs\n");
  1470. emrrdc.emr.iType = EMR_RESTOREDC;
  1471. emrrdc.emr.nSize = sizeof(EMRRESTOREDC);
  1472. emrrdc.iRelative = 1 - pmf->cLevel;
  1473. // If the app bails out, we still need to restore our states.
  1474. if (pfn == (ENHMFENUMPROC) NULL || bBailout)
  1475. {
  1476. if (!PlayEnhMetaFileRecord(hdc, (LPHANDLETABLE) pmf->pht,
  1477. (CONST ENHMETARECORD *) &emrrdc, (UINT) pmrmf->nHandles))
  1478. bRet = FALSE;
  1479. }
  1480. else
  1481. {
  1482. if (!(*pfn)(hdc, (LPHANDLETABLE) pmf->pht,
  1483. (CONST ENHMETARECORD *) &emrrdc, (int) pmrmf->nHandles,
  1484. (LPARAM)pv))
  1485. bRet = FALSE;
  1486. }
  1487. }
  1488. // Play the EMR_EOF record if the app did not bail out.
  1489. // We play it here to better identify the end of the picture.
  1490. if (!bBailout)
  1491. {
  1492. ASSERTGDI(pemr->iType == EMR_EOF, "bInternalPlayEMF: Bad EMR_EOF record");
  1493. if (pfn != (ENHMFENUMPROC) NULL)
  1494. {
  1495. if (!(*pfn)(hdc, (LPHANDLETABLE) pmf->pht,
  1496. (CONST ENHMETARECORD *) pemr,
  1497. (int) pmrmf->nHandles, (LPARAM)pv))
  1498. {
  1499. bRet = FALSE;
  1500. }
  1501. }
  1502. if (pfn == (ENHMFENUMPROC) NULL || pmf->bBeginGroup)
  1503. {
  1504. // If the enum callback function did not call us on EMR_EOF but
  1505. // called us on EMR_HEADER, we will emit the comment record anyway.
  1506. VERIFYGDI(pfn == (ENHMFENUMPROC) NULL,
  1507. "bInternalPlayEMF: fixing up public group comments\n");
  1508. if (!PlayEnhMetaFileRecord(hdc, (LPHANDLETABLE) pmf->pht,
  1509. (CONST ENHMETARECORD *) pemr, (UINT) pmrmf->nHandles))
  1510. {
  1511. bRet = FALSE;
  1512. }
  1513. }
  1514. }
  1515. // Clean up GL state
  1516. if (bGlmf &&
  1517. !GlmfEndPlayback(hdc))
  1518. {
  1519. ASSERTGDI(FALSE, "GlmfEndPlayback failed");
  1520. }
  1521. // Restore DC states.
  1522. if (hdc != (HDC) 0)
  1523. {
  1524. if (!RestoreDC(hdc, -1))
  1525. {
  1526. ERROR_ASSERT(FALSE, "RestoreDC failed");
  1527. }
  1528. // If PlayEnhMetaFile is called as a result of playback of the multi formats
  1529. // public comment, we have to preserve the DC_PLAYMETAFILE bit.
  1530. // If we hit a CancelDC, then we want to let the caller know.
  1531. ASSERTGDI(!(flPlayMetaFile & ~DC_PLAYMETAFILE),
  1532. "bInternalPlayEMF: bad flPlayMetaFile\n");
  1533. pDcAttr->ulDirty_ &= ~DC_PLAYMETAFILE;
  1534. pDcAttr->ulDirty_ |= flPlayMetaFile;
  1535. }
  1536. // Delete the objects created by play. The previous restore would have
  1537. // deselected these objects. The first entry contain the hemf handle.
  1538. for (ii = 1; ii < (ULONG) pmrmf->nHandles; ii++)
  1539. if (pmf->pht->objectHandle[ii])
  1540. {
  1541. PUTS("Deleting an object in bInternalPlayEMF\n");
  1542. if (!DeleteObject(pmf->pht->objectHandle[ii]))
  1543. {
  1544. VERIFYGDI(FALSE, "bInternalPlayEMF: DeleteObject failed\n");
  1545. }
  1546. pmf->pht->objectHandle[ii] = 0;
  1547. }
  1548. if(pemr)
  1549. pmf->emfc.ReleaseRecordPtr(pemr);
  1550. return(bRet);
  1551. }
  1552. /******************************Public*Routine******************************\
  1553. * BOOL PlayEnhMetaFileRecord(hDC, lpHandletable, lpEnhMetaRecord, nHandles)
  1554. * HDC hDC;
  1555. * LPHANDLETABLE lpHandletable;
  1556. * CONST ENHMETARECORD *lpMetaRecord;
  1557. * UINT nHandles;
  1558. *
  1559. * The PlayEnhMetaFileRecord function plays a metafile record by executing the GDI
  1560. * function call contained within the metafile record.
  1561. *
  1562. * Parameter Description
  1563. * hDC Identifies the device context.
  1564. * lpHandletable Points to the object handle table to be used for the metafile
  1565. * playback.
  1566. * lpMetaRecord Points to the metafile record to be played.
  1567. * nHandles Not used
  1568. *
  1569. * Return Value
  1570. * TRUE is returned for success, FALSE for failure.
  1571. *
  1572. * Comments
  1573. * An application typically uses this function in conjunction with the
  1574. * EnumEnhMetaFile function to modify and then play a metafile.
  1575. *
  1576. * The lpHandleTable, nHandles, and lpMetaRecord parameters must be exactly
  1577. * those passed to the MetaFunc procedure by EnumEnhMetaFile.
  1578. *
  1579. * History:
  1580. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  1581. * Wrote it.
  1582. \**************************************************************************/
  1583. extern "C" BOOL APIENTRY PlayEnhMetaFileRecord
  1584. (
  1585. HDC hdc,
  1586. LPHANDLETABLE pht,
  1587. CONST ENHMETARECORD *pmr,
  1588. UINT cht
  1589. )
  1590. {
  1591. PUTS("PlayEnhMetaFileRecord\n");
  1592. if (pmr->iType >= EMR_MIN && pmr->iType <= EMR_MAX)
  1593. {
  1594. return
  1595. (
  1596. (((PMR) pmr)->*afnbMRPlay[((PENHMETARECORD)pmr)->iType - 1])
  1597. (
  1598. hdc,
  1599. (PHANDLETABLE) pht,
  1600. cht
  1601. )
  1602. );
  1603. }
  1604. // Allow future metafile records to be embedded.
  1605. // Since it is impossible to know in advance the requirements for all new
  1606. // records, we will make the assumption that most records can be simply
  1607. // embedded with little or no modifications. If a new record cannot be
  1608. // embedded by the following code, it should include a special bit in its
  1609. // record type and we will ignore it during embedding. In this case,
  1610. // we assume that the record does not have side effects that distort the
  1611. // picture in a major way. If an embeddable record contains a bounds,
  1612. // we need to transform the bounds to the new device coords.
  1613. // I estimate the following code to embed 80% of the new records correctly.
  1614. //
  1615. // NOTE: The future designer should take into account the compatibility
  1616. // issue when adding new record types.
  1617. //
  1618. // Note that although the code is here, it is not a requirement for
  1619. // the future metafiles if you think it is insane. Just add EMR_NOEMBED
  1620. // to the metafile types and it will ignore the new records.
  1621. // For true compatibility support, see GdiComment for multiple formats.
  1622. ERROR_ASSERT(FALSE, "PlayEnhMetaFileRecord: unknown record");
  1623. if (pmr->iType & EMR_NOEMBED)
  1624. return(TRUE);
  1625. // If we are not embedding, we are done with this record.
  1626. PLDC pldc;
  1627. DC_PLDC(hdc,pldc,FALSE);
  1628. if (pldc->iType != LO_METADC)
  1629. return(TRUE);
  1630. // Embed this new record.
  1631. PMDC pmdc = (PMDC)pldc->pvPMDC;
  1632. PMR pmrNew;
  1633. PUTS("PlayEnhMetaFileRecord: embedding new record\n");
  1634. if (!(pmrNew = (PMR) pmdc->pvNewRecord((pmr->nSize + 3) & ~3)))
  1635. return(FALSE);
  1636. // Init the record header.
  1637. pmrNew->vInit(pmr->iType);
  1638. // Copy the body.
  1639. RtlCopyMemory
  1640. (
  1641. (PBYTE) ((PENHMETARECORD) pmrNew)->dParm,
  1642. (PBYTE) pmr->dParm,
  1643. pmr->nSize - sizeof(EMR)
  1644. );
  1645. // Update record with bounds.
  1646. if (pmr->iType & EMR_ACCUMBOUNDS)
  1647. {
  1648. if (!((PERECTL) &((PENHMETABOUNDRECORD) pmrNew)->rclBounds)->bEmpty())
  1649. {
  1650. PMF pmf;
  1651. XFORM xform;
  1652. POINTL aptlOld[4], aptlNew[4];
  1653. // Get metafile.
  1654. if (!(pmf = GET_PMF((HENHMETAFILE)pht->objectHandle[0])))
  1655. return(FALSE);
  1656. // Convert from old device coords to new device coords.
  1657. xform = pmf->xformBase;
  1658. aptlOld[0].x = ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.left;
  1659. aptlOld[0].y = ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.top;
  1660. aptlOld[1].x = ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.right;
  1661. aptlOld[1].y = ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.top;
  1662. aptlOld[2].x = ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.right;
  1663. aptlOld[2].y = ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.bottom;
  1664. aptlOld[3].x = ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.left;
  1665. aptlOld[3].y = ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.bottom;
  1666. for (int i = 0; i < 4; i++)
  1667. {
  1668. aptlNew[i].x = (LONG) ((FLOAT) aptlOld[i].x * xform.eM11
  1669. + (FLOAT) aptlOld[i].y * xform.eM21
  1670. + xform.eDx + 0.5f);
  1671. aptlNew[i].y = (LONG) ((FLOAT) aptlOld[i].x * xform.eM12
  1672. + (FLOAT) aptlOld[i].y * xform.eM22
  1673. + xform.eDy + 0.5f);
  1674. }
  1675. // Update the device bounds.
  1676. ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.left
  1677. = MIN4(aptlNew[0].x,aptlNew[1].x,aptlNew[2].x,aptlNew[3].x);
  1678. ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.right
  1679. = MAX4(aptlNew[0].x,aptlNew[1].x,aptlNew[2].x,aptlNew[3].x);
  1680. ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.top
  1681. = MIN4(aptlNew[0].y,aptlNew[1].y,aptlNew[2].y,aptlNew[3].y);
  1682. ((PENHMETABOUNDRECORD) pmrNew)->rclBounds.bottom
  1683. = MAX4(aptlNew[0].y,aptlNew[1].y,aptlNew[2].y,aptlNew[3].y);
  1684. // Accumulate the new bounds.
  1685. (void) SetBoundsRectAlt(hdc,
  1686. (LPRECT) &((PENHMETABOUNDRECORD) pmrNew)->rclBounds,
  1687. (UINT) (DCB_WINDOWMGR | DCB_ACCUMULATE));
  1688. }
  1689. }
  1690. pmrNew->vCommit(pmdc); // commit the record
  1691. return(TRUE);
  1692. }
  1693. /******************************Public*Routine******************************\
  1694. * UINT APIENTRY GetEnhMetaFileBits(
  1695. * HENHMETAFILE hemf,
  1696. * UINT nSize,
  1697. * LPBYTE lpData )
  1698. *
  1699. * The GetEnhMetaFileBits function returns the specified metafile as a block of
  1700. * data. The retrieved data must not be modified and is only usable by
  1701. * SetEnhMetaFileBits.
  1702. *
  1703. * Parameter Description
  1704. * hemf Identifies the metafile.
  1705. * nSize Specifies the size of the buffer reserved for the data. Only this
  1706. * many bytes will be written.
  1707. * lpData Points to the buffer to receive the metafile data. If this
  1708. * pointer is NULL, the function returns the size necessary to hold
  1709. * the data.
  1710. *
  1711. * Return Value
  1712. * The return value is the size of the metafile data in bytes. If an error
  1713. * occurs, 0 is returned.
  1714. *
  1715. * Comments
  1716. * The handle used as the hemf parameter does NOT become invalid when the
  1717. * GetEnhMetaFileBits function returns.
  1718. *
  1719. * History:
  1720. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  1721. * Wrote it.
  1722. \**************************************************************************/
  1723. extern "C" UINT APIENTRY GetEnhMetaFileBits(
  1724. HENHMETAFILE hEMF,
  1725. UINT nSize,
  1726. LPBYTE lpData )
  1727. {
  1728. PMF pmf;
  1729. PUTS("GetEnhMetaFileBits\n");
  1730. // Validate the metafile handle.
  1731. if (!(pmf = GET_PMF(hEMF)))
  1732. return(0);
  1733. PENHMETAHEADER pmrmf = pmf->emfc.GetEMFHeader();
  1734. if(!pmrmf)
  1735. return(0);
  1736. // If lpData is NULL, return the size necessary to hold the data.
  1737. if (!lpData)
  1738. return(pmrmf->nBytes);
  1739. // Make sure the input buffer is large enough.
  1740. if (nSize < pmrmf->nBytes)
  1741. {
  1742. GdiSetLastError(ERROR_INSUFFICIENT_BUFFER);
  1743. return(0);
  1744. }
  1745. // Copy the bits.
  1746. PBYTE pb = (PBYTE) pmf->emfc.ObtainPtr(0, pmrmf->nBytes);
  1747. if(!pb)
  1748. return(0);
  1749. RtlCopyMemory(lpData, pb, pmrmf->nBytes);
  1750. pmf->emfc.ReleasePtr(pb);
  1751. // Return the number of bytes copied.
  1752. return(pmrmf->nBytes);
  1753. }
  1754. /******************************Public*Routine******************************\
  1755. * UINT APIENTRY GetWinMetaFileBits(
  1756. * HENHMETAFILE hemf,
  1757. * UINT nSize,
  1758. * LPBYTE lpData
  1759. * INT iMapMode,
  1760. * HDC hdcRef)
  1761. *
  1762. * The GetWinMetaFileBits function returns the metafile records of the
  1763. * specified enhanced metafile in the Windows 3.0 format and copies
  1764. * them into the buffer specified.
  1765. *
  1766. * Parameter Description
  1767. * hemf Identifies the metafile.
  1768. * nSize Specifies the size of the buffer reserved for the data. Only this
  1769. * many bytes will be written.
  1770. * lpData Points to the buffer to receive the metafile data. If this
  1771. * pointer is NULL, the function returns the size necessary to hold
  1772. * the data.
  1773. * iMapMode the desired mapping mode of the metafile contents to be returned
  1774. * hdcRef defines the units of the metafile to be returned
  1775. *
  1776. * Return Value
  1777. * The return value is the size of the metafile data in bytes. If an error
  1778. * occurs, 0 is returned.
  1779. *
  1780. * Comments
  1781. * The handle used as the hemf parameter does NOT become invalid when the
  1782. * GetWinMetaFileBits function returns.
  1783. *
  1784. * History:
  1785. * Thu Apr 8 14:22:23 1993 -by- Hock San Lee [hockl]
  1786. * Rewrote it.
  1787. * 02-Jan-1992 -by- John Colleran [johnc]
  1788. * Wrote it.
  1789. \**************************************************************************/
  1790. extern "C" UINT APIENTRY GetWinMetaFileBits
  1791. (
  1792. HENHMETAFILE hemf,
  1793. UINT cbData16,
  1794. LPBYTE pData16,
  1795. INT iMapMode,
  1796. HDC hdcRef
  1797. )
  1798. {
  1799. static LPFNCONVERT lpConvertEmfToWmf = (LPFNCONVERT) NULL;
  1800. PENHMETAHEADER pmrmf = NULL;
  1801. PMF pmf;
  1802. UINT fConverter = MF3216_INCLUDE_WIN32MF;
  1803. PEMRGDICOMMENT_WINDOWS_METAFILE pemrWinMF;
  1804. UINT result = 0;
  1805. PUTS("GetWinMetaFileBits\n");
  1806. // Validate mapmode.
  1807. if ((iMapMode < MM_MIN) ||
  1808. (iMapMode > MM_MAX) ||
  1809. (LO_TYPE(hemf) != LO_METAFILE_TYPE))
  1810. {
  1811. ERROR_ASSERT(FALSE, "GetWinMetaFileBits: Bad mapmode");
  1812. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1813. return(0);
  1814. }
  1815. // Validate the metafile handle.
  1816. if (!(pmf = GET_PMF(hemf)))
  1817. goto getWinMetaFileBits_exit;
  1818. pmrmf = pmf->emfc.GetEMFHeader();
  1819. if(!pmrmf)
  1820. goto getWinMetaFileBits_exit;
  1821. pmrmf = (PENHMETAHEADER) pmf->emfc.ObtainPtr(0, pmrmf->nBytes);
  1822. if(!pmrmf)
  1823. goto getWinMetaFileBits_exit;
  1824. ASSERTGDI(pmrmf->iType == EMR_HEADER, "GetWinMetaFileBits: invalid data");
  1825. // Store hemf in the handle table.
  1826. pmf->pht->objectHandle[0] = hemf;
  1827. #ifndef DO_NOT_USE_EMBEDDED_WINDOWS_METAFILE
  1828. // See if the this was originally an old style metafile and if it has
  1829. // an encapsulated original
  1830. if (!pmf->bValidBoundedSize(pmrmf, ((PENHMETAHEADER) pmrmf)->nSize))
  1831. {
  1832. EMFVALFAIL(("GetWinMetaFileBits: pmf->bValidBoundedSize(%p,%08x) failed\n",pmrmf, ((PENHMETAHEADER) pmrmf)->nSize));
  1833. goto getWinMetaFileBits_exit;
  1834. }
  1835. pemrWinMF = (PEMRGDICOMMENT_WINDOWS_METAFILE)
  1836. ((PBYTE) pmrmf + ((PENHMETAHEADER) pmrmf)->nSize);
  1837. if (((PMRGDICOMMENT) pemrWinMF)->bIsWindowsMetaFile())
  1838. {
  1839. // Make sure that this is what we want and verify checksum
  1840. if (iMapMode != MM_ANISOTROPIC)
  1841. {
  1842. PUTS("GetWinMetaFileBits: Requested and embedded metafile mapmodes mismatch\n");
  1843. }
  1844. else if ((pemrWinMF->nVersion != METAVERSION300 &&
  1845. pemrWinMF->nVersion != METAVERSION100)
  1846. || pemrWinMF->fFlags != 0)
  1847. {
  1848. // In this release, we can only handle the given metafile
  1849. // versions. If we return a version that we don't recognize,
  1850. // the app will not be able to play that metafile later on!
  1851. VERIFYGDI(FALSE, "GetWinMetaFileBits: Unrecognized Windows metafile\n");
  1852. }
  1853. else if (GetDWordCheckSum((UINT) pmrmf->nBytes, (PDWORD) pmrmf))
  1854. {
  1855. PUTS("GetWinMetaFileBits: Metafile has been modified\n");
  1856. }
  1857. else
  1858. {
  1859. PUTS("GetWinMetaFileBits: Returning embedded Windows metafile\n");
  1860. if (pData16)
  1861. {
  1862. if (cbData16 < pemrWinMF->cbWinMetaFile)
  1863. {
  1864. ERROR_ASSERT(FALSE, "GetWinMetaFileBits: insufficient buffer");
  1865. GdiSetLastError(ERROR_INSUFFICIENT_BUFFER);
  1866. goto getWinMetaFileBits_exit;
  1867. }
  1868. RtlCopyMemory(pData16,
  1869. (PBYTE) &pemrWinMF[1],
  1870. pemrWinMF->cbWinMetaFile);
  1871. }
  1872. result = pemrWinMF->cbWinMetaFile;
  1873. goto getWinMetaFileBits_exit;
  1874. }
  1875. // Either the enhanced metafile containing an embedded Windows
  1876. // metafile has been modified or the embedded Windows metafile
  1877. // is not what we want. Since the original format is Windows
  1878. // format, we will not embed the enhanced metafile in the
  1879. // returned Windows metafile.
  1880. PUTS("GetWinMetaFileBits: Skipping embedded windows metafile\n");
  1881. fConverter &= ~MF3216_INCLUDE_WIN32MF;
  1882. }
  1883. #endif // DO_NOT_USE_EMBEDDED_WINDOWS_METAFILE
  1884. // Load the MF3216 metafile converter if it has not been loaded for this
  1885. // process. NOTE: the converter is unloaded when the process goes away.
  1886. if (!lpConvertEmfToWmf)
  1887. {
  1888. HANDLE hModule = LoadLibraryW(L"mf3216") ;
  1889. lpConvertEmfToWmf = (LPFNCONVERT) GetProcAddress(hModule, "ConvertEmfToWmf");
  1890. if (!lpConvertEmfToWmf)
  1891. {
  1892. VERIFYGDI(FALSE, "GetWinMetaFileBits: Failed to load mf3216.dll\n");
  1893. goto getWinMetaFileBits_exit;
  1894. }
  1895. }
  1896. // Tell the converter to emit the Enhanced metafile as a comment only if
  1897. // this metafile is not previously a Windows metafile
  1898. if (fConverter & MF3216_INCLUDE_WIN32MF)
  1899. {
  1900. PUTS("GetWinMetaFileBits: Embedding enhanced metafile\n");
  1901. }
  1902. else
  1903. {
  1904. PUTS("GetWinMetaFileBits: No embedding of enhanced metafile\n");
  1905. }
  1906. result = lpConvertEmfToWmf((PVOID)pmf->pht, (PBYTE) pmrmf, cbData16, pData16,
  1907. iMapMode, hdcRef, fConverter);
  1908. getWinMetaFileBits_exit:
  1909. if(pmrmf)
  1910. pmf->emfc.ReleasePtr(pmrmf);
  1911. return(result);
  1912. }
  1913. /******************************Public*Routine******************************\
  1914. * HENHMETAFILE APIENTRY SetWinMetaFileBits(
  1915. * UINT nSize,
  1916. * LPBYTE lpData,
  1917. * HDC hdcRef,
  1918. * LPMETAFILEPICT lpMFP
  1919. *
  1920. * The SetWinMetaFileBits function creates a memory-based enhanced metafile
  1921. * from Windows 3.X metafile data.
  1922. *
  1923. * hEMF Identifies the metafile.
  1924. * nSize Specifies the size of the buffer
  1925. * lpData Points to the buffer of the Win 3.x metafile data.
  1926. * hdcRef defines the units of the metafile to be returned
  1927. * lpMFP suggested size of metafile
  1928. *
  1929. * Return Value
  1930. * The return value is a handle to the new enhanced metafile if successful.
  1931. *
  1932. * History:
  1933. * Thu Apr 8 14:22:23 1993 -by- Hock San Lee [hockl]
  1934. * Rewrote it.
  1935. * 02-Jan-1992 -by- John Colleran [johnc]
  1936. * Wrote it.
  1937. \**************************************************************************/
  1938. extern "C" HENHMETAFILE APIENTRY SetWinMetaFileBits
  1939. (
  1940. UINT nSize,
  1941. CONST BYTE *lpMeta16Data,
  1942. HDC hdcRef,
  1943. CONST METAFILEPICT *lpMFP
  1944. )
  1945. {
  1946. HENHMETAFILE hemf32 = (HENHMETAFILE) 0;
  1947. HMETAFILE hmf16 = (HMETAFILE) 0;
  1948. HDC hdcT = (HDC) 0;
  1949. RECT rcFrame;
  1950. LPRECT lprcFrame = (LPRECT)NULL;
  1951. HDC hdcEMF;
  1952. INT iMapMode;
  1953. INT xExtPels;
  1954. INT yExtPels;
  1955. PMETA_ESCAPE_ENHANCED_METAFILE pmfeEnhMF;
  1956. BOOL bEmbedEmf = TRUE;
  1957. PMDC pmdcEMF;
  1958. PUTS("SetWinMetaFileBits\n");
  1959. if (lpMFP)
  1960. {
  1961. PUTSX("SetWinMetaFileBits: xExt:%lX ", lpMFP->xExt);
  1962. PUTSX("yExt:%lX\n", lpMFP->yExt);
  1963. }
  1964. else
  1965. PUTS("SetWinMetaFileBits: lpMFP is NULL\n");
  1966. // Verify the input data.
  1967. if (nSize < sizeof(METAHEADER)
  1968. || !IsValidMetaHeader16((PMETAHEADER) lpMeta16Data))
  1969. {
  1970. ERROR_ASSERT(FALSE, "SetWinMetaFileBits: Bad input data\n");
  1971. GdiSetLastError(ERROR_INVALID_DATA);
  1972. return((HENHMETAFILE) 0);
  1973. }
  1974. #ifndef DO_NOT_USE_EMBEDDED_ENHANCED_METAFILE
  1975. // Check if the windows metafile contains an embedded version of the
  1976. // original enhanced metafile.
  1977. pmfeEnhMF = (PMETA_ESCAPE_ENHANCED_METAFILE) &lpMeta16Data[sizeof(METAHEADER)];
  1978. if (IS_META_ESCAPE_ENHANCED_METAFILE(pmfeEnhMF))
  1979. {
  1980. PBYTE pMetaData32 = (PBYTE) NULL;
  1981. UINT i;
  1982. UINT cbMetaData32;
  1983. // We will not do metafile version check here. It is verified in
  1984. // pmfAllocMF eventually.
  1985. if (pmfeEnhMF->fFlags != 0)
  1986. {
  1987. VERIFYGDI(FALSE, "SetWinMetaFileBits: Unrecognized Windows metafile\n");
  1988. goto SWMFB_UseConverter;
  1989. }
  1990. // Validate checksum
  1991. if (GetWordCheckSum(nSize, (PWORD) lpMeta16Data))
  1992. {
  1993. PUTS("SetWinMetaFileBits: Metafile has been modified\n");
  1994. goto SWMFB_UseConverter;
  1995. }
  1996. // Unpack the data from the small chunks of metafile comment records
  1997. // Windows 3.0 chokes on Comment Record > 8K?
  1998. // We probably could probably just error out if out of memory but
  1999. // lets try to convert just because the embedded comment might be bad.
  2000. PUTS("SetWinMetaFileBits: Using embedded enhanced metafile\n");
  2001. cbMetaData32 = (UINT) pmfeEnhMF->cbEnhMetaFile;
  2002. if (!(pMetaData32 = (PBYTE) LocalAlloc(LMEM_FIXED, cbMetaData32)))
  2003. {
  2004. VERIFYGDI(FALSE, "SetWinMetaFileBits: LocalAlloc Failed");
  2005. goto SWMFB_UseConverter;
  2006. }
  2007. i = 0;
  2008. do
  2009. {
  2010. if (i + pmfeEnhMF->cbCurrent > cbMetaData32)
  2011. {
  2012. VERIFYGDI(FALSE, "SetWinMetaFileBits: Bad metafile comment");
  2013. goto SWMFB_UseConverter;
  2014. }
  2015. RtlCopyMemory(&pMetaData32[i], (PBYTE) &pmfeEnhMF[1], pmfeEnhMF->cbCurrent);
  2016. i += (UINT) pmfeEnhMF->cbCurrent;
  2017. pmfeEnhMF = (PMETA_ESCAPE_ENHANCED_METAFILE)
  2018. ((PWORD) pmfeEnhMF + pmfeEnhMF->rdSize);
  2019. } while (IS_META_ESCAPE_ENHANCED_METAFILE(pmfeEnhMF));
  2020. if (i != cbMetaData32)
  2021. {
  2022. VERIFYGDI(FALSE, "SetWinMetaFileBits: Insufficient metafile data");
  2023. goto SWMFB_UseConverter;
  2024. }
  2025. // Set the memory directly into the enhanced metafile and return the
  2026. // metafile.
  2027. if (hemf32 = SetEnhMetaFileBitsAlt((HLOCAL) pMetaData32, NULL, NULL, 0))
  2028. goto SWMFB_exit;
  2029. VERIFYGDI(FALSE, "SetWinMetaFileBits: SetEnhMetaFileBitsAlt failed\n");
  2030. SWMFB_UseConverter:
  2031. if (pMetaData32)
  2032. {
  2033. if (LocalFree((HANDLE) pMetaData32))
  2034. {
  2035. ASSERTGDI(FALSE, "SetWinMetaFileBits: LocalFree Failed");
  2036. }
  2037. }
  2038. // The Windows metafile containing an embedded enhanced metafile has
  2039. // been modified. Since the original format is enhanced format, we
  2040. // will not embed the Windows metafile in the returned enhanced
  2041. // metafile.
  2042. bEmbedEmf = FALSE;
  2043. }
  2044. #endif // DO_NOT_USE_EMBEDDED_ENHANCED_METAFILE
  2045. // Create the 16 bit metafile
  2046. if (!(hmf16 = SetMetaFileBitsEx(nSize, lpMeta16Data)))
  2047. {
  2048. ERROR_ASSERT(FALSE, "SetWinMetaFileBits: SetMetaFileBitsEx Failed");
  2049. goto SWMFB_exit;
  2050. }
  2051. // If no hdcRef is given, use the default display as reference.
  2052. if (!hdcRef)
  2053. {
  2054. if (!(hdcRef = hdcT = CreateICA((LPCSTR) "DISPLAY", (LPCSTR) NULL,
  2055. (LPCSTR) NULL, (LPDEVMODEA) NULL)))
  2056. {
  2057. ERROR_ASSERT(FALSE, "SetWinMetaFileBits: CreateICA Failed");
  2058. goto SWMFB_exit;
  2059. }
  2060. }
  2061. // Get the frame rect in .01mm units and extents in pel units.
  2062. // For fixed mapmodes, the extents are unnecessary.
  2063. if (lpMFP)
  2064. {
  2065. iMapMode = lpMFP->mm ? (INT) lpMFP->mm : MM_ANISOTROPIC; // zero used
  2066. switch (iMapMode)
  2067. {
  2068. case MM_ISOTROPIC:
  2069. case MM_ANISOTROPIC:
  2070. // If the extents are negative, use the default device extents.
  2071. if (lpMFP->xExt > 0 && lpMFP->yExt > 0)
  2072. {
  2073. // Convert the MetaFilePict suggested size HI-Metric into PELs
  2074. xExtPels = MulDiv((int) lpMFP->xExt,
  2075. GetDeviceCaps(hdcRef, DESKTOPHORZRES),
  2076. GetDeviceCaps(hdcRef, HORZSIZE) * 100);
  2077. yExtPels = MulDiv((int) lpMFP->yExt,
  2078. GetDeviceCaps(hdcRef, DESKTOPVERTRES),
  2079. GetDeviceCaps(hdcRef, VERTSIZE) * 100);
  2080. rcFrame.left = 0;
  2081. rcFrame.top = 0;
  2082. rcFrame.right = lpMFP->xExt;
  2083. rcFrame.bottom = lpMFP->yExt;
  2084. lprcFrame = &rcFrame;
  2085. break;
  2086. }
  2087. PUTS("SetWinMetaFileBits: negative extents in lpMFP\n");
  2088. // fall through
  2089. case MM_TEXT:
  2090. case MM_LOMETRIC:
  2091. case MM_HIMETRIC:
  2092. case MM_LOENGLISH:
  2093. case MM_HIENGLISH:
  2094. case MM_TWIPS:
  2095. xExtPels = GetDeviceCaps(hdcRef, DESKTOPHORZRES);
  2096. yExtPels = GetDeviceCaps(hdcRef, DESKTOPVERTRES);
  2097. break;
  2098. default:
  2099. VERIFYGDI(FALSE, "SetWinMetaFileBits: Bad mapmode in METAFILEPICT\n");
  2100. goto SWMFB_exit;
  2101. }
  2102. }
  2103. else
  2104. {
  2105. // If the METAFILEPICT is not given, use the MM_ANISOTROPIC mapmode
  2106. // and the default device extents.
  2107. iMapMode = MM_ANISOTROPIC;
  2108. xExtPels = GetDeviceCaps(hdcRef, DESKTOPHORZRES);
  2109. yExtPels = GetDeviceCaps(hdcRef, DESKTOPVERTRES);
  2110. }
  2111. PUTSX("SetWinMetaFileBits: xExtPels:%lX ", xExtPels);
  2112. PUTSX("yExtPels:%lX\n", yExtPels);
  2113. // Create the new 32 bit metafile DC
  2114. if (!(hdcEMF = CreateEnhMetaFileW(hdcRef, (LPWSTR) NULL, lprcFrame,
  2115. (LPWSTR) NULL)))
  2116. goto SWMFB_exit;
  2117. // We want to preserve the original Metafile as a comment only if this
  2118. // metafile wasn't originally an enhanced metafile as indicated by bEmbedEmf.
  2119. PLDC pldc;
  2120. DC_PLDC(hdcEMF,pldc,0);
  2121. pmdcEMF = (PMDC)pldc->pvPMDC;
  2122. #ifndef DO_NOT_EMBED_WINDOWS_METAFILE
  2123. // Embed it only if the mapmode is MM_ANISOTROPIC.
  2124. if (bEmbedEmf && iMapMode == MM_ANISOTROPIC)
  2125. {
  2126. if (!MF_GdiCommentWindowsMetaFile(hdcEMF, nSize, lpMeta16Data))
  2127. {
  2128. HENHMETAFILE hemfTmp;
  2129. ERROR_ASSERT(FALSE, "SetWinMetaFileBits: GdiComment Failed!");
  2130. if (hemfTmp = CloseEnhMetaFile(hdcEMF))
  2131. DeleteEnhMetaFile(hemfTmp);
  2132. goto SWMFB_exit;
  2133. }
  2134. pmdcEMF->fl |= MDC_CHECKSUM; // tell CloseEnhMetaFile we need a checksum
  2135. }
  2136. #endif // DO_NOT_EMBED_WINDOWS_METAFILE
  2137. // Play the 16 bit metafile into the new metafile DC
  2138. if (!SetMapMode(hdcEMF, iMapMode)
  2139. || !SetViewportExtEx(hdcEMF, (int)xExtPels, (int)yExtPels, (LPSIZE) NULL)
  2140. || !SetWindowExtEx (hdcEMF, (int)xExtPels, (int)yExtPels, (LPSIZE) NULL))
  2141. {
  2142. HENHMETAFILE hemfTmp;
  2143. ERROR_ASSERT(FALSE, "SetWinMetaFileBits: unable to PlayMetaFile");
  2144. if (hemfTmp = CloseEnhMetaFile(hdcEMF))
  2145. DeleteEnhMetaFile(hemfTmp);
  2146. goto SWMFB_exit;
  2147. }
  2148. // Ignore the return value from PlayMetaFile because some existing metafiles
  2149. // contains errors (e.g. DeleteObject for a handle that is selected) although
  2150. // they are not fatal.
  2151. (void) PlayMetaFile(hdcEMF, hmf16);
  2152. // Get the 32 bit metafile by closing the 32 bit metafile DC.
  2153. hemf32 = CloseEnhMetaFile(hdcEMF);
  2154. VERIFYGDI(hemf32, "SetWinMetaFileBits: CloseEnhMetaFile failed\n");
  2155. SWMFB_exit:
  2156. if (hdcT)
  2157. {
  2158. if (!DeleteDC(hdcT))
  2159. {
  2160. ASSERTGDI(FALSE, "SetWinMetaFileBits: DeleteDC Failed");
  2161. }
  2162. }
  2163. if (hmf16)
  2164. {
  2165. if (!DeleteMetaFile(hmf16))
  2166. {
  2167. ASSERTGDI(FALSE, "SetWinMetaFileBits: DeleteMetaFile failed");
  2168. }
  2169. }
  2170. ERROR_ASSERT(hemf32, "SetWinMetaFileBits failed");
  2171. return(hemf32);
  2172. }
  2173. /******************************Public*Routine******************************\
  2174. * GetWordCheckSum(UINT cbData, PWORD pwData)
  2175. *
  2176. * Adds cbData/2 number of words pointed to by pwData to provide an
  2177. * additive checksum. If the checksum is valid the sum of all the WORDs
  2178. * should be zero.
  2179. *
  2180. \**************************************************************************/
  2181. WORD GetWordCheckSum(UINT cbData, PWORD pwData)
  2182. {
  2183. WORD wCheckSum = 0;
  2184. UINT cwData = cbData / sizeof(WORD);
  2185. ASSERTGDI(!(cbData%sizeof(WORD)), "GetWordCheckSum data not WORD multiple");
  2186. ASSERTGDI(!((ULONG_PTR)pwData%sizeof(WORD)), "GetWordCheckSum data not WORD aligned");
  2187. while (cwData--)
  2188. wCheckSum += *pwData++;
  2189. return(wCheckSum);
  2190. }
  2191. DWORD GetDWordCheckSum(UINT cbData, PDWORD pdwData)
  2192. {
  2193. DWORD dwCheckSum = 0;
  2194. UINT cdwData = cbData / sizeof(DWORD);
  2195. ASSERTGDI(!(cbData%sizeof(DWORD)), "GetDWordCheckSum data not DWORD multiple");
  2196. ASSERTGDI(!((ULONG_PTR)pdwData%sizeof(DWORD)), "GetDWordCheckSum data not DWORD aligned");
  2197. while (cdwData--)
  2198. dwCheckSum += *pdwData++;
  2199. return(dwCheckSum);
  2200. }
  2201. /******************************Public*Routine******************************\
  2202. * HENHMETAFILE APIENTRY SetEnhMetaFileBits
  2203. * (
  2204. * UINT nSize,
  2205. * LPBYTE pb
  2206. * )
  2207. *
  2208. * The SetEnhMetaFileBits function creates a memory metafile from the data
  2209. * provided.
  2210. *
  2211. * Parameter Description
  2212. * nSize Specifies the size, in bytes, of the data provided.
  2213. * lpData Points to a buffer that contains the metafile data. It is assumed
  2214. * that the data was previously created using the GetEnhMetaFileBits
  2215. * function.
  2216. *
  2217. * Return Value
  2218. * The return value identifies a memory metafile if the function is successful.
  2219. * Otherwise, the return value is 0.
  2220. *
  2221. * History:
  2222. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  2223. * Wrote it.
  2224. \**************************************************************************/
  2225. extern "C" HENHMETAFILE APIENTRY SetEnhMetaFileBits
  2226. (
  2227. UINT nSize,
  2228. CONST BYTE * pb
  2229. )
  2230. {
  2231. PMF pmf;
  2232. HENHMETAFILE hmf;
  2233. PUTS("SetEnhMetaFileBits\n");
  2234. // Verify nSize is valid.
  2235. if (nSize < sizeof(META_HDR_SIZE_MIN) ||
  2236. nSize < ((PENHMETAHEADER) pb)->nBytes)
  2237. {
  2238. GdiSetLastError(ERROR_INVALID_DATA);
  2239. return((HENHMETAFILE) 0);
  2240. }
  2241. // Allocate and initialize a MF.
  2242. if (!(pmf = pmfAllocMF(0, (PDWORD)pb, (LPWSTR) NULL, NULL, 0, 0)))
  2243. return((HENHMETAFILE) 0);
  2244. // Allocate a local handle.
  2245. hmf = hmfCreate(pmf);
  2246. if (hmf == NULL)
  2247. {
  2248. vFreeMF(pmf);
  2249. }
  2250. // Return the metafile handle.
  2251. return(hmf);
  2252. }
  2253. // Similar to SetEnhMetaFileBits except that hMem is set into the metafile
  2254. // directly. It is assumed that hMem is allocated with the LMEM_FIXED option.
  2255. // For internal use only.
  2256. extern "C" HENHMETAFILE APIENTRY SetEnhMetaFileBitsAlt(HLOCAL hMem, HANDLE hExtra, HANDLE hFile, UINT64 qwFileOffset)
  2257. {
  2258. PMF pmf;
  2259. HENHMETAFILE hmf;
  2260. PUTS("SetEnhMetaFileBitsAlt\n");
  2261. // Allocate and initialize a MF.
  2262. if (!(pmf = pmfAllocMF(ALLOCMF_TRANSFER_BUFFER, (PDWORD) hMem, (LPWSTR) NULL, hFile, qwFileOffset, hExtra)))
  2263. return((HENHMETAFILE) 0);
  2264. // Allocate a local handle.
  2265. hmf = hmfCreate(pmf);
  2266. if (hmf == NULL)
  2267. {
  2268. // If memory got transferred reset it to not transferred state.
  2269. if(pmf->pvLocalCopy)
  2270. {
  2271. pmf->pvLocalCopy = 0;
  2272. }
  2273. vFreeMF(pmf);
  2274. }
  2275. // Return the metafile handle.
  2276. return(hmf);
  2277. }
  2278. /******************************Public*Routine******************************\
  2279. * UINT GetEnhMetaFilePaletteEntries(hEMF, nNumEntries, lpPaletteEntries)
  2280. * HENHMETAFILE hEMF;
  2281. * UINT nNumEntries;
  2282. * LPPALETTEENTRY lpPaletteEntries;
  2283. *
  2284. * The GetEnhMetaFilePaletteEntries function retrieves the palette entries
  2285. * used in a metafile. They include non-duplicate colors defined in
  2286. * CreatePalette and SetPaletteEntries records in a metafile. The
  2287. * palette entries do not contain any peFlags.
  2288. *
  2289. * Parameter Description
  2290. * hEMF Identifies the metafile.
  2291. * nNumEntries Specifies the number of entries in the metafile palette
  2292. * to be retrieved.
  2293. * lpPaletteEntries Points to an array of PALETTEENTRY structures to receive
  2294. * the palette entries. The array must contain at least as
  2295. * many data structures as specified by the nNumEntries
  2296. * parameter. If this parameter is NULL, the function will
  2297. * return the number of entries in the metafile palette.
  2298. *
  2299. * Return Value
  2300. * The return value is the number of entries retrieved from the palette.
  2301. * If no palette is created in the metafile, 0 is returned. If an error
  2302. * occurs, -1 is returned.
  2303. *
  2304. * History:
  2305. * Mon Sep 23 17:41:07 1991 -by- Hock San Lee [hockl]
  2306. * Wrote it.
  2307. \**************************************************************************/
  2308. extern "C" UINT APIENTRY GetEnhMetaFilePaletteEntries
  2309. (
  2310. HENHMETAFILE hemf,
  2311. UINT nNumEntries,
  2312. LPPALETTEENTRY lpPaletteEntries
  2313. )
  2314. {
  2315. PMF pmf = NULL;
  2316. UINT cEntries = GDI_ERROR;
  2317. PEMREOF pmreof = NULL;
  2318. PENHMETAHEADER pmrmf = NULL;
  2319. PUTS("GetEnhMetaFilePaletteEntries\n");
  2320. // Validate the metafile handle.
  2321. if (!(pmf = GET_PMF(hemf)))
  2322. goto GetEnhMetaFilePaletteEntries_exit;
  2323. pmrmf = pmf->emfc.GetEMFHeader();
  2324. if(!pmrmf)
  2325. goto GetEnhMetaFilePaletteEntries_exit;
  2326. pmreof = pmf->emfc.ObtainEOFRecordPtr();
  2327. if(!pmreof)
  2328. {
  2329. cEntries = 0; // We do not have a palette ih the metafile
  2330. goto GetEnhMetaFilePaletteEntries_exit;
  2331. }
  2332. // If lpPaletteEntries is NULL, return the number of entries in the metafile
  2333. // palette.
  2334. if (!lpPaletteEntries)
  2335. {
  2336. cEntries = pmrmf->nPalEntries;
  2337. goto GetEnhMetaFilePaletteEntries_exit;
  2338. }
  2339. // Get the number of entries to copy.
  2340. cEntries = min(nNumEntries,(UINT) pmrmf->nPalEntries);
  2341. ASSERTGDI
  2342. (
  2343. pmrmf->nPalEntries == pmreof->nPalEntries,
  2344. "GetEnhMetaFilePaletteEntries: Bad nPalEntries"
  2345. );
  2346. // Copy the palette.
  2347. RtlCopyMemory
  2348. (
  2349. (PBYTE) lpPaletteEntries,
  2350. (PBYTE) pmreof + pmreof->offPalEntries,
  2351. cEntries * sizeof(PALETTEENTRY)
  2352. );
  2353. // Return the number of entries copied.
  2354. GetEnhMetaFilePaletteEntries_exit:
  2355. if(pmreof)
  2356. pmf->emfc.ReleaseEOFRecordPtr(pmreof);
  2357. return(cEntries);
  2358. }
  2359. /******************************Public*Routine******************************\
  2360. * UINT APIENTRY GetEnhMetaFileHeader(
  2361. * HENHMETAFILE hemf,
  2362. * UINT nSize,
  2363. * LPENHMETAHEADER lpEnhMetaHeader );
  2364. *
  2365. * Returns the metafile header information for hemf.
  2366. * If lpEnhMetaHeader is NULL then the size of the header is returned.
  2367. *
  2368. * This routine supports multiple versions of the metafile header by
  2369. * returning the largest version that fits in the buffer
  2370. *
  2371. * History:
  2372. * 16-Oct-1991 1991 -by- John Colleran [johnc]
  2373. * Wrote it.
  2374. \**************************************************************************/
  2375. extern "C" UINT APIENTRY GetEnhMetaFileHeader
  2376. (
  2377. HENHMETAFILE hemf,
  2378. UINT nSize,
  2379. LPENHMETAHEADER lpEnhMetaHeader
  2380. )
  2381. {
  2382. PMF pmf;
  2383. UINT nCopySize = 0;
  2384. PENHMETAHEADER pmrmf = NULL;
  2385. PUTS("GetEnhMetaFileHeader\n");
  2386. // Validate the metafile handle.
  2387. if (!(pmf = GET_PMF(hemf)))
  2388. {
  2389. ERROR_ASSERT(FALSE, "GetEnhMetaFileHeader invalid metafile handle");
  2390. goto GetEnhMetaFileHeader_exit;
  2391. }
  2392. pmrmf = pmf->emfc.GetEMFHeader();
  2393. if(!pmrmf)
  2394. goto GetEnhMetaFileHeader_exit;
  2395. // Is this just a size query
  2396. if (lpEnhMetaHeader == (LPENHMETAHEADER) NULL)
  2397. {
  2398. nCopySize = pmrmf->nSize;
  2399. goto GetEnhMetaFileHeader_exit;
  2400. }
  2401. // Header request. The size must be large enough to include some version
  2402. // of the header
  2403. if (nSize < META_HDR_SIZE_MIN)
  2404. {
  2405. ERROR_ASSERT(FALSE, "GetEnhMetaFileHeader buffer size too small");
  2406. GdiSetLastError(ERROR_INSUFFICIENT_BUFFER);
  2407. goto GetEnhMetaFileHeader_exit;
  2408. }
  2409. // Figure out which version of the header to copy
  2410. if (nSize < META_HDR_SIZE_VERSION_2 ||
  2411. pmrmf->nSize == META_HDR_SIZE_VERSION_1)
  2412. {
  2413. nCopySize = META_HDR_SIZE_VERSION_1;
  2414. }
  2415. else if (nSize < META_HDR_SIZE_VERSION_3 ||
  2416. pmrmf->nSize == META_HDR_SIZE_VERSION_2)
  2417. {
  2418. nCopySize = META_HDR_SIZE_VERSION_2;
  2419. }
  2420. else
  2421. {
  2422. nCopySize = META_HDR_SIZE_VERSION_3;
  2423. }
  2424. // Copy the ENHMETAHEADER and return its size
  2425. RtlCopyMemory(lpEnhMetaHeader, pmrmf, nCopySize);
  2426. // If an application asks for a version two or three header
  2427. // but the metafile only has a version one header,
  2428. // we can still come up with a valid version two or three header
  2429. // by NULLing out the version two or three data
  2430. // This makes it easier to write an application that just
  2431. // does GetEnhMetaFileHeader with sizeof(ENHMETAHEADER)
  2432. // because it will work on both v1 and v2 and v3 metafiles
  2433. // Same applies to app asking for version three header on a metafile
  2434. // with a version two header
  2435. //
  2436. if (nCopySize == META_HDR_SIZE_VERSION_1 &&
  2437. ((nSize == META_HDR_SIZE_VERSION_2) ||
  2438. (nSize == META_HDR_SIZE_VERSION_3)))
  2439. {
  2440. nCopySize = META_HDR_SIZE_VERSION_2;
  2441. lpEnhMetaHeader->cbPixelFormat = 0;
  2442. lpEnhMetaHeader->offPixelFormat = 0;
  2443. lpEnhMetaHeader->bOpenGL = FALSE;
  2444. }
  2445. if (nCopySize == META_HDR_SIZE_VERSION_2 &&
  2446. nSize == META_HDR_SIZE_VERSION_3)
  2447. {
  2448. nCopySize = META_HDR_SIZE_VERSION_3;
  2449. lpEnhMetaHeader->szlMicrometers.cx = 0;
  2450. lpEnhMetaHeader->szlMicrometers.cy = 0;
  2451. }
  2452. lpEnhMetaHeader->nSize = nCopySize;
  2453. GetEnhMetaFileHeader_exit:
  2454. return nCopySize;
  2455. }
  2456. /******************************Public*Routine******************************\
  2457. * UINT APIENTRY GetEnhMetaFileDescription(
  2458. * HENHMETAFILE hemf,
  2459. * UINT cchBuffer,
  2460. * LPWSTR lpDescription );
  2461. *
  2462. *
  2463. * Returns: size of buffer in char count if successful
  2464. * 0 if no description
  2465. * GDI_ERROR if an error occurs
  2466. *
  2467. * History:
  2468. * 16-Oct-1991 1991 -by- John Colleran [johnc]
  2469. * Wrote it.
  2470. \**************************************************************************/
  2471. extern "C" UINT APIENTRY GetEnhMetaFileDescriptionA(
  2472. HENHMETAFILE hemf,
  2473. UINT cchBuffer,
  2474. LPSTR lpDescription )
  2475. {
  2476. return(InternalGetEnhMetaFileDescription(hemf, cchBuffer, lpDescription, FALSE));
  2477. }
  2478. extern "C" UINT APIENTRY GetEnhMetaFileDescriptionW
  2479. (
  2480. HENHMETAFILE hemf,
  2481. UINT cchBuffer,
  2482. LPWSTR lpDescription
  2483. )
  2484. {
  2485. return(InternalGetEnhMetaFileDescription(hemf, cchBuffer, (LPSTR) lpDescription, TRUE));
  2486. }
  2487. UINT InternalGetEnhMetaFileDescription
  2488. (
  2489. HENHMETAFILE hemf,
  2490. UINT cchBuffer,
  2491. LPSTR lpDescription,
  2492. BOOL bUnicode
  2493. )
  2494. {
  2495. PMF pmf;
  2496. UINT cchRet = GDI_ERROR;
  2497. PENHMETAHEADER pmrmf = NULL;
  2498. LPWSTR pwstr = NULL;
  2499. PUTS("InternalGetEnhMetaFileDescription\n");
  2500. // Validate the metafile handle.
  2501. if (!(pmf = GET_PMF(hemf)))
  2502. {
  2503. ERROR_ASSERT(FALSE, "InternalGetEnhMetaFileDescription: invalid hemf");
  2504. goto InternalGetEnhMetaFileDescription_exit;
  2505. }
  2506. pmrmf = pmf->emfc.GetEMFHeader();
  2507. if(!pmrmf)
  2508. goto InternalGetEnhMetaFileDescription_exit;
  2509. pwstr = (LPWSTR) pmf->emfc.ObtainPtr(pmrmf->offDescription,
  2510. pmrmf->nDescription * sizeof(WCHAR));
  2511. if(!pwstr)
  2512. goto InternalGetEnhMetaFileDescription_exit;
  2513. if (lpDescription == (LPSTR) NULL)
  2514. {
  2515. // Return the size if that's all they want.
  2516. if( bUnicode )
  2517. {
  2518. cchRet = pmrmf->nDescription;
  2519. }
  2520. else
  2521. {
  2522. cchRet = 0;
  2523. RtlUnicodeToMultiByteSize((ULONG*)&cchRet, pwstr,
  2524. (UINT)(pmrmf->nDescription)*sizeof(WCHAR));
  2525. }
  2526. }
  2527. else
  2528. {
  2529. // Copy the data
  2530. if (bUnicode)
  2531. {
  2532. cchRet = min(cchBuffer, (UINT) pmrmf->nDescription);
  2533. RtlCopyMemory
  2534. (
  2535. (PBYTE) lpDescription,
  2536. (PBYTE) pwstr,
  2537. cchRet * sizeof(WCHAR)
  2538. );
  2539. }
  2540. else
  2541. {
  2542. if (pmrmf->nDescription)
  2543. {
  2544. cchRet = WideCharToMultiByte(CP_ACP,
  2545. 0,
  2546. pwstr,
  2547. (UINT) pmrmf->nDescription,
  2548. lpDescription,
  2549. cchBuffer,
  2550. NULL,
  2551. NULL);
  2552. if (cchRet == 0)
  2553. {
  2554. // Unicode to Ansi translation is failed.
  2555. cchRet = (UINT) GDI_ERROR;
  2556. }
  2557. }
  2558. else
  2559. {
  2560. // There is no description.
  2561. cchRet = 0;
  2562. }
  2563. }
  2564. }
  2565. InternalGetEnhMetaFileDescription_exit:
  2566. if(pwstr)
  2567. pmf->emfc.ReleasePtr(pwstr);
  2568. return(cchRet);
  2569. }
  2570. /******************************Public*Routine******************************\
  2571. *
  2572. * GetEnhMetaFilePixelFormat
  2573. *
  2574. * Retrieves the last pixel format set in the given enhanced metafile
  2575. *
  2576. * History:
  2577. * Thu Apr 06 15:07:34 1995 -by- Drew Bliss [drewb]
  2578. * Created
  2579. *
  2580. \**************************************************************************/
  2581. extern "C" UINT APIENTRY GetEnhMetaFilePixelFormat(HENHMETAFILE hemf,
  2582. UINT cbBuffer,
  2583. PIXELFORMATDESCRIPTOR *ppfd)
  2584. {
  2585. PMF pmf;
  2586. UINT cbRet = GDI_ERROR;
  2587. PENHMETAHEADER pmrmf = NULL;
  2588. PBYTE pb = NULL;
  2589. PUTS("GetEnhMetaFilePixelFormat\n");
  2590. // Validate the metafile handle.
  2591. if (!(pmf = GET_PMF(hemf)))
  2592. {
  2593. ERROR_ASSERT(FALSE, "GetEnhMetaFilePixelFormat: invalid hemf");
  2594. GdiSetLastError(ERROR_INVALID_HANDLE);
  2595. goto GetEnhMetaFilePixelFormat_exit;
  2596. }
  2597. pmrmf = pmf->emfc.GetEMFHeader();
  2598. if(!pmrmf)
  2599. goto GetEnhMetaFilePixelFormat_exit;
  2600. // Ensure that this metafile is a version which supports the
  2601. // pixel format information
  2602. if (pmrmf->nSize < META_HDR_SIZE_VERSION_2)
  2603. {
  2604. ERROR_ASSERT(FALSE, "GetEnhMetaFilePixelFormat: invalid hdr version");
  2605. GdiSetLastError(ERROR_INVALID_HANDLE);
  2606. goto GetEnhMetaFilePixelFormat_exit;
  2607. }
  2608. pb = (PBYTE) pmf->emfc.ObtainPtr(pmrmf->offPixelFormat, pmrmf->cbPixelFormat);
  2609. if(!pb)
  2610. {
  2611. goto GetEnhMetaFilePixelFormat_exit;
  2612. }
  2613. cbRet = pmrmf->cbPixelFormat;
  2614. // Copy the data if a buffer is provided and is large enough and
  2615. // there is data to copy
  2616. if (cbRet > 0 && ppfd != NULL && cbBuffer >= cbRet)
  2617. {
  2618. ASSERTGDI(pmrmf->offPixelFormat != 0,
  2619. "cbPixelFormat set but not offPixelFormat\n");
  2620. RtlCopyMemory((PBYTE)ppfd, pb, cbRet);
  2621. }
  2622. GetEnhMetaFilePixelFormat_exit:
  2623. if(pb)
  2624. pmf->emfc.ReleasePtr(pb);
  2625. return cbRet;
  2626. }
  2627. /******************************Public*Routine******************************\
  2628. * BOOL APIENTRY GdiComment( HDC hDC, UINT nSize, LPBYTE lpData )
  2629. *
  2630. * Records a Comment record in a metafile if hDC is a metafile DC otherwise
  2631. * it is a no-op
  2632. *
  2633. *
  2634. * Returns: TRUE if succesful otherwise false
  2635. *
  2636. * History:
  2637. * 16-Oct-1991 1991 -by- John Colleran [johnc]
  2638. * Wrote it.
  2639. \**************************************************************************/
  2640. extern "C" BOOL APIENTRY GdiComment( HDC hdc, UINT nSize, CONST BYTE *lpData )
  2641. {
  2642. BOOL bRet = TRUE;
  2643. PUTS("GdiComment\n");
  2644. if (LO_TYPE(hdc) == LO_ALTDC_TYPE)
  2645. {
  2646. PLDC pldc;
  2647. DC_PLDC(hdc,pldc,FALSE);
  2648. if (pldc->iType == LO_METADC)
  2649. bRet = MF_GdiComment(hdc, nSize, lpData);
  2650. }
  2651. return(bRet);
  2652. }
  2653. /******************************Public*Routine******************************\
  2654. *
  2655. * BOOL IsValidEnhMetaRecord(pht,pemr)
  2656. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  2657. * Wrote it.
  2658. \**************************************************************************/
  2659. extern "C" BOOL APIENTRY IsValidEnhMetaRecord
  2660. (
  2661. PVOID pht,
  2662. PVOID pmrIn
  2663. )
  2664. {
  2665. PUTS("IsValidEnhMetaRecord\n");
  2666. CONST PENHMETARECORD pmr = (CONST PENHMETARECORD)pmrIn;
  2667. if (pmr->iType >= EMR_MIN && pmr->iType <= EMR_MAX)
  2668. {
  2669. return
  2670. (
  2671. (((PMR) pmr)->*afnbMRCheck[((PENHMETARECORD)pmr)->iType - 1])
  2672. (
  2673. (PHANDLETABLE) pht
  2674. )
  2675. );
  2676. }
  2677. EMFVALFAIL(("IsValidEnhMetaFileRecord: failed\n"));
  2678. return(FALSE);
  2679. }
  2680. /******************************Public*Routine******************************\
  2681. *
  2682. * BOOL IsValidEnhMetaRecordOffExt(pht,pemr,Off,Ext)
  2683. * Tue Sep 03 11:21:14 1991 -by- Hock San Lee [hockl]
  2684. * Wrote it.
  2685. \**************************************************************************/
  2686. extern "C" BOOL APIENTRY IsValidEnhMetaRecordOffExt
  2687. (
  2688. PVOID pht,
  2689. PVOID pmrIn,
  2690. DWORD Off,
  2691. DWORD Ext
  2692. )
  2693. {
  2694. PUTS("IsValidEnhMetaRecordOffExt\n");
  2695. CONST PENHMETARECORD pmr = (CONST PENHMETARECORD)pmrIn;
  2696. if (pmr->iType >= EMR_MIN && pmr->iType <= EMR_MAX)
  2697. {
  2698. return ((PMR)pmr)->bValidOffExt((PHANDLETABLE)pht, Off, Ext);
  2699. }
  2700. EMFVALFAIL(("IsValidEnhMetaRecordOffExt: failed\n"));
  2701. return(FALSE);
  2702. }