Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

574 lines
14 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WGMETA.C
  8. * WOW32 16-bit GDI API support
  9. *
  10. * History:
  11. * Created 07-Mar-1991 by Jeff Parsons (jeffpar)
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. MODNAME(wgmeta.c);
  16. typedef METAHEADER UNALIGNED *PMETAHEADER16;
  17. // WARNING: This function may cause 16-bit memory to move
  18. VOID CopyMetaFile16FromHMF32(HAND16 hMF16, HMETAFILE hMF32)
  19. {
  20. UINT cbMF32, cbMF16;
  21. VPVOID vp;
  22. PBYTE pMF16;
  23. if((vp = GlobalLock16(hMF16, &cbMF16)) && hMF32) {
  24. GETMISCPTR(vp, pMF16);
  25. cbMF32 = GetMetaFileBitsEx(hMF32, 0, NULL);
  26. // Verify these are the same size within the 16-bit kernel memory
  27. // allocation granularity
  28. WOW32WARNMSGF((abs(cbMF16 - cbMF32) < 32),
  29. ("WOW32: Size MF16 = %lu MF32 = %lu\n", cbMF16, cbMF32));
  30. // copy the bits from the 32-bit metafile to the 16-bit metafile memory
  31. cbMF32 = GetMetaFileBitsEx(hMF32, min(cbMF16, cbMF32), pMF16);
  32. GlobalUnlock16(hMF16);
  33. FLUSHVDMPTR(vp, cbMF32, pMF16);
  34. FREEMISCPTR(pMF16);
  35. }
  36. }
  37. // WARNING: This function may cause 16-bit memory to move
  38. HAND16 WinMetaFileFromHMF(HMETAFILE hmf, BOOL fFreeOriginal)
  39. {
  40. UINT cbMetaData;
  41. VPVOID vpMetaData;
  42. PBYTE pMetaData;
  43. HAND16 h16;
  44. /*
  45. * Under Windows Metafiles were merely Global Handle to memory
  46. * so we have to mimick that behavior because some apps "operate"
  47. * on metafile handles directly. (WinWord and PowerPoint to
  48. * GlobalSize and GlobalAlloc to size and create metafiles)
  49. */
  50. cbMetaData = GetMetaFileBitsEx(hmf, 0, NULL);
  51. if (!cbMetaData)
  52. return((HAND16)NULL);
  53. /*
  54. * Win 3.1 allocates extra space in MetaFile and OLE2 checks for this.
  55. * METAHEADER is defined to be the same size as the 16-bit structure.
  56. */
  57. cbMetaData += sizeof(METAHEADER);
  58. vpMetaData = GlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE, cbMetaData, &h16);
  59. if (!vpMetaData)
  60. return((HAND16)NULL);
  61. GETOPTPTR(vpMetaData, 0, pMetaData);
  62. if (GetMetaFileBitsEx(hmf, cbMetaData, pMetaData)) {
  63. GlobalUnlock16(h16);
  64. } else {
  65. GlobalUnlockFree16(vpMetaData);
  66. return((HAND16)NULL);
  67. }
  68. if (fFreeOriginal)
  69. DeleteMetaFile(hmf);
  70. return(h16);
  71. }
  72. HMETAFILE HMFFromWinMetaFile(HAND16 h16, BOOL fFreeOriginal)
  73. {
  74. INT cb;
  75. VPVOID vp;
  76. HMETAFILE hmf = (HMETAFILE)0;
  77. PMETAHEADER16 pMFH16;
  78. vp = GlobalLock16(h16, &cb);
  79. if (vp) {
  80. GETMISCPTR(vp, pMFH16);
  81. hmf = SetMetaFileBitsEx(cb, (LPBYTE)pMFH16);
  82. if (fFreeOriginal)
  83. GlobalUnlockFree16(vp);
  84. else
  85. GlobalUnlock16(h16);
  86. FREEMISCPTR(pMFH16);
  87. }
  88. return(hmf);
  89. }
  90. ULONG FASTCALL WG32CloseMetaFile(PVDMFRAME pFrame)
  91. {
  92. HMETAFILE hmf;
  93. ULONG ulRet = 0;
  94. register PCLOSEMETAFILE16 parg16;
  95. GETARGPTR(pFrame, sizeof(CLOSEMETAFILE16), parg16);
  96. hmf = CloseMetaFile(HDC32(parg16->f1));
  97. if (hmf)
  98. ulRet = (ULONG)WinMetaFileFromHMF(hmf, TRUE);
  99. // WARNING: 16-bit memory may have moved - invalidate flat pointers now
  100. FREEVDMPTR(pFrame);
  101. FREEARGPTR(parg16);
  102. RETURN(ulRet);
  103. }
  104. ULONG FASTCALL WG32CopyMetaFile(PVDMFRAME pFrame)
  105. {
  106. ULONG ul;
  107. PSZ psz2;
  108. HMETAFILE hmfNew;
  109. HMETAFILE hmf;
  110. register PCOPYMETAFILE16 parg16;
  111. GETARGPTR(pFrame, sizeof(COPYMETAFILE16), parg16);
  112. GETPSZPTR(parg16->f2, psz2);
  113. if (psz2) {
  114. hmf = HMFFromWinMetaFile(parg16->f1, FALSE);
  115. hmfNew = CopyMetaFile(hmf, psz2);
  116. DeleteMetaFile(hmf);
  117. ul = (ULONG)WinMetaFileFromHMF(hmfNew, TRUE);
  118. // WARNING: 16-bit memory may have moved - invalidate flat pointers now
  119. FREEVDMPTR(pFrame);
  120. FREEARGPTR(parg16);
  121. FREEPSZPTR(psz2);
  122. } else {
  123. UINT cb;
  124. VPVOID vp, vpNew;
  125. PBYTE pMF, pMFNew;
  126. HAND16 h16New, h16;
  127. h16 = (HAND16)parg16->f1;
  128. ul = (ULONG) NULL;
  129. vp = GlobalLock16(h16, &cb);
  130. if (vp) {
  131. /*
  132. * Windows app such as WinWord uses GlobalSize to determine
  133. * the size of the metafile. However, this size can be larger
  134. * than the true size of a metafile. We have to make sure that
  135. * both source and destination sizes are identical so that
  136. * WinWord doesn't crash.
  137. */
  138. vpNew = GlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE, cb, &h16New);
  139. // 16-bit memory may have moved - invalidate flat pointers now
  140. FREEVDMPTR(pFrame);
  141. FREEARGPTR(parg16);
  142. FREEPSZPTR(psz2);
  143. if (vpNew) {
  144. GETMISCPTR(vp, pMF);
  145. GETOPTPTR(vpNew, 0, pMFNew);
  146. RtlCopyMemory(pMFNew, pMF, cb);
  147. GlobalUnlock16(h16New);
  148. FLUSHVDMPTR(vpNew, cb, pMFNew);
  149. FREEOPTPTR(pMFNew);
  150. ul = h16New;
  151. }
  152. GlobalUnlock16(h16);
  153. FREEMISCPTR(pMF);
  154. }
  155. }
  156. FREEPSZPTR(psz2);
  157. FREEARGPTR(parg16);
  158. RETURN(ul);
  159. }
  160. ULONG FASTCALL WG32CreateMetaFile(PVDMFRAME pFrame)
  161. {
  162. ULONG ul;
  163. PSZ psz1;
  164. register PCREATEMETAFILE16 parg16;
  165. GETARGPTR(pFrame, sizeof(CREATEMETAFILE16), parg16);
  166. GETPSZPTR(parg16->f1, psz1);
  167. ul = GETHDC16(CreateMetaFile(psz1));
  168. FREEPSZPTR(psz1);
  169. FREEARGPTR(parg16);
  170. RETURN(ul);
  171. }
  172. //
  173. // This routine does what the 16-bit parameter validation layer would
  174. // normally do for metafile handles, but since it is currently disabled,
  175. // we'll do it here to fix WordPerfect that relies on it. Once true
  176. // win31-style parameter validation has been re-enabled for metafile
  177. // handles, all code within the ifndefs here and in WG32DeleteMetaFile
  178. // can be removed.
  179. //
  180. #ifndef PARAMETER_VALIDATION_16_RE_ENABLED
  181. #define MEMORYMETAFILE 1
  182. #define DISKMETAFILE 2
  183. #define HEADERSIZE (sizeof(METAHEADER)/sizeof(WORD))
  184. #define METAVERSION 0x0300
  185. #define METAVERSION100 0x0100
  186. BOOL IsValidMetaFile16(PMETAHEADER16 lpMetaData)
  187. {
  188. BOOL sts = FALSE;
  189. sts = (lpMetaData->mtType == MEMORYMETAFILE ||
  190. lpMetaData->mtType == DISKMETAFILE) &&
  191. (lpMetaData->mtHeaderSize == HEADERSIZE) &&
  192. ((lpMetaData->mtVersion ==METAVERSION) ||
  193. (lpMetaData->mtVersion ==METAVERSION100)) ;
  194. return sts;
  195. }
  196. #endif
  197. ULONG FASTCALL WG32DeleteMetaFile(PVDMFRAME pFrame)
  198. {
  199. ULONG ul = FALSE;
  200. VPVOID vp;
  201. #ifndef PARAMETER_VALIDATION_16_RE_ENABLED
  202. PMETAHEADER16 lpMetaData;
  203. #endif
  204. register PDELETEMETAFILE16 parg16;
  205. GETARGPTR(pFrame, sizeof(DELETEMETAFILE16), parg16);
  206. if (vp = GlobalLock16(parg16->f1,NULL)) {
  207. #ifdef PARAMETER_VALIDATION_16_RE_ENABLED
  208. GlobalUnlockFree16(vp);
  209. ul = TRUE;
  210. #else
  211. GETVDMPTR(vp, 1, lpMetaData);
  212. if (IsValidMetaFile16(lpMetaData)) {
  213. GlobalUnlockFree16(vp);
  214. ul = TRUE;
  215. }
  216. FREEVDMPTR(lpMetaData);
  217. #endif
  218. }
  219. // If this metafile was in DDE conversation, then DDE cleanup code
  220. // needs to free its 32 bit counter part. So give DDE clean up
  221. // code a chance.
  222. // ChandanC
  223. W32DdeFreeHandle16 (parg16->f1);
  224. FREEARGPTR(parg16);
  225. RETURN(ul);
  226. }
  227. INT WG32EnumMetaFileCallBack(HDC hdc, LPHANDLETABLE lpht, LPMETARECORD lpMR, LONG nObj, PMETADATA pMetaData )
  228. {
  229. INT iReturn;
  230. DWORD nWords;
  231. // update object table if we have one
  232. if (pMetaData->parmemp.vpHandleTable)
  233. PUTHANDLETABLE16(pMetaData->parmemp.vpHandleTable,nObj,lpht);
  234. // update MetaRecord
  235. // don't trash the heap with a bogus record, halt the enumeration
  236. nWords = lpMR->rdSize;
  237. if (nWords > pMetaData->mtMaxRecordSize) {
  238. LOGDEBUG(0,("WOW:bad metafile record during enumeration\n"));
  239. WOW32ASSERT(FALSE); // contact barryb
  240. return 0; // all done
  241. }
  242. putstr16(pMetaData->parmemp.vpMetaRecord, (LPSZ)lpMR, nWords*sizeof(WORD));
  243. CallBack16(RET_ENUMMETAFILEPROC, (PPARM16)&pMetaData->parmemp, pMetaData->vpfnEnumMetaFileProc, (PVPVOID)&iReturn);
  244. // update the metarec in case the app altered it (Approach does)
  245. getstr16(pMetaData->parmemp.vpMetaRecord, (LPSZ)lpMR, nWords*sizeof(WORD));
  246. // update object table if we have one
  247. if (pMetaData->parmemp.vpHandleTable)
  248. GETHANDLETABLE16(pMetaData->parmemp.vpHandleTable,nObj,lpht);
  249. return (SHORT)iReturn;
  250. hdc; // quiet the compilier; we already know the DC
  251. }
  252. ULONG FASTCALL WG32EnumMetaFile(PVDMFRAME pFrame)
  253. {
  254. ULONG ul = 0;
  255. register PENUMMETAFILE16 parg16;
  256. METADATA metadata;
  257. VPVOID vpMetaFile = (VPVOID) NULL;
  258. PBYTE pMetaFile;
  259. HMETAFILE hmf = (HMETAFILE) 0;
  260. HAND16 hMetaFile16;
  261. HDC hDC = 0;
  262. GETARGPTR(pFrame, sizeof(ENUMMETAFILE16), parg16);
  263. hMetaFile16 = parg16->f2;
  264. metadata.vpfnEnumMetaFileProc = DWORD32(parg16->f3);
  265. metadata.parmemp.vpData = (VPVOID)DWORD32(parg16->f4);
  266. metadata.parmemp.vpMetaRecord = (VPVOID) NULL;
  267. metadata.parmemp.vpHandleTable = (VPVOID) NULL;
  268. metadata.parmemp.hdc = parg16->f1;
  269. // WinWord never calls SetMetaFileBits; they peeked and know that
  270. // a metafile is really a GlobalHandle in Windows so we have
  271. // to look for that case.
  272. hmf = HMFFromWinMetaFile(hMetaFile16, FALSE);
  273. if (!hmf)
  274. goto EMF_Exit;
  275. // Get the metafile bits so we can get max record size and number of objects
  276. vpMetaFile = GlobalLock16(hMetaFile16, NULL);
  277. FREEARGPTR(parg16); // memory may have moved
  278. FREEVDMPTR(pFrame);
  279. if (!vpMetaFile)
  280. goto EMF_Exit;
  281. GETOPTPTR(vpMetaFile, 0, pMetaFile);
  282. if (!pMetaFile)
  283. goto EMF_Exit;
  284. metadata.parmemp.nObjects = ((PMETAHEADER16)pMetaFile)->mtNoObjects;
  285. metadata.mtMaxRecordSize = ((PMETAHEADER16)pMetaFile)->mtMaxRecord;
  286. if (metadata.parmemp.nObjects)
  287. {
  288. PBYTE pHT;
  289. DWORD cb = ((PMETAHEADER16)pMetaFile)->mtNoObjects*sizeof(HAND16);
  290. metadata.parmemp.vpHandleTable = GlobalAllocLock16(GMEM_MOVEABLE, cb, NULL);
  291. FREEOPTPTR(pMetaFile); // memory may have moved
  292. FREEARGPTR(parg16);
  293. FREEVDMPTR(pFrame);
  294. if (!metadata.parmemp.vpHandleTable)
  295. goto EMF_Exit;
  296. GETOPTPTR(metadata.parmemp.vpHandleTable, 0, pHT);
  297. RtlZeroMemory(pHT, cb);
  298. }
  299. metadata.parmemp.vpMetaRecord = GlobalAllocLock16(GMEM_MOVEABLE, metadata.mtMaxRecordSize*sizeof(WORD), NULL);
  300. FREEOPTPTR(pMetaFile); // memory may have moved
  301. FREEARGPTR(parg16);
  302. FREEVDMPTR(pFrame);
  303. if (!metadata.parmemp.vpMetaRecord)
  304. goto EMF_Exit;
  305. // Corel Draw passes a NULL hDC, we'll create a dummy to keep GDI32 happy.
  306. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_GETDUMMYDC) {
  307. if ((hDC = HDC32(metadata.parmemp.hdc)) == 0) {
  308. hDC = CreateMetaFile(NULL);
  309. }
  310. }
  311. else {
  312. hDC = HDC32(metadata.parmemp.hdc);
  313. }
  314. // When processing metafile, access2.0 faults while receiving
  315. // WM_DEVMODECHANGE so we block that particular message when
  316. // in EnumMetaFile
  317. if ( CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_EATDEVMODEMSG) {
  318. CURRENTPTD()->dwFlags |= TDF_EATDEVMODEMSG;
  319. }
  320. ul = GETBOOL16(EnumMetaFile(hDC,
  321. hmf,
  322. (MFENUMPROC)WG32EnumMetaFileCallBack,
  323. ((LPARAM)(LPVOID)&metadata)));
  324. CURRENTPTD()->dwFlags &= ~TDF_EATDEVMODEMSG;
  325. // 16-bit memory may have moved - nothing to do as no flat ptrs exist now
  326. // copy the 32-bit metafile back to 16-bit land (the app may have altered
  327. // some of the metarecs in its MetaRecCallBackFunc -- Approach does)
  328. CopyMetaFile16FromHMF32(hMetaFile16, hmf);
  329. // Cleanup the dummy hDC created for Corel Draw 5.0.
  330. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_GETDUMMYDC) {
  331. if (HDC32(metadata.parmemp.hdc) == 0) {
  332. DeleteMetaFile(CloseMetaFile(hDC));
  333. }
  334. }
  335. EMF_Exit:
  336. if (vpMetaFile)
  337. GlobalUnlock16(hMetaFile16);
  338. if (hmf)
  339. DeleteMetaFile(hmf);
  340. if (metadata.parmemp.vpHandleTable)
  341. GlobalUnlockFree16(metadata.parmemp.vpHandleTable);
  342. if (metadata.parmemp.vpMetaRecord)
  343. GlobalUnlockFree16(metadata.parmemp.vpMetaRecord);
  344. FREEARGPTR(parg16);
  345. RETURN(ul);
  346. }
  347. ULONG FASTCALL WG32GetMetaFile(PVDMFRAME pFrame)
  348. {
  349. ULONG ul;
  350. PSZ psz1;
  351. HMETAFILE hmf;
  352. register PGETMETAFILE16 parg16;
  353. GETARGPTR(pFrame, sizeof(GETMETAFILE16), parg16);
  354. GETPSZPTR(parg16->f1, psz1);
  355. hmf = GetMetaFile(psz1);
  356. if (hmf)
  357. ul = WinMetaFileFromHMF(hmf, TRUE);
  358. else
  359. ul = 0;
  360. FREEPSZPTR(psz1);
  361. FREEARGPTR(parg16);
  362. RETURN(ul);
  363. }
  364. ULONG FASTCALL WG32PlayMetaFile(PVDMFRAME pFrame)
  365. {
  366. ULONG ul;
  367. HMETAFILE hmf;
  368. register PPLAYMETAFILE16 parg16;
  369. GETARGPTR(pFrame, sizeof(PLAYMETAFILE16), parg16);
  370. hmf = HMFFromWinMetaFile(parg16->f2, FALSE);
  371. ul = GETBOOL16(PlayMetaFile(HDC32(parg16->f1), hmf));
  372. if (hmf)
  373. DeleteMetaFile(hmf);
  374. FREEARGPTR(parg16);
  375. RETURN(ul);
  376. }
  377. ULONG FASTCALL WG32PlayMetaFileRecord(PVDMFRAME pFrame)
  378. {
  379. ULONG ul = FALSE;
  380. LPHANDLETABLE pHT = NULL;
  381. PBYTE pMetaData;
  382. WORD wHandles;
  383. VPHANDLETABLE16 vpHT;
  384. register PPLAYMETAFILERECORD16 parg16;
  385. GETARGPTR(pFrame, sizeof(PLAYMETAFILERECORD16), parg16);
  386. wHandles = parg16->f4;
  387. vpHT = parg16->f2;
  388. if (wHandles && vpHT) {
  389. ALLOCHANDLETABLE16(wHandles, pHT);
  390. if (!pHT)
  391. goto PMFR_Exit;
  392. GETHANDLETABLE16(vpHT, wHandles, pHT);
  393. }
  394. GETOPTPTR(parg16->f3, 0, pMetaData);
  395. ul = (ULONG) PlayMetaFileRecord(HDC32(parg16->f1),
  396. pHT,
  397. (LPMETARECORD)pMetaData,
  398. (UINT)wHandles);
  399. if (wHandles && vpHT) {
  400. PUTHANDLETABLE16(vpHT, wHandles, pHT);
  401. FREEHANDLETABLE16(pHT);
  402. }
  403. PMFR_Exit:
  404. FREEARGPTR(parg16);
  405. RETURN(ul);
  406. }
  407. #if 0 // implemented in gdi.exe
  408. ULONG FASTCALL WG32GetMetaFileBits(PVDMFRAME pFrame)
  409. {
  410. ULONG ul = 0;
  411. register PGETMETAFILEBITS16 parg16;
  412. GETARGPTR(pFrame, sizeof(GETMETAFILEBITS16), parg16);
  413. if (GlobalLock16(parg16->f1,NULL))
  414. {
  415. GlobalUnlock16(parg16->f1);
  416. ul = parg16->f1;
  417. }
  418. FREEARGPTR(parg16);
  419. RETURN(ul);
  420. }
  421. ULONG FASTCALL WG32SetMetaFileBits(PVDMFRAME pFrame)
  422. {
  423. ULONG ul;
  424. register PSETMETAFILEBITS16 parg16;
  425. GETARGPTR(pFrame, sizeof(SETMETAFILEBITS16), parg16);
  426. ul = parg16->f1;
  427. FREEARGPTR(parg16);
  428. RETURN(ul);
  429. }
  430. #endif