windows-nt/Source/XPSP1/NT/base/mvdm/wow32/wgmeta.c
2020-09-26 16:20:57 +08:00

575 lines
14 KiB
C

/*++
*
* 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