From cfbe32d557f5f07a1e6d6796c478e22274002117 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Sat, 15 Oct 2022 18:15:25 +0200 Subject: [PATCH] winedump: Add initial EMF spool files support. --- tools/winedump/Makefile.in | 1 + tools/winedump/dump.c | 1 + tools/winedump/emfspool.c | 158 +++++++++++++++++++++++++++++++++++++ tools/winedump/winedump.h | 4 +- 4 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 tools/winedump/emfspool.c diff --git a/tools/winedump/Makefile.in b/tools/winedump/Makefile.in index 54028024b0d..04dcacf0216 100644 --- a/tools/winedump/Makefile.in +++ b/tools/winedump/Makefile.in @@ -7,6 +7,7 @@ C_SRCS = \ dos.c \ dump.c \ emf.c \ + emfspool.c \ font.c \ le.c \ lib.c \ diff --git a/tools/winedump/dump.c b/tools/winedump/dump.c index cf52761290b..f2cb601b295 100644 --- a/tools/winedump/dump.c +++ b/tools/winedump/dump.c @@ -255,6 +255,7 @@ dumpers[] = {SIG_MDMP, get_kind_mdmp, mdmp_dump}, {SIG_LNK, get_kind_lnk, lnk_dump}, {SIG_EMF, get_kind_emf, emf_dump}, + {SIG_EMFSPOOL, get_kind_emfspool, emfspool_dump}, {SIG_MF, get_kind_mf, mf_dump}, {SIG_FNT, get_kind_fnt, fnt_dump}, {SIG_TLB, get_kind_tlb, tlb_dump}, diff --git a/tools/winedump/emfspool.c b/tools/winedump/emfspool.c new file mode 100644 index 00000000000..a10b3be2788 --- /dev/null +++ b/tools/winedump/emfspool.c @@ -0,0 +1,158 @@ +/* + * Dump an EMF Spool File + * + * Copyright 2022 Piotr Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "winedump.h" + +#define EMFSPOOL_VERSION 0x10000 + +typedef enum +{ + EMRI_METAFILE = 1, + EMRI_ENGINE_FONT, + EMRI_DEVMODE, + EMRI_TYPE1_FONT, + EMRI_PRESTARTPAGE, + EMRI_DESIGNVECTOR, + EMRI_SUBSET_FONT, + EMRI_DELTA_FONT, + EMRI_FORM_METAFILE, + EMRI_BW_METAFILE, + EMRI_BW_FORM_METAFILE, + EMRI_METAFILE_DATA, + EMRI_METAFILE_EXT, + EMRI_BW_METAFILE_EXT, + EMRI_ENGINE_FONT_EXT, + EMRI_TYPE1_FONT_EXT, + EMRI_DESIGNVECTOR_EXT, + EMRI_SUBSET_FONT_EXT, + EMRI_DELTA_FONT_EXT, + EMRI_PS_JOB_DATA, + EMRI_EMBED_FONT_EXT, +} record_type; + +typedef struct +{ + unsigned int dwVersion; + unsigned int cjSize; + unsigned int dpszDocName; + unsigned int dpszOutput; +} header; + +typedef struct +{ + unsigned int ulID; + unsigned int cjSize; +} record_hdr; + +static const WCHAR* read_wstr(unsigned long off) +{ + const WCHAR *beg, *end; + + if (!off) + return NULL; + + beg = end = PRD(off, sizeof(WCHAR)); + off += sizeof(WCHAR); + if (!beg) + fatal("can't read Unicode string, corrupted file\n"); + + while (*end) + { + end = PRD(off, sizeof(WCHAR)); + off += sizeof(WCHAR); + if (!end) + fatal("can't read Unicode string, corrupted file\n"); + } + return beg; +} + +#define EMRICASE(x) case x: printf("%-24s %08x\n", #x, hdr->cjSize); break +static unsigned long dump_emfspool_record(unsigned long off) +{ + const record_hdr *hdr; + + hdr = PRD(off, sizeof(*hdr)); + if (!hdr) + return 0; + + switch (hdr->ulID) + { + EMRICASE(EMRI_METAFILE); + EMRICASE(EMRI_ENGINE_FONT); + EMRICASE(EMRI_DEVMODE); + EMRICASE(EMRI_TYPE1_FONT); + EMRICASE(EMRI_PRESTARTPAGE); + EMRICASE(EMRI_DESIGNVECTOR); + EMRICASE(EMRI_SUBSET_FONT); + EMRICASE(EMRI_DELTA_FONT); + EMRICASE(EMRI_FORM_METAFILE); + EMRICASE(EMRI_BW_METAFILE); + EMRICASE(EMRI_BW_FORM_METAFILE); + EMRICASE(EMRI_METAFILE_DATA); + EMRICASE(EMRI_METAFILE_EXT); + EMRICASE(EMRI_BW_METAFILE_EXT); + EMRICASE(EMRI_ENGINE_FONT_EXT); + EMRICASE(EMRI_TYPE1_FONT_EXT); + EMRICASE(EMRI_DESIGNVECTOR_EXT); + EMRICASE(EMRI_SUBSET_FONT_EXT); + EMRICASE(EMRI_DELTA_FONT_EXT); + EMRICASE(EMRI_PS_JOB_DATA); + EMRICASE(EMRI_EMBED_FONT_EXT); + default: + printf("%u %08x\n", hdr->ulID, hdr->cjSize); + break; + } + + dump_data((const unsigned char *)(hdr + 1), hdr->cjSize, ""); + return off + sizeof(*hdr) + hdr->cjSize; +} + +enum FileSig get_kind_emfspool(void) +{ + const header *hdr; + + hdr = PRD(0, sizeof(*hdr)); + if (hdr && hdr->dwVersion == EMFSPOOL_VERSION) + return SIG_EMFSPOOL; + return SIG_UNKNOWN; +} + +void emfspool_dump(void) +{ + const WCHAR *doc_name, *output; + unsigned long off; + const header *hdr; + + hdr = PRD(0, sizeof(*hdr)); + if(!hdr) + return; + doc_name = read_wstr(hdr->dpszDocName); + output = read_wstr(hdr->dpszOutput); + + printf("File Header\n"); + printf(" %-20s %#x\n", "dwVersion:", hdr->dwVersion); + printf(" %-20s %#x\n", "cjSize:", hdr->cjSize); + printf(" %-20s %#x %s\n", "dpszDocName:", hdr->dpszDocName, get_unicode_str(doc_name, -1)); + printf(" %-20s %#x %s\n", "dpszOutput:", hdr->dpszOutput, get_unicode_str(output, -1)); + printf("\n"); + + off = hdr->cjSize; + while ((off = dump_emfspool_record(off))); +} diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h index 361f44b62b0..505470436d0 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -214,7 +214,7 @@ const char *get_machine_str(int mach); /* file dumping functions */ enum FileSig {SIG_UNKNOWN, SIG_DOS, SIG_PE, SIG_DBG, SIG_PDB, SIG_NE, SIG_LE, SIG_MDMP, SIG_COFFLIB, SIG_LNK, - SIG_EMF, SIG_MF, SIG_FNT, SIG_TLB, SIG_NLS}; + SIG_EMF, SIG_EMFSPOOL, SIG_MF, SIG_FNT, SIG_TLB, SIG_NLS}; const void* PRD(unsigned long prd, unsigned long len); unsigned long Offset(const void* ptr); @@ -249,6 +249,8 @@ enum FileSig get_kind_lnk(void); void lnk_dump( void ); enum FileSig get_kind_emf(void); void emf_dump( void ); +enum FileSig get_kind_emfspool(void); +void emfspool_dump(void); enum FileSig get_kind_mf(void); void mf_dump(void); enum FileSig get_kind_pdb(void);