|
|
/*++
* * WOW v1.0 * * Copyright (c) 1991, Microsoft Corporation * * WGMETA.C * WOW32 16-bit GDI API support * * History: * Created 07-Mar-1991 by Jeff Parsons (jeffpar) --*/
#include "precomp.h"
#pragma hdrstop
MODNAME(wgmeta.c);
typedef METAHEADER UNALIGNED *PMETAHEADER16;
// WARNING: This function may cause 16-bit memory to move
VOID CopyMetaFile16FromHMF32(HAND16 hMF16, HMETAFILE hMF32) { UINT cbMF32, cbMF16; VPVOID vp; PBYTE pMF16;
if((vp = GlobalLock16(hMF16, &cbMF16)) && hMF32) {
GETMISCPTR(vp, pMF16);
cbMF32 = GetMetaFileBitsEx(hMF32, 0, NULL); // Verify these are the same size within the 16-bit kernel memory
// allocation granularity
WOW32WARNMSGF((abs(cbMF16 - cbMF32) < 32), ("WOW32: Size MF16 = %lu MF32 = %lu\n", cbMF16, cbMF32));
// copy the bits from the 32-bit metafile to the 16-bit metafile memory
cbMF32 = GetMetaFileBitsEx(hMF32, min(cbMF16, cbMF32), pMF16);
GlobalUnlock16(hMF16); FLUSHVDMPTR(vp, cbMF32, pMF16); FREEMISCPTR(pMF16); } }
// WARNING: This function may cause 16-bit memory to move
HAND16 WinMetaFileFromHMF(HMETAFILE hmf, BOOL fFreeOriginal) { UINT cbMetaData; VPVOID vpMetaData; PBYTE pMetaData; HAND16 h16;
/*
* Under Windows Metafiles were merely Global Handle to memory * so we have to mimick that behavior because some apps "operate" * on metafile handles directly. (WinWord and PowerPoint to * GlobalSize and GlobalAlloc to size and create metafiles) */
cbMetaData = GetMetaFileBitsEx(hmf, 0, NULL);
if (!cbMetaData) return((HAND16)NULL);
/*
* Win 3.1 allocates extra space in MetaFile and OLE2 checks for this. * METAHEADER is defined to be the same size as the 16-bit structure. */
cbMetaData += sizeof(METAHEADER);
vpMetaData = GlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE, cbMetaData, &h16);
if (!vpMetaData) return((HAND16)NULL);
GETOPTPTR(vpMetaData, 0, pMetaData);
if (GetMetaFileBitsEx(hmf, cbMetaData, pMetaData)) { GlobalUnlock16(h16); } else { GlobalUnlockFree16(vpMetaData); return((HAND16)NULL); }
if (fFreeOriginal) DeleteMetaFile(hmf);
return(h16); }
HMETAFILE HMFFromWinMetaFile(HAND16 h16, BOOL fFreeOriginal) { INT cb; VPVOID vp; HMETAFILE hmf = (HMETAFILE)0; PMETAHEADER16 pMFH16;
vp = GlobalLock16(h16, &cb);
if (vp) { GETMISCPTR(vp, pMFH16);
hmf = SetMetaFileBitsEx(cb, (LPBYTE)pMFH16);
if (fFreeOriginal) GlobalUnlockFree16(vp); else GlobalUnlock16(h16);
FREEMISCPTR(pMFH16); }
return(hmf); }
ULONG FASTCALL WG32CloseMetaFile(PVDMFRAME pFrame) { HMETAFILE hmf; ULONG ulRet = 0; register PCLOSEMETAFILE16 parg16;
GETARGPTR(pFrame, sizeof(CLOSEMETAFILE16), parg16);
hmf = CloseMetaFile(HDC32(parg16->f1));
if (hmf) ulRet = (ULONG)WinMetaFileFromHMF(hmf, TRUE); // WARNING: 16-bit memory may have moved - invalidate flat pointers now
FREEVDMPTR(pFrame); FREEARGPTR(parg16); RETURN(ulRet); }
ULONG FASTCALL WG32CopyMetaFile(PVDMFRAME pFrame) { ULONG ul; PSZ psz2; HMETAFILE hmfNew; HMETAFILE hmf; register PCOPYMETAFILE16 parg16;
GETARGPTR(pFrame, sizeof(COPYMETAFILE16), parg16); GETPSZPTR(parg16->f2, psz2);
if (psz2) { hmf = HMFFromWinMetaFile(parg16->f1, FALSE); hmfNew = CopyMetaFile(hmf, psz2); DeleteMetaFile(hmf); ul = (ULONG)WinMetaFileFromHMF(hmfNew, TRUE); // WARNING: 16-bit memory may have moved - invalidate flat pointers now
FREEVDMPTR(pFrame); FREEARGPTR(parg16); FREEPSZPTR(psz2); } else { UINT cb; VPVOID vp, vpNew; PBYTE pMF, pMFNew; HAND16 h16New, h16;
h16 = (HAND16)parg16->f1;
ul = (ULONG) NULL;
vp = GlobalLock16(h16, &cb); if (vp) {
/*
* Windows app such as WinWord uses GlobalSize to determine * the size of the metafile. However, this size can be larger * than the true size of a metafile. We have to make sure that * both source and destination sizes are identical so that * WinWord doesn't crash. */
vpNew = GlobalAllocLock16(GMEM_MOVEABLE | GMEM_DDESHARE, cb, &h16New);
// 16-bit memory may have moved - invalidate flat pointers now
FREEVDMPTR(pFrame); FREEARGPTR(parg16); FREEPSZPTR(psz2);
if (vpNew) { GETMISCPTR(vp, pMF); GETOPTPTR(vpNew, 0, pMFNew);
RtlCopyMemory(pMFNew, pMF, cb);
GlobalUnlock16(h16New); FLUSHVDMPTR(vpNew, cb, pMFNew); FREEOPTPTR(pMFNew); ul = h16New; }
GlobalUnlock16(h16); FREEMISCPTR(pMF); } }
FREEPSZPTR(psz2); FREEARGPTR(parg16); RETURN(ul); }
ULONG FASTCALL WG32CreateMetaFile(PVDMFRAME pFrame) { ULONG ul; PSZ psz1; register PCREATEMETAFILE16 parg16;
GETARGPTR(pFrame, sizeof(CREATEMETAFILE16), parg16); GETPSZPTR(parg16->f1, psz1);
ul = GETHDC16(CreateMetaFile(psz1));
FREEPSZPTR(psz1); FREEARGPTR(parg16); RETURN(ul); }
//
// This routine does what the 16-bit parameter validation layer would
// normally do for metafile handles, but since it is currently disabled,
// we'll do it here to fix WordPerfect that relies on it. Once true
// win31-style parameter validation has been re-enabled for metafile
// handles, all code within the ifndefs here and in WG32DeleteMetaFile
// can be removed.
//
#ifndef PARAMETER_VALIDATION_16_RE_ENABLED
#define MEMORYMETAFILE 1
#define DISKMETAFILE 2
#define HEADERSIZE (sizeof(METAHEADER)/sizeof(WORD))
#define METAVERSION 0x0300
#define METAVERSION100 0x0100
BOOL IsValidMetaFile16(PMETAHEADER16 lpMetaData) { BOOL sts = FALSE;
sts = (lpMetaData->mtType == MEMORYMETAFILE || lpMetaData->mtType == DISKMETAFILE) && (lpMetaData->mtHeaderSize == HEADERSIZE) && ((lpMetaData->mtVersion ==METAVERSION) || (lpMetaData->mtVersion ==METAVERSION100)) ; return sts; } #endif
ULONG FASTCALL WG32DeleteMetaFile(PVDMFRAME pFrame) { ULONG ul = FALSE; VPVOID vp; #ifndef PARAMETER_VALIDATION_16_RE_ENABLED
PMETAHEADER16 lpMetaData; #endif
register PDELETEMETAFILE16 parg16;
GETARGPTR(pFrame, sizeof(DELETEMETAFILE16), parg16);
if (vp = GlobalLock16(parg16->f1,NULL)) { #ifdef PARAMETER_VALIDATION_16_RE_ENABLED
GlobalUnlockFree16(vp); ul = TRUE; #else
GETVDMPTR(vp, 1, lpMetaData);
if (IsValidMetaFile16(lpMetaData)) { GlobalUnlockFree16(vp); ul = TRUE; }
FREEVDMPTR(lpMetaData); #endif
}
// If this metafile was in DDE conversation, then DDE cleanup code
// needs to free its 32 bit counter part. So give DDE clean up
// code a chance.
// ChandanC
W32DdeFreeHandle16 (parg16->f1);
FREEARGPTR(parg16); RETURN(ul); }
INT WG32EnumMetaFileCallBack(HDC hdc, LPHANDLETABLE lpht, LPMETARECORD lpMR, LONG nObj, PMETADATA pMetaData ) { INT iReturn; DWORD nWords;
// update object table if we have one
if (pMetaData->parmemp.vpHandleTable) PUTHANDLETABLE16(pMetaData->parmemp.vpHandleTable,nObj,lpht);
// update MetaRecord
// don't trash the heap with a bogus record, halt the enumeration
nWords = lpMR->rdSize; if (nWords > pMetaData->mtMaxRecordSize) { LOGDEBUG(0,("WOW:bad metafile record during enumeration\n")); WOW32ASSERT(FALSE); // contact barryb
return 0; // all done
} putstr16(pMetaData->parmemp.vpMetaRecord, (LPSZ)lpMR, nWords*sizeof(WORD));
CallBack16(RET_ENUMMETAFILEPROC, (PPARM16)&pMetaData->parmemp, pMetaData->vpfnEnumMetaFileProc, (PVPVOID)&iReturn);
// update the metarec in case the app altered it (Approach does)
getstr16(pMetaData->parmemp.vpMetaRecord, (LPSZ)lpMR, nWords*sizeof(WORD));
// update object table if we have one
if (pMetaData->parmemp.vpHandleTable) GETHANDLETABLE16(pMetaData->parmemp.vpHandleTable,nObj,lpht);
return (SHORT)iReturn;
hdc; // quiet the compilier; we already know the DC
}
ULONG FASTCALL WG32EnumMetaFile(PVDMFRAME pFrame) { ULONG ul = 0; register PENUMMETAFILE16 parg16; METADATA metadata; VPVOID vpMetaFile = (VPVOID) NULL; PBYTE pMetaFile; HMETAFILE hmf = (HMETAFILE) 0; HAND16 hMetaFile16; HDC hDC = 0;
GETARGPTR(pFrame, sizeof(ENUMMETAFILE16), parg16);
hMetaFile16 = parg16->f2;
metadata.vpfnEnumMetaFileProc = DWORD32(parg16->f3); metadata.parmemp.vpData = (VPVOID)DWORD32(parg16->f4); metadata.parmemp.vpMetaRecord = (VPVOID) NULL; metadata.parmemp.vpHandleTable = (VPVOID) NULL; metadata.parmemp.hdc = parg16->f1;
// WinWord never calls SetMetaFileBits; they peeked and know that
// a metafile is really a GlobalHandle in Windows so we have
// to look for that case.
hmf = HMFFromWinMetaFile(hMetaFile16, FALSE); if (!hmf) goto EMF_Exit;
// Get the metafile bits so we can get max record size and number of objects
vpMetaFile = GlobalLock16(hMetaFile16, NULL); FREEARGPTR(parg16); // memory may have moved
FREEVDMPTR(pFrame); if (!vpMetaFile) goto EMF_Exit;
GETOPTPTR(vpMetaFile, 0, pMetaFile); if (!pMetaFile) goto EMF_Exit;
metadata.parmemp.nObjects = ((PMETAHEADER16)pMetaFile)->mtNoObjects; metadata.mtMaxRecordSize = ((PMETAHEADER16)pMetaFile)->mtMaxRecord;
if (metadata.parmemp.nObjects) { PBYTE pHT; DWORD cb = ((PMETAHEADER16)pMetaFile)->mtNoObjects*sizeof(HAND16);
metadata.parmemp.vpHandleTable = GlobalAllocLock16(GMEM_MOVEABLE, cb, NULL); FREEOPTPTR(pMetaFile); // memory may have moved
FREEARGPTR(parg16); FREEVDMPTR(pFrame); if (!metadata.parmemp.vpHandleTable) goto EMF_Exit;
GETOPTPTR(metadata.parmemp.vpHandleTable, 0, pHT); RtlZeroMemory(pHT, cb); }
metadata.parmemp.vpMetaRecord = GlobalAllocLock16(GMEM_MOVEABLE, metadata.mtMaxRecordSize*sizeof(WORD), NULL); FREEOPTPTR(pMetaFile); // memory may have moved
FREEARGPTR(parg16); FREEVDMPTR(pFrame); if (!metadata.parmemp.vpMetaRecord) goto EMF_Exit;
// Corel Draw passes a NULL hDC, we'll create a dummy to keep GDI32 happy.
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_GETDUMMYDC) { if ((hDC = HDC32(metadata.parmemp.hdc)) == 0) { hDC = CreateMetaFile(NULL); } } else { hDC = HDC32(metadata.parmemp.hdc); }
// When processing metafile, access2.0 faults while receiving
// WM_DEVMODECHANGE so we block that particular message when
// in EnumMetaFile
if ( CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_EATDEVMODEMSG) { CURRENTPTD()->dwFlags |= TDF_EATDEVMODEMSG; } ul = GETBOOL16(EnumMetaFile(hDC, hmf, (MFENUMPROC)WG32EnumMetaFileCallBack, ((LPARAM)(LPVOID)&metadata)));
CURRENTPTD()->dwFlags &= ~TDF_EATDEVMODEMSG; // 16-bit memory may have moved - nothing to do as no flat ptrs exist now
// copy the 32-bit metafile back to 16-bit land (the app may have altered
// some of the metarecs in its MetaRecCallBackFunc -- Approach does)
CopyMetaFile16FromHMF32(hMetaFile16, hmf);
// Cleanup the dummy hDC created for Corel Draw 5.0.
if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_GETDUMMYDC) { if (HDC32(metadata.parmemp.hdc) == 0) { DeleteMetaFile(CloseMetaFile(hDC)); } }
EMF_Exit: if (vpMetaFile) GlobalUnlock16(hMetaFile16);
if (hmf) DeleteMetaFile(hmf);
if (metadata.parmemp.vpHandleTable) GlobalUnlockFree16(metadata.parmemp.vpHandleTable);
if (metadata.parmemp.vpMetaRecord) GlobalUnlockFree16(metadata.parmemp.vpMetaRecord);
FREEARGPTR(parg16); RETURN(ul); }
ULONG FASTCALL WG32GetMetaFile(PVDMFRAME pFrame) { ULONG ul; PSZ psz1; HMETAFILE hmf; register PGETMETAFILE16 parg16;
GETARGPTR(pFrame, sizeof(GETMETAFILE16), parg16); GETPSZPTR(parg16->f1, psz1);
hmf = GetMetaFile(psz1);
if (hmf) ul = WinMetaFileFromHMF(hmf, TRUE); else ul = 0;
FREEPSZPTR(psz1); FREEARGPTR(parg16); RETURN(ul); }
ULONG FASTCALL WG32PlayMetaFile(PVDMFRAME pFrame) { ULONG ul; HMETAFILE hmf; register PPLAYMETAFILE16 parg16;
GETARGPTR(pFrame, sizeof(PLAYMETAFILE16), parg16);
hmf = HMFFromWinMetaFile(parg16->f2, FALSE);
ul = GETBOOL16(PlayMetaFile(HDC32(parg16->f1), hmf));
if (hmf) DeleteMetaFile(hmf);
FREEARGPTR(parg16); RETURN(ul); }
ULONG FASTCALL WG32PlayMetaFileRecord(PVDMFRAME pFrame) { ULONG ul = FALSE; LPHANDLETABLE pHT = NULL; PBYTE pMetaData; WORD wHandles; VPHANDLETABLE16 vpHT; register PPLAYMETAFILERECORD16 parg16;
GETARGPTR(pFrame, sizeof(PLAYMETAFILERECORD16), parg16);
wHandles = parg16->f4; vpHT = parg16->f2; if (wHandles && vpHT) { ALLOCHANDLETABLE16(wHandles, pHT); if (!pHT) goto PMFR_Exit;
GETHANDLETABLE16(vpHT, wHandles, pHT); } GETOPTPTR(parg16->f3, 0, pMetaData);
ul = (ULONG) PlayMetaFileRecord(HDC32(parg16->f1), pHT, (LPMETARECORD)pMetaData, (UINT)wHandles);
if (wHandles && vpHT) { PUTHANDLETABLE16(vpHT, wHandles, pHT); FREEHANDLETABLE16(pHT); } PMFR_Exit: FREEARGPTR(parg16); RETURN(ul); }
#if 0 // implemented in gdi.exe
ULONG FASTCALL WG32GetMetaFileBits(PVDMFRAME pFrame) { ULONG ul = 0; register PGETMETAFILEBITS16 parg16;
GETARGPTR(pFrame, sizeof(GETMETAFILEBITS16), parg16);
if (GlobalLock16(parg16->f1,NULL)) { GlobalUnlock16(parg16->f1); ul = parg16->f1; }
FREEARGPTR(parg16); RETURN(ul); }
ULONG FASTCALL WG32SetMetaFileBits(PVDMFRAME pFrame) { ULONG ul; register PSETMETAFILEBITS16 parg16;
GETARGPTR(pFrame, sizeof(SETMETAFILEBITS16), parg16);
ul = parg16->f1;
FREEARGPTR(parg16); RETURN(ul); }
#endif
|