Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. emfspool.hxx
  5. Abstract:
  6. EMF spooling functions - header file
  7. Environment:
  8. Windows NT GDI
  9. Revision History:
  10. 01/19/98 -davidx-
  11. Created it.
  12. --*/
  13. #ifndef _EMFSPOOL_H_
  14. #define _EMFSPOOL_H_
  15. //
  16. // Data structure for a linked-list of temporary data buffers
  17. //
  18. typedef struct _TempSpoolBuf {
  19. DWORD maxSize;
  20. DWORD currentSize;
  21. BYTE data[1];
  22. } TempSpoolBuf, *PTempSpoolBuf;
  23. #define TEMPBUF_DATAOFFSET offsetof(TempSpoolBuf, data)
  24. //
  25. // Special error value for EMFSpoolData.emfrOffset field
  26. //
  27. #define INVALID_EMFROFFSET ((UINT64) -1)
  28. //
  29. // EMF container class used to abstract access to the EMF data allowing us
  30. // to implement a sliding window mapping when the stream is stored in a file.
  31. //
  32. typedef struct EMFContainer
  33. {
  34. public:
  35. // Init() intializes the EMFContainer from an in memory buffer. The METAHEADER
  36. // must have a valid nSize value which is used to determine the size of the
  37. // EMF stream (and thus, how much data is valid).
  38. VOID Init(PENHMETAHEADER inHdr, UINT32 inFileSize);
  39. // This version of Init() intializes the EMFContainer from a file handle and
  40. // is given the total size of the file and the offset to the EMFHEADER.
  41. BOOL Init(HANDLE inFile, UINT64 inHdrOffset, UINT64 inFileSize);
  42. // Term() must be called after Init() has been called successfully.
  43. VOID Term();
  44. //
  45. // Pointer to header remains valid till call to Term()
  46. //
  47. ENHMETAHEADER * GetEMFHeader()
  48. {
  49. return pemfhdr;
  50. }
  51. // ObtainPtr() obtains a pointer that the user can use to reference the
  52. // emf stream. This pointer remains valid the caller calls ReleasePtr.
  53. // Any pointer obtained must be released via ReleasePtr().
  54. // Only one pointer obtained via ObtainPtr(), ObtainRecordPtr() or
  55. // ObtainEOFRecordPtr() can be valid at one time. An attempt to obtain
  56. // a second ptr via one of these calls when a previous ptr is still valid
  57. // (the release has not been called yet for the ptr) will fail.
  58. //
  59. PVOID ObtainPtr(UINT inOffset, UINT inSize);
  60. // ReleasePtr() releases a reference obtained via ObtainPtr().
  61. VOID ReleasePtr(PVOID inPtr)
  62. {
  63. ASSERTGDI(dwRefCount != 0, "EMFContainer::ReleasePtr() releasing with zero ref count\n");
  64. dwRefCount--;
  65. }
  66. // ObtainRecordPtr() obtains a pointer to an EMF record stored at the given
  67. // offset. Note that the record's header must be valid allowing
  68. // the call to derive the size of the record from the header.
  69. // NOTE: the EMFHeader pointer obtained via GetEMFHeader() is special and
  70. // is always valid and does not need to be released.
  71. //
  72. PENHMETARECORD ObtainRecordPtr(UINT inOffset);
  73. // ReleaseRecordPtr() releases a record ptr obtained via ObtainRecordPtr().
  74. VOID ReleaseRecordPtr(PENHMETARECORD inPtr)
  75. {
  76. ReleasePtr(inPtr);
  77. }
  78. // ObtainEOFRecordPtr() obtains a pointer the the EOF record of the emf
  79. // stream. The EMF streams EMFHEADER must be valid and the streams EOF
  80. // record must be valid in order for this call to be successful.
  81. PEMREOF ObtainEOFRecordPtr();
  82. // ReleaseEOFRecordPtr() releases a pointer obtained via ObtainEOFRecordPtr().
  83. VOID ReleaseEOFRecordPtr(PEMREOF pmreof)
  84. {
  85. ReleaseRecordPtr((PENHMETARECORD) pmreof);
  86. }
  87. UINT32 GetdwHdrSize() { return dwHdrSize; }
  88. BOOL bBounded(BYTE *p, DWORD dwSize);
  89. private:
  90. PVOID pvMapView(UINT64 * ioOffset, UINT32 * ioSize);
  91. ULONG dwRefCount; // number of outstanding pointer references
  92. // Can be zero or one. We do not support
  93. // multiple outstanding references.
  94. PENHMETAHEADER pemfhdr; // pointer to EMFHEeader. Always valid.
  95. UINT32 dwHdrSize; // Size of valid header data (can be larger
  96. // then the header size and may actual be
  97. // the size of the stream allowing the
  98. // stream to be accessed via this pointer
  99. // alone).
  100. PVOID pvHdr; // pointer to EMFHeader mapping or NULL.
  101. // May be different then pemfhdr (if pemfhdr
  102. // mapping did not fall on an even mapping
  103. // alignmnet).
  104. PVOID pvWindow; // pointer to sliding window mapping
  105. UINT32 dwWindowUnusable; // number of bytes that are unusable
  106. // at the start of the window mapping.
  107. // Non-zero when mapping starts before
  108. // emfheader file offset.
  109. UINT32 dwWindowOffset; // Offset in file of window.
  110. UINT32 dwWindowSize; // size of the window in bytes
  111. HANDLE hFile; // file handle for EMF stream (null if
  112. // stream is entirely in memory)
  113. UINT64 qwHdrOffset; // file offset to EMF header
  114. UINT64 qwFileSize; // total size of file in bytes
  115. HANDLE hFileMapping; // file mapping used to obtain mappings
  116. // into the file.
  117. } EMFContainer;
  118. //
  119. // Class for representing extra information used during EMF spooling
  120. //
  121. class MDC;
  122. class EMFSpoolData
  123. {
  124. public:
  125. //
  126. // Initialization and cleanup functions.
  127. // These are needed because GDI doesn't use new and delete operators.
  128. //
  129. BOOL Init(HANDLE hSpooler, BOOL banding);
  130. VOID Cleanup();
  131. // GetPtr - Return a pointer to emf data starting at inOffset and having
  132. // size inSize. This pointer must be released by calling ReleaesPtr().
  133. // If this call fails NULL is returned.
  134. PVOID GetPtr(UINT32 inOffset, UINT32 inSize);
  135. // ReleasePtr() - Releases a poitner obtained via GetPtr().
  136. VOID ReleasePtr(PVOID inPtr);
  137. // ResizeCurrentBuffer - Expand the size of the current buffer
  138. BOOL ResizeCurrentBuffer(DWORD newsize);
  139. // WriteData - Write data to the memory-mapped spool file
  140. BOOL WriteData(PVOID buffer, DWORD size);
  141. // GetTotalSize - Return the total number of bytes written to the mapped file
  142. UINT64 GetTotalSize() { return mapStart + currentOffset; }
  143. // CompleteCurrentBuffer - Finish working with the current buffer and move on to the next
  144. VOID CompleteCurrentBuffer(DWORD size)
  145. {
  146. if(bMapping)
  147. {
  148. currentOffset += size;
  149. ASSERTGDI(size % sizeof(DWORD) == 0, "CompleteCurrentBuffer: misalignment\n");
  150. ASSERTGDI(currentOffset <= mapSize, "CompleteCurrentBuffer: overflow\n");
  151. }
  152. }
  153. //
  154. // GetEMFData - Initialize buffer to start EMF recording associating
  155. // the MDC with the spooler.
  156. // NOTE: this is a very poorly named function. This call is used to
  157. // kick off the recording process (it does not really get EMF data at
  158. // all).
  159. //
  160. BOOL GetEMFData(MDC *pmdc);
  161. //
  162. // ResizeEMFData - Resize current EMF data buffer
  163. //
  164. BOOL ResizeEMFData(DWORD size);
  165. //
  166. // CompleteEMFData - Finish recording EMF data
  167. //
  168. BOOL CompleteEMFData(DWORD size, HANDLE* outFile, UINT64* outOffset);
  169. //
  170. // AbortEMFData - Stop recording EMF data
  171. //
  172. BOOL AbortEMFData();
  173. //
  174. // MapFile - Map the EMF spool file into the current process' address space
  175. // UnmapFile - Unmap the currently mapped EMF spool file
  176. // FlushPage - Flush the current content of the mapped file to spooler
  177. //
  178. BOOL MapFile();
  179. VOID UnmapFile(BOOL bCloseHandle = TRUE);
  180. BOOL FlushPage(DWORD pageType);
  181. VOID ResetMappingState()
  182. {
  183. bMapping = FALSE;
  184. mapStart = committedSize = 0;
  185. mapSize = currentOffset = 0;
  186. emfrOffset = INVALID_EMFROFFSET;
  187. }
  188. //
  189. // Remember where a font related EMFITEMHEADER_EXT record is
  190. //
  191. BOOL AddFontExtRecord(DWORD recType, DWORD offset);
  192. //
  193. // Whether we're banding on the client side. This happens when:
  194. // Printer driver requests banding and
  195. // EMF spooling is not enabled
  196. //
  197. BOOL IsBanding() { return bBanding; }
  198. private:
  199. DWORD signature; // data structure signature
  200. HANDLE hPrinter; // spooler handle to the current printer
  201. HANDLE hFile; // file handle to the currently mapped spool file
  202. UINT64 committedSize; // number of bytes already commited
  203. UINT64 emfrOffset; // starting offset for EMRI_METAFILE_DATA record
  204. BOOL bMapping;
  205. UINT64 mapStart; // starting offset for the current view
  206. DWORD mapSize; // size of current view
  207. DWORD currentOffset; // current offset relative to the start of current view
  208. BOOL bBanding; // whether GDI is doing banding on the current DC
  209. MDC *pmdcActive; // whether we're actively recording EMF data
  210. //
  211. // Abstract class to manage access to EMF data via sliding window (if file
  212. // based access).
  213. //
  214. EMFContainer emfc;
  215. //
  216. // Scratch data buffer: If WriteData is called while we're in the middle
  217. // of recording EMF data for a page, then we cache the data in the scratch
  218. // buffer.
  219. //
  220. PTempSpoolBuf scratchBuf;
  221. //
  222. // Temporary buffer for caching information about various font related
  223. // spool file records that we embedded as comments inside EMF data
  224. //
  225. PTempSpoolBuf fontBuf;
  226. //
  227. // constructor / destructor
  228. //
  229. // NOTE: Since GDI doesn't use new and delete operators.
  230. // We allocate and deallocate object memory ourselves.
  231. // So we make constructor and destructor private so that
  232. // nobody can use new and delete on EMFSpoolData object.
  233. //
  234. EMFSpoolData() {}
  235. ~EMFSpoolData() {}
  236. // PVOID GetCurrentBuffer();
  237. //
  238. // Private methods for working with temporary buffers
  239. //
  240. BOOL WriteTempData(PTempSpoolBuf *ppBuf, PVOID data, DWORD size);
  241. BOOL FlushTempBuffer(PTempSpoolBuf buf);
  242. BOOL FlushFontExtRecords();
  243. VOID FreeTempBuffers(BOOL freeMem = TRUE);
  244. //
  245. // Create a temporary spool file when we're using EMF for banding
  246. //
  247. HANDLE GetTempSpoolFileHandle();
  248. //
  249. // Ugh, we have to impliment this locally because of how we do
  250. // the EMFITEMHEADER goop. A pointer obtained via this call
  251. // must also be released vie ReleasePtr().
  252. //
  253. PVOID GetPtrUsingSignedOffset(INT32 inOffset, UINT32 inSize);
  254. };
  255. //
  256. // Tracing macro used by EMF spooling functions
  257. //
  258. //#define TRACE_EMFSPL_ENABLED
  259. #if DBG && defined(TRACE_EMFSPL_ENABLED)
  260. #define TRACE_EMFSPL(arg) DbgPrint arg
  261. #else
  262. #define TRACE_EMFSPL(arg)
  263. #endif
  264. #ifndef HIDWORD
  265. //
  266. // Our own macros for working with 64-bit integer values
  267. // WINBUG #82848 2-7-2000 bhouse Investigate using system wide definitons for getting hi/low dword of 64bit values
  268. // Old Comment:
  269. // - Use this until we have a system-wide definition in place.
  270. //
  271. #define LODWORD(i64) ((DWORD) (i64))
  272. #define HIDWORD(i64) ((DWORD) ((UINT64) (i64) >> 32))
  273. #endif
  274. #endif // !_EMFSPOOL_H_