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.
386 lines
12 KiB
386 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
emfspool.hxx
|
|
|
|
Abstract:
|
|
|
|
EMF spooling functions - header file
|
|
|
|
Environment:
|
|
|
|
Windows NT GDI
|
|
|
|
Revision History:
|
|
|
|
01/19/98 -davidx-
|
|
Created it.
|
|
|
|
--*/
|
|
|
|
|
|
#ifndef _EMFSPOOL_H_
|
|
#define _EMFSPOOL_H_
|
|
|
|
|
|
//
|
|
// Data structure for a linked-list of temporary data buffers
|
|
//
|
|
|
|
typedef struct _TempSpoolBuf {
|
|
|
|
DWORD maxSize;
|
|
DWORD currentSize;
|
|
BYTE data[1];
|
|
|
|
} TempSpoolBuf, *PTempSpoolBuf;
|
|
|
|
#define TEMPBUF_DATAOFFSET offsetof(TempSpoolBuf, data)
|
|
|
|
//
|
|
// Special error value for EMFSpoolData.emfrOffset field
|
|
//
|
|
|
|
#define INVALID_EMFROFFSET ((UINT64) -1)
|
|
|
|
//
|
|
// EMF container class used to abstract access to the EMF data allowing us
|
|
// to implement a sliding window mapping when the stream is stored in a file.
|
|
//
|
|
|
|
typedef struct EMFContainer
|
|
{
|
|
|
|
public:
|
|
|
|
// Init() intializes the EMFContainer from an in memory buffer. The METAHEADER
|
|
// must have a valid nSize value which is used to determine the size of the
|
|
// EMF stream (and thus, how much data is valid).
|
|
|
|
VOID Init(PENHMETAHEADER inHdr, UINT32 inFileSize);
|
|
|
|
// This version of Init() intializes the EMFContainer from a file handle and
|
|
// is given the total size of the file and the offset to the EMFHEADER.
|
|
|
|
BOOL Init(HANDLE inFile, UINT64 inHdrOffset, UINT64 inFileSize);
|
|
|
|
// Term() must be called after Init() has been called successfully.
|
|
|
|
VOID Term();
|
|
|
|
//
|
|
// Pointer to header remains valid till call to Term()
|
|
//
|
|
|
|
ENHMETAHEADER * GetEMFHeader()
|
|
{
|
|
return pemfhdr;
|
|
}
|
|
|
|
// ObtainPtr() obtains a pointer that the user can use to reference the
|
|
// emf stream. This pointer remains valid the caller calls ReleasePtr.
|
|
// Any pointer obtained must be released via ReleasePtr().
|
|
|
|
// Only one pointer obtained via ObtainPtr(), ObtainRecordPtr() or
|
|
// ObtainEOFRecordPtr() can be valid at one time. An attempt to obtain
|
|
// a second ptr via one of these calls when a previous ptr is still valid
|
|
// (the release has not been called yet for the ptr) will fail.
|
|
//
|
|
|
|
PVOID ObtainPtr(UINT inOffset, UINT inSize);
|
|
|
|
// ReleasePtr() releases a reference obtained via ObtainPtr().
|
|
|
|
VOID ReleasePtr(PVOID inPtr)
|
|
{
|
|
ASSERTGDI(dwRefCount != 0, "EMFContainer::ReleasePtr() releasing with zero ref count\n");
|
|
dwRefCount--;
|
|
}
|
|
|
|
// ObtainRecordPtr() obtains a pointer to an EMF record stored at the given
|
|
// offset. Note that the record's header must be valid allowing
|
|
// the call to derive the size of the record from the header.
|
|
// NOTE: the EMFHeader pointer obtained via GetEMFHeader() is special and
|
|
// is always valid and does not need to be released.
|
|
//
|
|
|
|
PENHMETARECORD ObtainRecordPtr(UINT inOffset);
|
|
|
|
// ReleaseRecordPtr() releases a record ptr obtained via ObtainRecordPtr().
|
|
|
|
VOID ReleaseRecordPtr(PENHMETARECORD inPtr)
|
|
{
|
|
ReleasePtr(inPtr);
|
|
}
|
|
|
|
// ObtainEOFRecordPtr() obtains a pointer the the EOF record of the emf
|
|
// stream. The EMF streams EMFHEADER must be valid and the streams EOF
|
|
// record must be valid in order for this call to be successful.
|
|
|
|
PEMREOF ObtainEOFRecordPtr();
|
|
|
|
// ReleaseEOFRecordPtr() releases a pointer obtained via ObtainEOFRecordPtr().
|
|
|
|
VOID ReleaseEOFRecordPtr(PEMREOF pmreof)
|
|
{
|
|
ReleaseRecordPtr((PENHMETARECORD) pmreof);
|
|
}
|
|
|
|
UINT32 GetdwHdrSize() { return dwHdrSize; }
|
|
|
|
BOOL bBounded(BYTE *p, DWORD dwSize);
|
|
|
|
private:
|
|
|
|
PVOID pvMapView(UINT64 * ioOffset, UINT32 * ioSize);
|
|
|
|
ULONG dwRefCount; // number of outstanding pointer references
|
|
// Can be zero or one. We do not support
|
|
// multiple outstanding references.
|
|
|
|
PENHMETAHEADER pemfhdr; // pointer to EMFHEeader. Always valid.
|
|
UINT32 dwHdrSize; // Size of valid header data (can be larger
|
|
// then the header size and may actual be
|
|
// the size of the stream allowing the
|
|
// stream to be accessed via this pointer
|
|
// alone).
|
|
|
|
PVOID pvHdr; // pointer to EMFHeader mapping or NULL.
|
|
// May be different then pemfhdr (if pemfhdr
|
|
// mapping did not fall on an even mapping
|
|
// alignmnet).
|
|
|
|
PVOID pvWindow; // pointer to sliding window mapping
|
|
UINT32 dwWindowUnusable; // number of bytes that are unusable
|
|
// at the start of the window mapping.
|
|
// Non-zero when mapping starts before
|
|
// emfheader file offset.
|
|
UINT32 dwWindowOffset; // Offset in file of window.
|
|
UINT32 dwWindowSize; // size of the window in bytes
|
|
|
|
HANDLE hFile; // file handle for EMF stream (null if
|
|
// stream is entirely in memory)
|
|
UINT64 qwHdrOffset; // file offset to EMF header
|
|
UINT64 qwFileSize; // total size of file in bytes
|
|
|
|
HANDLE hFileMapping; // file mapping used to obtain mappings
|
|
// into the file.
|
|
|
|
} EMFContainer;
|
|
|
|
//
|
|
// Class for representing extra information used during EMF spooling
|
|
//
|
|
|
|
class MDC;
|
|
|
|
class EMFSpoolData
|
|
{
|
|
public:
|
|
|
|
//
|
|
// Initialization and cleanup functions.
|
|
// These are needed because GDI doesn't use new and delete operators.
|
|
//
|
|
|
|
BOOL Init(HANDLE hSpooler, BOOL banding);
|
|
VOID Cleanup();
|
|
|
|
// GetPtr - Return a pointer to emf data starting at inOffset and having
|
|
// size inSize. This pointer must be released by calling ReleaesPtr().
|
|
// If this call fails NULL is returned.
|
|
|
|
PVOID GetPtr(UINT32 inOffset, UINT32 inSize);
|
|
|
|
// ReleasePtr() - Releases a poitner obtained via GetPtr().
|
|
|
|
VOID ReleasePtr(PVOID inPtr);
|
|
|
|
// ResizeCurrentBuffer - Expand the size of the current buffer
|
|
|
|
BOOL ResizeCurrentBuffer(DWORD newsize);
|
|
|
|
// WriteData - Write data to the memory-mapped spool file
|
|
|
|
BOOL WriteData(PVOID buffer, DWORD size);
|
|
|
|
// GetTotalSize - Return the total number of bytes written to the mapped file
|
|
|
|
UINT64 GetTotalSize() { return mapStart + currentOffset; }
|
|
|
|
// CompleteCurrentBuffer - Finish working with the current buffer and move on to the next
|
|
|
|
VOID CompleteCurrentBuffer(DWORD size)
|
|
{
|
|
if(bMapping)
|
|
{
|
|
currentOffset += size;
|
|
|
|
ASSERTGDI(size % sizeof(DWORD) == 0, "CompleteCurrentBuffer: misalignment\n");
|
|
ASSERTGDI(currentOffset <= mapSize, "CompleteCurrentBuffer: overflow\n");
|
|
}
|
|
}
|
|
|
|
//
|
|
// GetEMFData - Initialize buffer to start EMF recording associating
|
|
// the MDC with the spooler.
|
|
// NOTE: this is a very poorly named function. This call is used to
|
|
// kick off the recording process (it does not really get EMF data at
|
|
// all).
|
|
//
|
|
BOOL GetEMFData(MDC *pmdc);
|
|
|
|
//
|
|
// ResizeEMFData - Resize current EMF data buffer
|
|
//
|
|
|
|
BOOL ResizeEMFData(DWORD size);
|
|
|
|
//
|
|
// CompleteEMFData - Finish recording EMF data
|
|
//
|
|
|
|
BOOL CompleteEMFData(DWORD size, HANDLE* outFile, UINT64* outOffset);
|
|
|
|
//
|
|
// AbortEMFData - Stop recording EMF data
|
|
//
|
|
|
|
BOOL AbortEMFData();
|
|
|
|
//
|
|
// MapFile - Map the EMF spool file into the current process' address space
|
|
// UnmapFile - Unmap the currently mapped EMF spool file
|
|
// FlushPage - Flush the current content of the mapped file to spooler
|
|
//
|
|
|
|
BOOL MapFile();
|
|
VOID UnmapFile(BOOL bCloseHandle = TRUE);
|
|
BOOL FlushPage(DWORD pageType);
|
|
|
|
VOID ResetMappingState()
|
|
{
|
|
bMapping = FALSE;
|
|
mapStart = committedSize = 0;
|
|
mapSize = currentOffset = 0;
|
|
emfrOffset = INVALID_EMFROFFSET;
|
|
}
|
|
|
|
//
|
|
// Remember where a font related EMFITEMHEADER_EXT record is
|
|
//
|
|
|
|
BOOL AddFontExtRecord(DWORD recType, DWORD offset);
|
|
|
|
//
|
|
// Whether we're banding on the client side. This happens when:
|
|
// Printer driver requests banding and
|
|
// EMF spooling is not enabled
|
|
//
|
|
|
|
BOOL IsBanding() { return bBanding; }
|
|
|
|
private:
|
|
|
|
DWORD signature; // data structure signature
|
|
HANDLE hPrinter; // spooler handle to the current printer
|
|
HANDLE hFile; // file handle to the currently mapped spool file
|
|
UINT64 committedSize; // number of bytes already commited
|
|
UINT64 emfrOffset; // starting offset for EMRI_METAFILE_DATA record
|
|
BOOL bMapping;
|
|
UINT64 mapStart; // starting offset for the current view
|
|
DWORD mapSize; // size of current view
|
|
DWORD currentOffset; // current offset relative to the start of current view
|
|
BOOL bBanding; // whether GDI is doing banding on the current DC
|
|
MDC *pmdcActive; // whether we're actively recording EMF data
|
|
|
|
//
|
|
// Abstract class to manage access to EMF data via sliding window (if file
|
|
// based access).
|
|
//
|
|
EMFContainer emfc;
|
|
|
|
//
|
|
// Scratch data buffer: If WriteData is called while we're in the middle
|
|
// of recording EMF data for a page, then we cache the data in the scratch
|
|
// buffer.
|
|
//
|
|
|
|
PTempSpoolBuf scratchBuf;
|
|
|
|
//
|
|
// Temporary buffer for caching information about various font related
|
|
// spool file records that we embedded as comments inside EMF data
|
|
//
|
|
|
|
PTempSpoolBuf fontBuf;
|
|
|
|
//
|
|
// constructor / destructor
|
|
//
|
|
// NOTE: Since GDI doesn't use new and delete operators.
|
|
// We allocate and deallocate object memory ourselves.
|
|
// So we make constructor and destructor private so that
|
|
// nobody can use new and delete on EMFSpoolData object.
|
|
//
|
|
|
|
EMFSpoolData() {}
|
|
~EMFSpoolData() {}
|
|
|
|
// PVOID GetCurrentBuffer();
|
|
|
|
//
|
|
// Private methods for working with temporary buffers
|
|
//
|
|
|
|
BOOL WriteTempData(PTempSpoolBuf *ppBuf, PVOID data, DWORD size);
|
|
BOOL FlushTempBuffer(PTempSpoolBuf buf);
|
|
BOOL FlushFontExtRecords();
|
|
VOID FreeTempBuffers(BOOL freeMem = TRUE);
|
|
|
|
//
|
|
// Create a temporary spool file when we're using EMF for banding
|
|
//
|
|
|
|
HANDLE GetTempSpoolFileHandle();
|
|
|
|
//
|
|
// Ugh, we have to impliment this locally because of how we do
|
|
// the EMFITEMHEADER goop. A pointer obtained via this call
|
|
// must also be released vie ReleasePtr().
|
|
//
|
|
PVOID GetPtrUsingSignedOffset(INT32 inOffset, UINT32 inSize);
|
|
};
|
|
|
|
|
|
//
|
|
// Tracing macro used by EMF spooling functions
|
|
//
|
|
//#define TRACE_EMFSPL_ENABLED
|
|
|
|
#if DBG && defined(TRACE_EMFSPL_ENABLED)
|
|
#define TRACE_EMFSPL(arg) DbgPrint arg
|
|
#else
|
|
#define TRACE_EMFSPL(arg)
|
|
#endif
|
|
|
|
|
|
#ifndef HIDWORD
|
|
|
|
//
|
|
// Our own macros for working with 64-bit integer values
|
|
// WINBUG #82848 2-7-2000 bhouse Investigate using system wide definitons for getting hi/low dword of 64bit values
|
|
// Old Comment:
|
|
// - Use this until we have a system-wide definition in place.
|
|
//
|
|
|
|
#define LODWORD(i64) ((DWORD) (i64))
|
|
#define HIDWORD(i64) ((DWORD) ((UINT64) (i64) >> 32))
|
|
|
|
#endif
|
|
|
|
#endif // !_EMFSPOOL_H_
|
|
|