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.
763 lines
19 KiB
763 lines
19 KiB
/*************************************************************************\
|
|
* Module Name: mfdc.cxx
|
|
*
|
|
* This file contains the member functions for metafile DC class defined
|
|
* in mfdc.hxx.
|
|
*
|
|
* Created: 12-June-1991 13:46:00
|
|
* Author: Hock San Lee [hockl]
|
|
*
|
|
* Copyright (c) 1991-1999 Microsoft Corporation
|
|
\*************************************************************************/
|
|
|
|
#define NO_STRICT
|
|
|
|
extern "C" {
|
|
#if defined(_GDIPLUS_)
|
|
#include <gpprefix.h>
|
|
#endif
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <stddef.h>
|
|
#include <windows.h> // GDI function declarations.
|
|
#include <winerror.h>
|
|
#include "firewall.h"
|
|
#define __CPLUSPLUS
|
|
#include <winspool.h>
|
|
#include <wingdip.h>
|
|
#include "ntgdistr.h"
|
|
#include "winddi.h"
|
|
#include "hmgshare.h"
|
|
#include "icm.h"
|
|
#include "local.h" // Local object support.
|
|
#include "gdiicm.h"
|
|
#include "metadef.h" // Metafile record type constants.
|
|
|
|
}
|
|
|
|
#include "rectl.hxx"
|
|
#include "mfdc.hxx" // Metafile DC class declarations.
|
|
|
|
extern RECTL rclNull; // METAFILE.CXX
|
|
|
|
#define MF_CHECK_RECORDMEMORY_LIMIT 0x00010000
|
|
|
|
|
|
VOID METALINK::vInit(ULONG metalink)
|
|
{
|
|
imhe = ((METALINK *) &metalink)->imhe;
|
|
ihdc = ((METALINK *) &metalink)->ihdc;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* void * MDC::pvNewRecord(nSize)
|
|
*
|
|
* Allocate a metafile record from memory buffer.
|
|
* Also set the size field in the metafile record. If a fatal error
|
|
* has occurred, do not allocate new record.
|
|
*
|
|
* History:
|
|
* Thu Jul 18 11:19:20 1991 -by- Hock San Lee [hockl]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void * MDC::pvNewRecord(DWORD nSize)
|
|
{
|
|
#if DBG
|
|
static DWORD cRcd = 0;
|
|
|
|
PUTSX("MDC::pvNewRecord %ld \n", cRcd++);
|
|
#endif
|
|
|
|
// If a fatal error has occurred, do not allocate any more.
|
|
|
|
if (fl & MDC_FATALERROR)
|
|
return((void *) 0);
|
|
|
|
// Before we allocate a new record, commit the previous bounds record
|
|
// if necessary.
|
|
|
|
if (fl & MDC_DELAYCOMMIT)
|
|
{
|
|
// Clear the flag.
|
|
|
|
fl &= ~MDC_DELAYCOMMIT;
|
|
|
|
PENHMETABOUNDRECORD pmrb = (PENHMETABOUNDRECORD) GetNextRecordPtr(sizeof(ENHMETABOUNDRECORD));
|
|
|
|
if(pmrb)
|
|
{
|
|
// Get and reset bounds.
|
|
// See also MDC::vFlushBounds.
|
|
|
|
if (GetBoundsRectAlt(hdcRef, (LPRECT) &pmrb->rclBounds, (UINT) (DCB_RESET | DCB_WINDOWMGR))
|
|
== DCB_SET)
|
|
{
|
|
// Need to intersect bounds with current clipping region first
|
|
|
|
*((PERECTL) &pmrb->rclBounds) *= *perclMetaBoundsGet();
|
|
*((PERECTL) &pmrb->rclBounds) *= *perclClipBoundsGet();
|
|
|
|
// Make it inclusive-inclusive.
|
|
|
|
pmrb->rclBounds.right--;
|
|
pmrb->rclBounds.bottom--;
|
|
|
|
// Accumulate bounds to the metafile header.
|
|
|
|
if (!((PERECTL) &pmrb->rclBounds)->bEmpty())
|
|
*((PERECTL) &mrmf.rclBounds) += pmrb->rclBounds;
|
|
else
|
|
pmrb->rclBounds = rclNull;
|
|
}
|
|
else
|
|
{
|
|
pmrb->rclBounds = rclNull;
|
|
}
|
|
|
|
vCommit(*(PENHMETARECORD) pmrb);
|
|
|
|
ASSERTGDI(!(fl & MDC_FATALERROR),
|
|
"MDC::pvNewRecord: Fatal error has occurred");
|
|
|
|
ReleasePtr(pmrb);
|
|
}
|
|
else
|
|
{
|
|
WARNING("MDC::pvNewRecord() failed to get new record\n");
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
// If there is enough free buffer space, use it.
|
|
|
|
if (iMem + nSize > nMem)
|
|
{
|
|
// Not enough free buffer space. Flush the filled buffer if it is
|
|
// a disk metafile.
|
|
|
|
if (bIsDiskFile())
|
|
if (!bFlush())
|
|
return((void *) 0);
|
|
|
|
// Realloc memory buffer if the free buffer is still too small.
|
|
|
|
if (iMem + nSize > nMem)
|
|
{
|
|
ULONG nMemNew, sizeNeeded, sizeExtra;
|
|
|
|
sizeNeeded = (nSize + MF_BUFSIZE_INC - 1) / MF_BUFSIZE_INC * MF_BUFSIZE_INC;
|
|
|
|
if (!bIsEMFSpool())
|
|
{
|
|
//
|
|
// When not EMF spooling, use the following heuristics:
|
|
// If current size <= 64K, enlarge the buffer by extra 16K
|
|
// Else, enlarge the buffer by extra 25%
|
|
//
|
|
|
|
sizeExtra = (nMem > 0x10000) ? (nMem >> 2) : MF_BUFSIZE_INC;
|
|
|
|
nMemNew = nMem + sizeExtra + sizeNeeded;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// When EMF spooling, use the more aggressive heuristics:
|
|
// If current size <= 1MB, double the buffer
|
|
// Else, enlarge the buffer by 50% with a cap of 4MB
|
|
|
|
if (nMem > 0x100000)
|
|
{
|
|
sizeExtra = nMem >> 1;
|
|
|
|
if (sizeExtra > 0x400000)
|
|
sizeExtra = 0x400000;
|
|
}
|
|
else
|
|
sizeExtra = nMem;
|
|
|
|
nMemNew = nMem + max(sizeNeeded, sizeExtra);
|
|
}
|
|
|
|
if (!ReallocMem(nMemNew))
|
|
{
|
|
ERROR_ASSERT(FALSE, "ReallocMem failed\n");
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Zero the last dword. If the record does not use up all bytes in the
|
|
// last dword, the unused bytes will be zeros.
|
|
|
|
PVOID pvRecord = GetNextRecordPtr(nSize);
|
|
|
|
if(pvRecord)
|
|
{
|
|
((PDWORD) pvRecord)[nSize / 4 - 1] = 0;
|
|
|
|
// Set the size field and return the pointer to the new record.
|
|
|
|
((PENHMETARECORD) pvRecord)->nSize = nSize;
|
|
|
|
// WINBUG 365051 4-10-2001 pravins Need to modify usage of pvNewRecord() to release ptr
|
|
// We should not be doing the release here. We should have users of pvNewRecord()
|
|
// call ReleasePtr when they are done. This requires a bunch of edits in metarec.cxx
|
|
// and mestsup.cxx.
|
|
|
|
ReleasePtr(pvRecord);
|
|
}
|
|
else
|
|
{
|
|
WARNING("MDC::pvNewRecord() failed to get next record ptr\n");
|
|
}
|
|
|
|
return pvRecord;
|
|
}
|
|
|
|
|
|
BOOL
|
|
MDC::ReallocMem(
|
|
ULONG newsize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Resize the memory buffer used to hold EMF data
|
|
|
|
Arguments:
|
|
|
|
newsize - new size of EMF memory buffer
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
if (bIsEMFSpool())
|
|
{
|
|
ENHMETAHEADER *pNewHeader;
|
|
|
|
if(!((EMFSpoolData *) hData)->ResizeEMFData(newsize))
|
|
return FALSE;
|
|
|
|
}
|
|
else
|
|
{
|
|
HANDLE hMemNew;
|
|
|
|
if ((hMemNew = LocalReAlloc(hData, newsize, LMEM_MOVEABLE)) == NULL)
|
|
{
|
|
ERROR_ASSERT(FALSE, "LocalReAlloc failed");
|
|
return FALSE;
|
|
}
|
|
|
|
hData = hMemNew;
|
|
}
|
|
|
|
nMem = newsize;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BOOL MDC::bFlush()
|
|
*
|
|
* Flush the filled memory buffer to disk.
|
|
*
|
|
* History:
|
|
* Thu Jul 18 11:19:20 1991 -by- Hock San Lee [hockl]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL MDC::bFlush()
|
|
{
|
|
ULONG nWritten ;
|
|
|
|
PUTS("MDC::bFlush\n");
|
|
PUTSX("\tnFlushSize = %ld\n", (ULONG)iMem);
|
|
PUTSX("\tnBufferSize = %ld\n", (ULONG)nMem);
|
|
|
|
ASSERTGDI(bIsDiskFile(), "MDC::bFlush: Not a disk metafile");
|
|
ASSERTGDI(!(fl & MDC_FATALERROR), "MDC::bFlush: Fatal error has occurred");
|
|
|
|
// WriteFile handles a null write correctly.
|
|
|
|
if (!WriteFile(hFile, hData, iMem, &nWritten, (LPOVERLAPPED) NULL)
|
|
|| nWritten != iMem)
|
|
{
|
|
// The write error here is fatal since we are doing record buffering and
|
|
// have no way of recovering to a previous state.
|
|
|
|
ERROR_ASSERT(FALSE, "MDC::bFlush failed");
|
|
fl |= MDC_FATALERROR;
|
|
return(FALSE);
|
|
}
|
|
iMem = 0L;
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID MDC::vAddToMetaFilePalette(cEntries, pPalEntriesNew)
|
|
*
|
|
* Add new palette entries to the metafile palette.
|
|
*
|
|
* When new palette entries are added to a metafile in CreatePalette or
|
|
* SetPaletteEntries, they are also accumulated to the metafile palette.
|
|
* The palette is later returned in GetEnhMetaFilePaletteEntries when an
|
|
* application queries it. It assumes that the peFlags of the palette entries
|
|
* are zeroes.
|
|
*
|
|
* A palette color is added to the metafile palette only if it is not a
|
|
* duplicate. It uses a simple linear search algorithm to determine if
|
|
* a duplicate palette exists.
|
|
*
|
|
* History:
|
|
* Mon Sep 23 14:27:25 1991 -by- Hock San Lee [hockl]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID MDC::vAddToMetaFilePalette(UINT cEntries, PPALETTEENTRY pPalEntriesNew)
|
|
{
|
|
UINT ii;
|
|
|
|
PUTS("vAddToMetaFilePalette\n");
|
|
|
|
while (cEntries--)
|
|
{
|
|
ASSERTGDI(pPalEntriesNew->peFlags == 0,
|
|
"MDC::vAddToMetaFilePalette: peFlags not zero");
|
|
|
|
// Look for duplicate.
|
|
|
|
for (ii = 0; ii < iPalEntries; ii++)
|
|
{
|
|
ASSERTGDI(sizeof(PALETTEENTRY) == sizeof(DWORD),
|
|
"MDC::vAddToMetaFilePalette: Bad size");
|
|
|
|
if (*(PDWORD) &pPalEntries[ii] == *(PDWORD) pPalEntriesNew)
|
|
break;
|
|
}
|
|
|
|
// Add to the metafile palette if not a duplicate.
|
|
|
|
if (ii >= iPalEntries)
|
|
{
|
|
pPalEntries[iPalEntries] = *pPalEntriesNew;
|
|
iPalEntries++; // Advance iPalEntries for next loop!
|
|
}
|
|
|
|
pPalEntriesNew++;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID METALINK::vNext()
|
|
*
|
|
* Update *this to the next metalink.
|
|
*
|
|
* History:
|
|
* Wed Aug 07 09:28:54 1991 -by- Hock San Lee [hockl]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID METALINK::vNext()
|
|
{
|
|
PUTS("METALINK::vNext\n");
|
|
ASSERTGDI(bValid(), "METALINK::vNext: Invalid metalink");
|
|
|
|
PMDC pmdc = pmdcGetFromIhdc(ihdc);
|
|
ASSERTGDI(pmdc,"METALINK::vNext - invalid pmdc\n");
|
|
|
|
if (pmdc == NULL)
|
|
ZeroMemory(this,sizeof(*this)); // Make it invalid so bValid will fail
|
|
else
|
|
*this = pmdc->pmhe[imhe].metalink;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* METALINK * METALINK::pmetalinkNext()
|
|
*
|
|
* Return the pointer to the next metalink.
|
|
*
|
|
* History:
|
|
* Wed Aug 07 09:28:54 1991 -by- Hock San Lee [hockl]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
METALINK * METALINK::pmetalinkNext()
|
|
{
|
|
PUTS("METALINK::pmetalinkNext\n");
|
|
ASSERTGDI(bValid(), "METALINK::pmetalinkNext: Invalid metalink");
|
|
|
|
PMDC pmdc = pmdcGetFromIhdc(ihdc);
|
|
ASSERTGDI(pmdc,"METALINK::vNext - invalid pmdc\n");
|
|
|
|
return(&pmdc->pmhe[imhe].metalink);
|
|
}
|
|
|
|
VOID EMFContainer::Init(ENHMETAHEADER * inHdr, UINT32 dataSize)
|
|
{
|
|
dwRefCount = 0;
|
|
|
|
pemfhdr = inHdr;
|
|
dwHdrSize = dataSize;
|
|
|
|
pvWindow = NULL;
|
|
dwWindowOffset = 0;
|
|
dwWindowSize = 0;
|
|
|
|
hFile = NULL;
|
|
}
|
|
|
|
BOOL EMFContainer::Init(HANDLE inFile, UINT64 inHdrOffset, UINT64 inFileSize)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
|
|
dwRefCount = 0;
|
|
|
|
pemfhdr = NULL;
|
|
dwHdrSize = 0;
|
|
|
|
pvWindow = NULL;
|
|
dwWindowOffset = 0;
|
|
dwWindowSize = 0;
|
|
|
|
hFile = inFile;
|
|
hFileMapping = NULL;
|
|
pvHdr = NULL;
|
|
|
|
qwHdrOffset = inHdrOffset;
|
|
qwFileSize = inFileSize;
|
|
|
|
if(qwFileSize != 0 || GetFileSizeEx(hFile, (LARGE_INTEGER *) &qwFileSize))
|
|
{
|
|
hFileMapping = CreateFileMappingW(hFile,
|
|
NULL,
|
|
PAGE_READWRITE,
|
|
HIDWORD(qwFileSize),
|
|
LODWORD(qwFileSize),
|
|
NULL);
|
|
|
|
if(hFileMapping != NULL)
|
|
{
|
|
UINT64 qwOffset = qwHdrOffset;
|
|
UINT32 dwSize = sizeof(ENHMETAHEADER);
|
|
|
|
pvHdr = pvMapView(&qwOffset, &dwSize);
|
|
|
|
if(pvHdr)
|
|
{
|
|
UINT32 dwViewOffset = (UINT32) (qwHdrOffset - qwOffset);
|
|
|
|
pemfhdr = (PENHMETAHEADER) ((PBYTE) pvHdr + dwViewOffset);
|
|
dwHdrSize = dwSize - dwViewOffset;
|
|
|
|
bResult = TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if(!bResult)
|
|
Term();
|
|
|
|
return bResult;
|
|
|
|
}
|
|
|
|
VOID EMFContainer::Term()
|
|
{
|
|
// Free any locally allocated resources
|
|
|
|
if(hFile)
|
|
{
|
|
// We were using mapped views of the file
|
|
|
|
if(hFileMapping)
|
|
{
|
|
if(!CloseHandle(hFileMapping))
|
|
{
|
|
WARNING("EMFContainer::Term() failed to close file mapping\n");
|
|
}
|
|
hFileMapping = NULL;
|
|
}
|
|
|
|
if(pvHdr != NULL)
|
|
{
|
|
if(!UnmapViewOfFile(pvHdr))
|
|
{
|
|
WARNING("EMFContainer::Term() Failed to unmap header view\n");
|
|
}
|
|
pvHdr = NULL;
|
|
}
|
|
|
|
if(pvWindow != NULL)
|
|
{
|
|
if(!UnmapViewOfFile(pvWindow))
|
|
{
|
|
WARNING("EMFContainer::Term() Failed to unmap window view\n");
|
|
}
|
|
pvWindow = NULL;
|
|
}
|
|
|
|
hFile = NULL;
|
|
|
|
}
|
|
|
|
pemfhdr = NULL;
|
|
dwHdrSize = 0;
|
|
|
|
}
|
|
|
|
BOOL bProbeAndPageInAddressRange(BYTE *pb, UINT inSize)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
if (inSize == 0)
|
|
return bRet;
|
|
|
|
__try
|
|
{
|
|
DWORD dwPagesize = GetSystemPageSize( );
|
|
BYTE bData;
|
|
BYTE *pbLoc = pb;
|
|
BYTE *pbEnd = pbLoc + ( (inSize < MF_CHECK_RECORDMEMORY_LIMIT) ? inSize : MF_CHECK_RECORDMEMORY_LIMIT );
|
|
|
|
while (pbLoc < pbEnd)
|
|
{
|
|
bData = *pbLoc;
|
|
pbLoc += dwPagesize;
|
|
}
|
|
pbEnd--;
|
|
bData = *pbEnd;
|
|
}
|
|
__except( GetExceptionCode() == STATUS_IN_PAGE_ERROR ||
|
|
GetExceptionCode() == STATUS_ACCESS_VIOLATION)
|
|
{
|
|
EMFVALFAIL(("bProbeAndPageInAddressRange: (%p) [%08x] Failed\n", pb, inSize));
|
|
bRet = FALSE;
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
PVOID EMFContainer::ObtainPtr(UINT inOffset, UINT inSize)
|
|
{
|
|
if(dwRefCount > 1)
|
|
{
|
|
WARNING("Obtaining record with non-zero ref count\n");
|
|
return NULL;
|
|
}
|
|
|
|
dwRefCount++;
|
|
|
|
if(inOffset < dwHdrSize && inSize <= (dwHdrSize - inOffset))
|
|
{
|
|
if (bProbeAndPageInAddressRange((PBYTE) pemfhdr + inOffset, inSize))
|
|
return (PVOID) ((PBYTE) pemfhdr + inOffset);
|
|
else
|
|
{
|
|
--dwRefCount;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if(!hFile)
|
|
{
|
|
WARNING("EMFContainer::ObtainPtr() Attempt to obtain ptr past end of memory EMF\n");
|
|
dwRefCount--;
|
|
return NULL;
|
|
}
|
|
|
|
if(inOffset < dwWindowOffset ||
|
|
(inOffset + inSize) > (dwWindowOffset + dwWindowSize))
|
|
{
|
|
|
|
if(pvWindow && !UnmapViewOfFile(pvWindow))
|
|
{
|
|
WARNING("EMFContainer::ObtainPtr() failed to unmap window view\n");
|
|
}
|
|
|
|
UINT64 qwOffset = qwHdrOffset + inOffset;
|
|
|
|
dwWindowSize = inSize;
|
|
|
|
pvWindow = pvMapView(&qwOffset, &dwWindowSize);
|
|
|
|
if(!pvWindow)
|
|
{
|
|
WARNING("EMFContainer::ObtainPtr() failed to map window view\n");
|
|
dwRefCount--;
|
|
return NULL;
|
|
}
|
|
|
|
if(qwOffset < qwHdrOffset)
|
|
{
|
|
dwWindowUnusable = (UINT32) (qwHdrOffset - qwOffset);
|
|
|
|
ASSERTGDI(dwWindowUnusable < dwWindowSize, "EMFContainer::ObtainPtr() Unexpected dwUnusable value\n");
|
|
|
|
dwWindowSize -= dwWindowUnusable;
|
|
dwWindowOffset = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
dwWindowUnusable = 0;
|
|
dwWindowOffset = (UINT32) (qwOffset - qwHdrOffset);
|
|
}
|
|
|
|
if(inOffset < dwWindowOffset ||
|
|
(inOffset + inSize) > (dwWindowOffset + dwWindowSize))
|
|
{
|
|
WARNING("EMFContainer::ObtainPtr() something went really wrong\n");
|
|
dwRefCount--;
|
|
return NULL;
|
|
}
|
|
|
|
}
|
|
|
|
BYTE *pbRet = (BYTE *)pvWindow + inOffset - dwWindowOffset + dwWindowUnusable;
|
|
if (bProbeAndPageInAddressRange(pbRet, inSize))
|
|
return (PVOID)pbRet;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
PENHMETARECORD EMFContainer::ObtainRecordPtr(UINT inOffset)
|
|
{
|
|
ENHMETARECORD *pemr = NULL;
|
|
|
|
ENHMETARECORD *pemrTemp = (ENHMETARECORD *) ObtainPtr(inOffset, sizeof(ENHMETARECORD));
|
|
|
|
if (pemrTemp != NULL)
|
|
{
|
|
UINT size = pemrTemp->nSize;
|
|
|
|
ReleasePtr(pemrTemp);
|
|
|
|
pemrTemp = (ENHMETARECORD *) ObtainPtr(inOffset, size);
|
|
|
|
if (pemrTemp != NULL)
|
|
{
|
|
pemr = pemrTemp;
|
|
}
|
|
}
|
|
return pemr;
|
|
}
|
|
|
|
PEMREOF EMFContainer::ObtainEOFRecordPtr()
|
|
{
|
|
PEMREOF pmreof = NULL;
|
|
ENHMETAHEADER * pmrmf = GetEMFHeader();
|
|
|
|
if(pmrmf)
|
|
{
|
|
PDWORD pdw = (PDWORD) ObtainPtr(pmrmf->nBytes - sizeof(DWORD),
|
|
sizeof(DWORD));
|
|
|
|
if(pdw)
|
|
{
|
|
DWORD dwOffset = pmrmf->nBytes - *pdw;
|
|
|
|
ReleasePtr(pdw);
|
|
|
|
pmreof = (PEMREOF) ObtainRecordPtr(dwOffset);
|
|
}
|
|
|
|
}
|
|
|
|
return pmreof;
|
|
|
|
|
|
}
|
|
|
|
PVOID EMFContainer::pvMapView(UINT64 * ioOffset, UINT32 * ioSize)
|
|
{
|
|
UINT64 qwMappingAlignment = GetFileMappingAlignment();
|
|
UINT64 qwMappingMask = ~(qwMappingAlignment - 1);
|
|
UINT64 qwRecordStart = *ioOffset;
|
|
UINT64 qwRecordEnd = qwRecordStart + *ioSize;
|
|
UINT64 qwViewStart;
|
|
UINT64 qwViewEnd;
|
|
PVOID pvView;
|
|
|
|
qwViewStart = qwRecordStart & qwMappingMask;
|
|
|
|
qwViewEnd = qwViewStart + qwMappingAlignment;
|
|
|
|
if(qwViewEnd < qwRecordEnd)
|
|
{
|
|
qwViewEnd = qwRecordEnd;
|
|
}
|
|
|
|
qwViewEnd = (qwViewEnd + (qwMappingAlignment - 1)) & qwMappingMask;
|
|
|
|
if(qwViewEnd > qwFileSize)
|
|
{
|
|
qwViewEnd = qwFileSize;
|
|
}
|
|
|
|
DWORD dwViewSize = (DWORD) (qwViewEnd - qwViewStart);
|
|
|
|
pvView = MapViewOfFile(hFileMapping,
|
|
FILE_MAP_WRITE,
|
|
HIDWORD(qwViewStart),
|
|
LODWORD(qwViewStart),
|
|
dwViewSize);
|
|
|
|
if(pvView)
|
|
{
|
|
*ioOffset = qwViewStart;
|
|
*ioSize = dwViewSize;
|
|
}
|
|
else
|
|
{
|
|
ioOffset = 0;
|
|
ioSize = 0;
|
|
}
|
|
|
|
return pvView;
|
|
|
|
}
|
|
|
|
BOOL EMFContainer::bBounded(BYTE *p, DWORD dwSize)
|
|
{
|
|
BYTE *pBh = 0, *pEh = 0;
|
|
BYTE *pBw = 0, *pEw = 0;
|
|
BYTE *pBt = 0, *pEt = 0;
|
|
|
|
if (pvWindow)
|
|
{
|
|
pBw = (PBYTE)pvWindow;
|
|
pEw = pBw + dwWindowSize;
|
|
}
|
|
|
|
if (pemfhdr)
|
|
{
|
|
pBh = (PBYTE)pemfhdr;
|
|
pEh = pBh + dwHdrSize;
|
|
}
|
|
|
|
pBt = p;
|
|
pEt = p + dwSize - 1;
|
|
|
|
// The pointer/extent is bounded if the address range they represent are
|
|
// bounded between the address ranges represented by the header range or
|
|
// the window range.
|
|
|
|
if (((pBt >= pBw && pBt < pEw) && (pEt >= pBw && pEt < pEw)) ||
|
|
((pBt >= pBh && pBt < pEh) && (pEt >= pBh && pEt < pEh)))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|