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.

434 lines
13 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. #define _GDI32_
  13. #define WMF_KEY 0x9ac6cdd7l
  14. extern "C" {
  15. #if defined(_GDIPLUS_)
  16. #include <gpprefix.h>
  17. #endif
  18. #include <string.h>
  19. #include <stdio.h>
  20. #include <nt.h>
  21. #include <ntrtl.h> // defines but doesn't use ASSERT and ASSERTMSG
  22. #undef ASSERT
  23. #undef ASSERTMSG
  24. #include <nturtl.h>
  25. #include <stddef.h>
  26. #include <windows.h> // GDI function declarations.
  27. #include <winspool.h>
  28. #include "..\runtime\debug.h"
  29. #include "mf3216Debug.h"
  30. #define ERROR_ASSERT(cond, msg) ASSERTMSG((cond), (msg))
  31. //#include "nlsconv.h" // UNICODE helpers
  32. //#include "firewall.h"
  33. #define __CPLUSPLUS
  34. #include <winspool.h>
  35. #include <w32gdip.h>
  36. #include "ntgdistr.h"
  37. #include "winddi.h"
  38. #include "hmgshare.h"
  39. #include "icm.h"
  40. #include "local.h" // Local object support.
  41. #include "gdiicm.h"
  42. #include "metadef.h" // Metafile record type constants.
  43. #include "metarec.h"
  44. #include "mf16.h"
  45. #include "ntgdi.h"
  46. #include "glsup.h"
  47. #include "mf3216.h"
  48. #include <GdiplusEnums.h>
  49. }
  50. #undef WARNING
  51. #define WARNING(msg) WARNING1(msg)
  52. #include "rectl.hxx"
  53. #include "mfdc.hxx" // Metafile DC declarations.
  54. #define USE(x) (x)
  55. #include "mfrec.hxx" // Metafile record class declarations.
  56. #undef USE
  57. #undef WARNING
  58. #define WARNING SAVE_WARNING
  59. #include "Metafile.hpp"
  60. DWORD GetDWordCheckSum(UINT cbData, PDWORD pdwData);
  61. #define DbgPrint printf
  62. static inline void PvmsoFromW(void *pv, WORD w)
  63. { ((BYTE*)pv)[0] = BYTE(w); ((BYTE*)pv)[1] = BYTE(w >> 8); }
  64. static inline void PvmsoFromU(void *pv, ULONG u)
  65. { ((BYTE*)pv)[0] = BYTE(u);
  66. ((BYTE*)pv)[1] = BYTE(u >> 8);
  67. ((BYTE*)pv)[2] = BYTE(u >> 16);
  68. ((BYTE*)pv)[3] = BYTE(u >> 24); }
  69. #ifdef DBG
  70. static BOOL g_outputEMF = FALSE;
  71. #endif
  72. /******************************Public*Routine******************************\
  73. * GetWordCheckSum(UINT cbData, PWORD pwData)
  74. *
  75. * Adds cbData/2 number of words pointed to by pwData to provide an
  76. * additive checksum. If the checksum is valid the sum of all the WORDs
  77. * should be zero.
  78. *
  79. \**************************************************************************/
  80. static DWORD GetDWordCheckSum(UINT cbData, PDWORD pdwData)
  81. {
  82. DWORD dwCheckSum = 0;
  83. UINT cdwData = cbData / sizeof(DWORD);
  84. ASSERTGDI(!(cbData%sizeof(DWORD)), "GetDWordCheckSum data not DWORD multiple");
  85. ASSERTGDI(!((ULONG_PTR)pdwData%sizeof(DWORD)), "GetDWordCheckSum data not DWORD aligned");
  86. while (cdwData--)
  87. dwCheckSum += *pdwData++;
  88. return(dwCheckSum);
  89. }
  90. /******************************Public*Routine******************************\
  91. * UINT APIENTRY GetWinMetaFileBits(
  92. * HENHMETAFILE hemf,
  93. * UINT nSize,
  94. * LPBYTE lpData
  95. * INT iMapMode,
  96. * HDC hdcRef)
  97. *
  98. * The GetWinMetaFileBits function returns the metafile records of the
  99. * specified enhanced metafile in the Windows 3.0 format and copies
  100. * them into the buffer specified.
  101. *
  102. * Parameter Description
  103. * hemf Identifies the metafile.
  104. * nSize Specifies the size of the buffer reserved for the data. Only this
  105. * many bytes will be written.
  106. * lpData Points to the buffer to receive the metafile data. If this
  107. * pointer is NULL, the function returns the size necessary to hold
  108. * the data.
  109. * iMapMode the desired mapping mode of the metafile contents to be returned
  110. * hdcRef defines the units of the metafile to be returned
  111. *
  112. * Return Value
  113. * The return value is the size of the metafile data in bytes. If an error
  114. * occurs, 0 is returned.
  115. *
  116. * Comments
  117. * The handle used as the hemf parameter does NOT become invalid when the
  118. * GetWinMetaFileBits function returns.
  119. *
  120. * History:
  121. * Thu Apr 8 14:22:23 1993 -by- Hock San Lee [hockl]
  122. * Rewrote it.
  123. * 02-Jan-1992 -by- John Colleran [johnc]
  124. * Wrote it.
  125. \**************************************************************************/
  126. UINT GdipGetWinMetaFileBitsEx
  127. (
  128. HENHMETAFILE hemf,
  129. UINT cbData16,
  130. LPBYTE pData16,
  131. INT iMapMode,
  132. INT eFlags
  133. )
  134. {
  135. BOOL bEmbedEmf = ((eFlags & EmfToWmfBitsFlagsEmbedEmf) == EmfToWmfBitsFlagsEmbedEmf);
  136. BOOL bXorPass = !((eFlags & EmfToWmfBitsFlagsNoXORClip) == EmfToWmfBitsFlagsNoXORClip);
  137. UINT fConverter = 0;
  138. if (bEmbedEmf)
  139. {
  140. fConverter |= MF3216_INCLUDE_WIN32MF;
  141. }
  142. if (bXorPass)
  143. {
  144. fConverter |= GPMF3216_INCLUDE_XORPATH;
  145. }
  146. PEMRGDICOMMENT_WINDOWS_METAFILE pemrWinMF;
  147. UINT uiHeaderSize ;
  148. // Always go through Cleanup to return...
  149. UINT returnVal = 0 ; // Pessimistic Case
  150. PENHMETAHEADER pmfh = NULL;
  151. PBYTE pemfb = NULL;
  152. PUTS("GetWinMetaFileBits\n");
  153. // Validate mapmode.
  154. if ((iMapMode < MM_MIN) ||
  155. (iMapMode > MM_MAX) ||
  156. GetObjectTypeInternal(hemf) != OBJ_ENHMETAFILE)
  157. {
  158. ERROR_ASSERT(FALSE, "GetWinMetaFileBits: Bad mapmode");
  159. return 0;
  160. }
  161. if(hemf == (HENHMETAFILE) 0 )
  162. {
  163. ERROR_ASSERT(FALSE, "GetWinMetaFileBits: Bad HEMF");
  164. return 0;
  165. }
  166. // Validate the metafile handle.
  167. // GillesK:
  168. // We cannot access the MF object from the handle given, but all we need
  169. // is the PENHMETAHEADER, so get it
  170. uiHeaderSize = GetEnhMetaFileHeader(hemf, // handle to enhanced metafile
  171. 0, // size of buffer
  172. NULL); // data buffer
  173. // We have the size of the header that we need, so Allocate the header....
  174. // We must make sure to free it after we are done....
  175. pmfh = (PENHMETAHEADER)GlobalAlloc(GMEM_FIXED,uiHeaderSize);
  176. if(pmfh == NULL)
  177. {
  178. goto Cleanup ;
  179. }
  180. uiHeaderSize = GetEnhMetaFileHeader(hemf, // handle to enhanced metafile
  181. uiHeaderSize, // size of buffer
  182. pmfh); // data buffer
  183. ERROR_ASSERT(pmfh->iType == EMR_HEADER, "GetWinMetaFileBits: invalid data");
  184. // ASSERTGDI(pmf->pmrmf->iType == EMR_HEADER, "GetWinMetaFileBits: invalid data");
  185. #ifndef DO_NOT_USE_EMBEDDED_WINDOWS_METAFILE
  186. // See if the this was originally an old style metafile and if it has
  187. // an encapsulated original
  188. pemrWinMF = (PEMRGDICOMMENT_WINDOWS_METAFILE)
  189. ((PBYTE) pmfh + ((PENHMETAHEADER) pmfh)->nSize);
  190. if (((PMRGDICOMMENT) pemrWinMF)->bIsWindowsMetaFile())
  191. {
  192. // Make sure that this is what we want and verify checksum
  193. if (iMapMode != MM_ANISOTROPIC)
  194. {
  195. PUTS("GetWinMetaFileBits: Requested and embedded metafile mapmodes mismatch\n");
  196. }
  197. else if ((pemrWinMF->nVersion != METAVERSION300 &&
  198. pemrWinMF->nVersion != METAVERSION100)
  199. || pemrWinMF->fFlags != 0)
  200. {
  201. // In this release, we can only handle the given metafile
  202. // versions. If we return a version that we don't recognize,
  203. // the app will not be able to play that metafile later on!
  204. //VERIFYGDI(FALSE, "GetWinMetaFileBits: Unrecognized Windows metafile\n");
  205. }
  206. else if (GetDWordCheckSum((UINT) pmfh->nBytes, (PDWORD) pmfh))
  207. {
  208. PUTS("GetWinMetaFileBits: Metafile has been modified\n");
  209. }
  210. else
  211. {
  212. PUTS("GetWinMetaFileBits: Returning embedded Windows metafile\n");
  213. if (pData16)
  214. {
  215. if (cbData16 < pemrWinMF->cbWinMetaFile)
  216. {
  217. ERROR_ASSERT(FALSE, "GetWinMetaFileBits: insufficient buffer");
  218. //GdiSetLastError(ERROR_INSUFFICIENT_BUFFER);
  219. goto Cleanup ;
  220. }
  221. RtlCopyMemory(pData16,
  222. (PBYTE) &pemrWinMF[1],
  223. pemrWinMF->cbWinMetaFile);
  224. }
  225. returnVal = pemrWinMF->cbWinMetaFile ;
  226. goto Cleanup ;
  227. }
  228. // Either the enhanced metafile containing an embedded Windows
  229. // metafile has been modified or the embedded Windows metafile
  230. // is not what we want. Since the original format is Windows
  231. // format, we will not embed the enhanced metafile in the
  232. // returned Windows metafile.
  233. PUTS("GetWinMetaFileBits: Skipping embedded windows metafile\n");
  234. fConverter &= ~MF3216_INCLUDE_WIN32MF;
  235. }
  236. #endif // DO_NOT_USE_EMBEDDED_WINDOWS_METAFILE
  237. // Tell the converter to emit the Enhanced metafile as a comment only if
  238. // this metafile is not previously a Windows metafile
  239. if (fConverter & MF3216_INCLUDE_WIN32MF)
  240. {
  241. PUTS("GetWinMetaFileBits: Embedding enhanced metafile\n");
  242. }
  243. else
  244. {
  245. PUTS("GetWinMetaFileBits: No embedding of enhanced metafile\n");
  246. }
  247. uiHeaderSize = GetEnhMetaFileBits(hemf, 0, NULL);
  248. // Allocate the memory to receive the enhance MetaFile
  249. pemfb = (PBYTE) GlobalAlloc(GMEM_FIXED, uiHeaderSize);
  250. if( pemfb == NULL )
  251. {
  252. goto Cleanup;
  253. }
  254. uiHeaderSize = GetEnhMetaFileBits(hemf, uiHeaderSize, pemfb);
  255. #if DBG
  256. // This in only here for debugging... Save the initial EMF file to be
  257. // able to compare later
  258. // We need the ASCII version for it to work with Win98
  259. if (g_outputEMF)
  260. {
  261. ::DeleteEnhMetaFile(::CopyEnhMetaFileA(hemf, "C:\\emf.emf" ));
  262. }
  263. #endif
  264. returnVal = (GdipConvertEmfToWmf((PBYTE) pemfb, cbData16, pData16,
  265. iMapMode, NULL,
  266. fConverter));
  267. if(!returnVal && bXorPass)
  268. {
  269. // If we fail then call without the XOR PASS
  270. returnVal = (GdipConvertEmfToWmf((PBYTE) pemfb, cbData16, pData16,
  271. iMapMode, NULL,
  272. fConverter & ~GPMF3216_INCLUDE_XORPATH));
  273. #if DBG
  274. if( !returnVal )
  275. {
  276. // The Win32API version needs an hdcRef, get the screen DC and
  277. // do it
  278. HDC newhdc = ::GetDC(NULL);
  279. // If we fail again then go back to Windows
  280. ASSERT(::GetWinMetaFileBits(hemf, cbData16, pData16,
  281. iMapMode, newhdc) == 0);
  282. ::ReleaseDC(NULL, newhdc);
  283. }
  284. #endif
  285. }
  286. Cleanup:
  287. if(pmfh != NULL)
  288. {
  289. GlobalFree(pmfh);
  290. }
  291. if(pemfb != NULL)
  292. {
  293. GlobalFree(pemfb);
  294. }
  295. return returnVal;
  296. }
  297. extern "C"
  298. UINT ConvertEmfToPlaceableWmf
  299. (
  300. HENHMETAFILE hemf,
  301. UINT cbData16,
  302. LPBYTE pData16,
  303. INT iMapMode,
  304. INT eFlags
  305. )
  306. {
  307. UINT uiRet ;
  308. ENHMETAHEADER l_emetaHeader ;
  309. BOOL placeable = (eFlags & EmfToWmfBitsFlagsIncludePlaceable) == EmfToWmfBitsFlagsIncludePlaceable;
  310. // Call the GdipGetWinMetaFileBits
  311. // And add the header information afterwards
  312. // If we have a buffer then leave room for the header
  313. uiRet = GdipGetWinMetaFileBitsEx(hemf,
  314. cbData16,
  315. pData16?pData16+(placeable?22:0):pData16,
  316. iMapMode,
  317. eFlags);
  318. // If the client only wants the size of the buffer, then we return the size
  319. // of the buffer plus the size of the header
  320. if(uiRet != 0 && placeable)
  321. {
  322. // If the previous call succeeded then we will append the size of the
  323. // header to the return value
  324. uiRet += 22;
  325. if(pData16 != NULL)
  326. {
  327. BYTE *rgb = pData16;
  328. PvmsoFromU(rgb , WMF_KEY);
  329. PvmsoFromW(rgb+ 4, 0);
  330. PvmsoFromU(rgb+16, 0);
  331. if(GetEnhMetaFileHeader(hemf, sizeof(l_emetaHeader), &l_emetaHeader))
  332. {
  333. FLOAT pp01mm = ((((FLOAT)l_emetaHeader.szlDevice.cx)/l_emetaHeader.szlMillimeters.cx/100.0f +
  334. (FLOAT)l_emetaHeader.szlDevice.cy)/l_emetaHeader.szlMillimeters.cy/100.0f)/2.0f;
  335. PvmsoFromW(rgb+ 6, SHORT((FLOAT)l_emetaHeader.rclFrame.left*pp01mm));
  336. PvmsoFromW(rgb+ 8, SHORT((FLOAT)l_emetaHeader.rclFrame.top*pp01mm));
  337. PvmsoFromW(rgb+10, SHORT((FLOAT)l_emetaHeader.rclFrame.right*pp01mm));
  338. PvmsoFromW(rgb+12, SHORT((FLOAT)l_emetaHeader.rclFrame.bottom*pp01mm));
  339. PvmsoFromW(rgb+14, SHORT(pp01mm*2540.0f));
  340. }
  341. else
  342. {
  343. // If we cant get the information from the EMF then default
  344. PvmsoFromW(rgb+ 6, SHORT(0));
  345. PvmsoFromW(rgb+ 8, SHORT(0));
  346. PvmsoFromW(rgb+10, SHORT(2000));
  347. PvmsoFromW(rgb+12, SHORT(2000));
  348. PvmsoFromW(rgb+14, 96);
  349. }
  350. /* Checksum. This works on any byte order machine because the data is swapped
  351. consistently. */
  352. USHORT *pu = (USHORT*)rgb;
  353. USHORT u = 0;
  354. /* The checksum is even parity. */
  355. while (pu < (USHORT*)(rgb+20))
  356. u ^= *pu++;
  357. *pu = u;
  358. }
  359. }
  360. return uiRet ;
  361. }