|
|
/*****************************************************************************
* * apientry.c - This module contains the API entry points for the * Win32 to Win16 metafile converter. * * Date: 8/29/91 * Author: Jeffrey Newman (c-jeffn) * * Copyright 1991 Microsoft Corp *****************************************************************************/
#include "precomp.h"
#pragma hdrstop
BOOL bMemUpdateCheckSum(PLOCALDC pLocalDC) ; PLOCALDC pldcInitLocalDC(HDC hdcRef, INT iMapMode, DWORD flags) ; VOID vFreeLocalDC(PLOCALDC pLocalDC);
extern VOID __cdecl _cfltcvt_init(VOID) ;
// This critical section structure is shared by all the threads of a given
// process.
CRITICAL_SECTION CriticalSection ;
// Constant definition for internal static string(s).
BYTE szDisplay[] = "DISPLAY" ;
/*****************************************************************************
* Entry point for translation *****************************************************************************/ UINT ConvertEmfToWmf(PVOID pht, PBYTE pMetafileBits, UINT cDest, PBYTE pDest, INT iMapMode, HDC hdcRef, UINT flags) { BOOL b ; DWORD lret = 0; PLOCALDC pLocalDC ;
// We funnel through one exit to make sure we leave the
// critical section.
EnterCriticalSection(&CriticalSection) ;
// Check the requested map mode and if it's valid
if (iMapMode < MM_MIN || iMapMode > MM_MAX) { RIP("MF3216:ConvertEmfToWmf - Invalid MapMode\n") ; goto ErrorExit; }
// Check for a reference DC. If one is not supplied we fail.
if (hdcRef == (HDC) 0) { RIP("MF3216:ConvertEmfToWmf - Invalid RefDC\n") ; goto ErrorExit; }
// Check the validity of the flags.
if ((flags & ~MF3216_INCLUDE_WIN32MF) != 0) { RIP("MF3216: ConvertEmfToWmf - Invalid flags\n") ; goto ErrorExit ; }
// Allocate the LocalDC and initialize some of it's fields.
pLocalDC = pldcInitLocalDC(hdcRef, iMapMode, flags) ; if (pLocalDC == (PLOCALDC) 0) { goto ErrorExit ; }
// If pDest is NULL then we just return the size of the buffer required
// to hold the Win16 metafile bits.
pLocalDC->pht = pht;
if (pDest == (PBYTE) 0) { pLocalDC->flags |= SIZE_ONLY ; b = bParseWin32Metafile(pMetafileBits, pLocalDC) ; if (b == TRUE) { lret = pLocalDC->ulBytesEmitted ; } else { PUTS("MF3216: ConvertEmfToWmf - Size Only failed\n") ; } } else {
// Put the user specified Win16 buffer pointer and buffer length
// into the localDC.
pLocalDC->pMf16Bits = pDest ; pLocalDC->cMf16Dest = cDest ;
// Translate the Win32 metafile to a Win16 metafile.
b = bParseWin32Metafile(pMetafileBits, pLocalDC) ; if (b == TRUE) { // Update the Win16 metafile header.
b = bUpdateMf16Header(pLocalDC) ; if (b == TRUE) { // Only acknowledge that we have translated some bits
// if everything has gone well.
lret = pLocalDC->ulBytesEmitted ;
// If we're including the Win32 metafile then update the
// checksum field in the "Win32Comment header" record.
if (pLocalDC->flags & INCLUDE_W32MF_COMMENT) bMemUpdateCheckSum(pLocalDC) ; } } else { PUTS("MF3216: ConvertEmfToWmf - Metafile conversion failed\n") ; } }
// Free the LocalDC and its resources.
vFreeLocalDC(pLocalDC);
ErrorExit: LeaveCriticalSection(&CriticalSection) ;
return (lret) ; }
/*****************************************************************************
* pldcInitLocalDC - Initialize the Local DC. *****************************************************************************/ PLOCALDC pldcInitLocalDC(HDC hdcRef, INT iMapMode, DWORD flags) { PLOCALDC pLocalDC; PLOCALDC pldcRet = (PLOCALDC) NULL; // assume error
// Allocate and initialize memory for the LocalDC.
pLocalDC = (PLOCALDC) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(LOCALDC)); if (!pLocalDC) { PUTS("MF3216:pldcInitLocalDC - LocalAlloc failure\n") ; return((PLOCALDC) NULL); }
// Record the size of the DC.
pLocalDC->nSize = sizeof(LOCALDC) ;
// Set the LocalDC boolean that controls whether or not we include
// the Win32 metafile as one or more comment records.
if (flags & MF3216_INCLUDE_WIN32MF) pLocalDC->flags |= INCLUDE_W32MF_COMMENT ;
#if 0
// Need to create a hdc for the display.
// Initially this will be used by the bitblt translation code
// to get a reasonable set of palette entries.
// The reference DC only has a black & white palette.
pLocalDC->hdcDisp = CreateDCA((LPCSTR)szDisplay, (LPCSTR)NULL, (LPCSTR)NULL, (CONST DEVMODEA *)NULL) ; if (pLocalDC->hdcDisp == (HDC) 0) { RIP("MF3216:pldcInitLocalDC - CreateDCA(hdcDisp) failed\n") ; goto pldcInitLocalDC_exit; } #endif // 0
// Create the HelperDC.
pLocalDC->hdcHelper = CreateICA((LPCSTR) szDisplay, (LPCSTR) NULL, (LPCSTR) NULL, (LPDEVMODEA) NULL) ; if (pLocalDC->hdcHelper == (HDC)0) { PUTS("MF3216: pldcInitLocalDC, Create Helper DC failed\n") ; goto pldcInitLocalDC_exit; }
// Initialize the counters we need to keep for updating the header,
// and keeping track of the object table.
pLocalDC->nObjectHighWaterMark = -1;
// Get the play-time device dimensions in millimeters and in pels.
pLocalDC->cxPlayDevMM = GetDeviceCaps(hdcRef, HORZSIZE) ; pLocalDC->cyPlayDevMM = GetDeviceCaps(hdcRef, VERTSIZE) ; pLocalDC->cxPlayDevPels = GetDeviceCaps(hdcRef, HORZRES) ; pLocalDC->cyPlayDevPels = GetDeviceCaps(hdcRef, VERTRES) ;
// Record the requested map mode and reference DC.
pLocalDC->iMapMode = iMapMode ; pLocalDC->hdcRef = hdcRef ;
// Init Arc Direction.
pLocalDC->iArcDirection = AD_COUNTERCLOCKWISE ;
// Make current position invalid so that a moveto will be
// emitted when it is first used. See comments in DoMoveTo.
pLocalDC->ptCP.x = MAXLONG ; pLocalDC->ptCP.y = MAXLONG ;
// Default pen is a black pen.
pLocalDC->lhpn32 = BLACK_PEN | ENHMETA_STOCK_OBJECT;
// Default brush is a white brush.
pLocalDC->lhbr32 = WHITE_BRUSH | ENHMETA_STOCK_OBJECT;
// Default palette.
pLocalDC->ihpal32 = DEFAULT_PALETTE | ENHMETA_STOCK_OBJECT; pLocalDC->ihpal16 = (DWORD) -1; // no W16 palette created yet
pLocalDC->crBkColor = RGB(0xFF,0xFF,0xFF);
// pLocalDC->pW16ObjHndlSlotStatus = NULL;
// pLocalDC->cW16ObjHndlSlotStatus = 0;
// pLocalDC->piW32ToW16ObjectMap = NULL;
// pLocalDC->cW32ToW16ObjectMap = 0;
// pLocalDC->crTextColor = RGB(0x0,0x0,0x0);
// pLocalDC->iLevel = 0;
// pLocalDC->pLocalDCSaved = NULL;
// pLocalDC->ulBytesEmitted = 0;
// pLocalDC->ulMaxRecord = 0;
// pLocalDC->pW32hPal = NULL;
// Set the advanced graphics mode in the helper DC. This is needed
// to notify the helper DC that rectangles and ellipses are
// inclusive-inclusive etc., especially when rendering them in a path.
// Also, the world transform can only be set in the advanced mode.
(void) SetGraphicsMode(pLocalDC->hdcHelper, GM_ADVANCED);
// We are golden.
pldcRet = pLocalDC;
pldcInitLocalDC_exit:
if (!pldcRet) vFreeLocalDC(pLocalDC);
return(pldcRet) ; }
/*****************************************************************************
* vFreeLocalDC - Free the Local DC and its resources. *****************************************************************************/ VOID vFreeLocalDC(PLOCALDC pLocalDC) { UINT i;
// Free the helper DCs.
if (pLocalDC->hdcHelper) if (!DeleteDC(pLocalDC->hdcHelper)) ASSERTGDI(FALSE, "MF3216: vFreeLocalDC, DeleteDC failed"); #if 0
if (pLocalDC->hdcDisp) if (!DeleteDC(pLocalDC->hdcDisp)) ASSERTGDI(FALSE, "MF3216: vFreeLocalDC, DeleteDC failed"); #endif // 0
// Free the storage for the object translation map.
if (pLocalDC->piW32ToW16ObjectMap) { #if 0
for (i = 0 ; i < pLocalDC->cW32ToW16ObjectMap ; i++) { if (pLocalDC->piW32ToW16ObjectMap[i] != UNMAPPED) if (i > STOCK_LAST) PUTS1("MF3216: vFreeLocalDC, object32 %ld is not freed\n", i - STOCK_LAST - 1); else PUTS1("MF3216: vFreeLocalDC, stock object32 %ld is mapped\n",i); } #endif // 0
if (LocalFree(pLocalDC->piW32ToW16ObjectMap)) ASSERTGDI(FALSE, "MF3216: vFreeLocalDC, LocalFree failed"); }
// Free the W32 palette handles.
if (pLocalDC->pW32hPal) { for (i = 0; i < pLocalDC->cW32hPal; i++) { if (pLocalDC->pW32hPal[i]) if (!DeleteObject(pLocalDC->pW32hPal[i])) ASSERTGDI(FALSE, "MF3216: vFreeLocalDC, delete palette failed"); }
if (LocalFree(pLocalDC->pW32hPal)) ASSERTGDI(FALSE, "MF3216: vFreeLocalDC, LocalFree failed"); }
// Free the w32 handles in the pW16ObjHndlSlotStatus array.
// We free the handles after we have deleted the helper DC so that
// the w32 handles are not selected into any DC.
if (pLocalDC->pW16ObjHndlSlotStatus) { for (i = 0 ; i < pLocalDC->cW16ObjHndlSlotStatus ; i++) { #if 0
if (pLocalDC->pW16ObjHndlSlotStatus[i].use != OPEN_AVAILABLE_SLOT) PUTS1("MF3216: vFreeLocalDC, object16 %ld is not freed\n", i); #endif // 0
if (pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle) { ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[i].use != OPEN_AVAILABLE_SLOT, "MF3216: error in object handle table");
if (!DeleteObject(pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle)) ASSERTGDI(FALSE, "MF3216: vFreeLocalDC, DeleteObject failed"); } }
if (LocalFree(pLocalDC->pW16ObjHndlSlotStatus)) ASSERTGDI(FALSE, "MF3216: vFreeLocalDC, LocalFree failed"); }
// The DC level should be balanced.
if (pLocalDC->pLocalDCSaved != NULL) { PLOCALDC pNext, pTmp;
for (pNext = pLocalDC->pLocalDCSaved; pNext; ) { PUTS("MF3216: vFreeLocalDC, unbalanced DC level\n");
pTmp = pNext->pLocalDCSaved; if (LocalFree(pNext)) ASSERTGDI(FALSE, "MF3216: vFreeLocalDC, LocalFree failed"); pNext = pTmp; } }
// Finally, free the LocalDC.
if (LocalFree(pLocalDC)) ASSERTGDI(FALSE, "MF3216: vFreeLocalDC, LocalFree failed"); }
/***************************************************************************
* Handle emitting the Win32 metafile comment record(s). **************************************************************************/ BOOL bHandleWin32Comment(PLOCALDC pLocalDC) { INT i; BOOL b ; META_ESCAPE_ENHANCED_METAFILE mfeEnhMF;
// Win30 may have problems with large (over 8K) escape records.
// We will limit the size of each Win32 Comment record to
// MAX_WIN32_COMMENT_REC_SIZE.
// Initialize the record header.
mfeEnhMF.rdFunction = META_ESCAPE; mfeEnhMF.wEscape = MFCOMMENT; mfeEnhMF.ident = MFCOMMENT_IDENTIFIER; mfeEnhMF.iComment = MFCOMMENT_ENHANCED_METAFILE; mfeEnhMF.nVersion = ((PENHMETAHEADER) pLocalDC->pMf32Bits)->nVersion; mfeEnhMF.wChecksum = 0; // updated by bMemUpdateCheckSum
mfeEnhMF.fFlags = 0; mfeEnhMF.nCommentRecords = (pLocalDC->cMf32Bits + MAX_WIN32_COMMENT_REC_SIZE - 1) / MAX_WIN32_COMMENT_REC_SIZE; mfeEnhMF.cbEnhMetaFile = pLocalDC->cMf32Bits;
mfeEnhMF.cbRemainder = pLocalDC->cMf32Bits; i = 0 ; while (mfeEnhMF.cbRemainder) { mfeEnhMF.cbCurrent = min(mfeEnhMF.cbRemainder, MAX_WIN32_COMMENT_REC_SIZE); mfeEnhMF.rdSize = (sizeof(mfeEnhMF) + mfeEnhMF.cbCurrent) / 2; mfeEnhMF.wCount = (WORD)(sizeof(mfeEnhMF) + mfeEnhMF.cbCurrent - sizeof(METARECORD_ESCAPE)); mfeEnhMF.cbRemainder -= mfeEnhMF.cbCurrent;
b = bEmitWin16EscapeEnhMetaFile(pLocalDC, (PMETARECORD_ESCAPE) &mfeEnhMF, &pLocalDC->pMf32Bits[i]);
if (!b) break; i += mfeEnhMF.cbCurrent; }
return(b) ; }
/*****************************************************************************
* bMemUpdateCheckSum - Update the checksum *****************************************************************************/ BOOL bMemUpdateCheckSum(PLOCALDC pLocalDC) { INT i, k ; PWORD pword ; WORD CheckSum ; PMETA_ESCAPE_ENHANCED_METAFILE pmfeEnhMF;
// CheckSum the file.
// Do a 16 bit checksum
pword = (PWORD) pLocalDC->pMf16Bits ; k = pLocalDC->ulBytesEmitted / 2 ;
CheckSum = 0 ; for (i = 0 ; i < k ; i++) CheckSum += pword[i] ;
// Update the checksum record value with the real checksum.
pmfeEnhMF = (PMETA_ESCAPE_ENHANCED_METAFILE) &pLocalDC->pMf16Bits[sizeof(METAHEADER)];
ASSERTGDI(IS_META_ESCAPE_ENHANCED_METAFILE(pmfeEnhMF) && pmfeEnhMF->wChecksum == 0 && pmfeEnhMF->fFlags == 0, "MF3216: bMemUpdateCheckSum: Bad pmfeEnhMF");
pmfeEnhMF->wChecksum = -CheckSum;
#if DBG
// Now test the checksum. The checksum of the entire file
// should be 0.
CheckSum = 0 ; pword = (PWORD) pLocalDC->pMf16Bits ; for (i = 0 ; i < k ; i++) CheckSum += pword[i] ;
if (CheckSum != 0) { RIP("MF3216: MemUpdateCheckSum, (CheckSum != 0)\n") ; } #endif
return (TRUE) ; }
/******************************Public*Routine******************************\
* Mf3216DllInitialize * * * * This is the init procedure for MF3216.DLL, * * which is called each time a new * * process links to it. * \**************************************************************************/
BOOL Mf3216DllInitialize(PVOID pvDllHandle, DWORD ulReason, PCONTEXT pcontext) {
NOTUSED(pvDllHandle) ; NOTUSED(pcontext) ;
if ( ulReason == DLL_PROCESS_ATTACH ) { // This does the critical section initialization for a single
// process. Each process does this. The CriticalSection data
// structure is one of the very few (if not the only one) data
// structures in the data segment.
InitializeCriticalSection(&CriticalSection) ; } else if ( ulReason == DLL_PROCESS_DETACH ) { DeleteCriticalSection(&CriticalSection) ; }
return(TRUE);
}
|