diff --git a/tools/winedump/Makefile.in b/tools/winedump/Makefile.in index 43e200ab6ed..54028024b0d 100644 --- a/tools/winedump/Makefile.in +++ b/tools/winedump/Makefile.in @@ -12,6 +12,7 @@ C_SRCS = \ lib.c \ lnk.c \ main.c \ + mf.c \ minidump.c \ misc.c \ msc.c \ diff --git a/tools/winedump/dump.c b/tools/winedump/dump.c index 412880c4bd6..d2e920ef6cb 100644 --- a/tools/winedump/dump.c +++ b/tools/winedump/dump.c @@ -265,6 +265,7 @@ dumpers[] = {SIG_MDMP, get_kind_mdmp, mdmp_dump}, {SIG_LNK, get_kind_lnk, lnk_dump}, {SIG_EMF, get_kind_emf, emf_dump}, + {SIG_MF, get_kind_mf, mf_dump}, {SIG_FNT, get_kind_fnt, fnt_dump}, {SIG_TLB, get_kind_tlb, tlb_dump}, {SIG_NLS, get_kind_nls, nls_dump}, diff --git a/tools/winedump/mf.c b/tools/winedump/mf.c new file mode 100644 index 00000000000..37869d3bb8a --- /dev/null +++ b/tools/winedump/mf.c @@ -0,0 +1,219 @@ +/* + * Dump a Windows Metafile + * + * Copyright 2021 Zhiyi Zhang 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 "config.h" +#include "wine/port.h" +#include "winedump.h" + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" + +#define META_EOF 0 +#define METAFILE_MEMORY 1 +#define METAFILE_DISK 2 + +static unsigned offset = 0; + +static unsigned short read_word(const unsigned char *buffer) +{ + return buffer[0] + (buffer[1] << 8); +} + +static unsigned int read_int(const unsigned char *buffer) +{ + return buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24); +} + +static int dump_mfrecord(void) +{ + unsigned int type, size, i; + const unsigned char *ptr; + + ptr = PRD(offset, 6); + if (!ptr) + return -1; + + /* METAHEADER */ + if (offset == 0) + { + type = read_word(ptr); + /* mtHeaderSize is in words */ + size = read_word(ptr + 2) * 2; + } + /* METARECORD */ + else + { + /* rdSize is in words */ + size = read_int(ptr) * 2; + type = read_word(ptr + 4); + } + +#define MRCASE(x) \ + case x: \ + printf("%-20s %08x\n", #x, size); \ + break + + switch (type) + { + case METAFILE_MEMORY: + case METAFILE_DISK: + { + const METAHEADER *header = PRD(offset, sizeof(*header)); + + printf("%-20s %08x\n", "METAHEADER", size); + printf("type %d header_size %#x version %#x size %#x object_count %d max_record_size %#x " + "parameter_count %d\n", + header->mtType, header->mtHeaderSize * 2, header->mtVersion, header->mtSize * 2, + header->mtNoObjects, header->mtMaxRecord * 2, header->mtNoParameters); + break; + } + MRCASE(META_SETBKCOLOR); + MRCASE(META_SETBKMODE); + MRCASE(META_SETMAPMODE); + MRCASE(META_SETROP2); + MRCASE(META_SETRELABS); + MRCASE(META_SETPOLYFILLMODE); + MRCASE(META_SETSTRETCHBLTMODE); + MRCASE(META_SETTEXTCHAREXTRA); + MRCASE(META_SETTEXTCOLOR); + MRCASE(META_SETTEXTJUSTIFICATION); + MRCASE(META_SETWINDOWORG); + MRCASE(META_SETWINDOWEXT); + MRCASE(META_SETVIEWPORTORG); + MRCASE(META_SETVIEWPORTEXT); + MRCASE(META_OFFSETWINDOWORG); + MRCASE(META_SCALEWINDOWEXT); + MRCASE(META_OFFSETVIEWPORTORG); + MRCASE(META_SCALEVIEWPORTEXT); + MRCASE(META_LINETO); + MRCASE(META_MOVETO); + MRCASE(META_EXCLUDECLIPRECT); + MRCASE(META_INTERSECTCLIPRECT); + MRCASE(META_ARC); + MRCASE(META_ELLIPSE); + MRCASE(META_FLOODFILL); + MRCASE(META_PIE); + MRCASE(META_RECTANGLE); + MRCASE(META_ROUNDRECT); + MRCASE(META_PATBLT); + MRCASE(META_SAVEDC); + MRCASE(META_SETPIXEL); + MRCASE(META_OFFSETCLIPRGN); + MRCASE(META_TEXTOUT); + MRCASE(META_BITBLT); + MRCASE(META_STRETCHBLT); + MRCASE(META_POLYGON); + MRCASE(META_POLYLINE); + MRCASE(META_ESCAPE); + MRCASE(META_RESTOREDC); + MRCASE(META_FILLREGION); + MRCASE(META_FRAMEREGION); + MRCASE(META_INVERTREGION); + MRCASE(META_PAINTREGION); + MRCASE(META_SELECTCLIPREGION); + MRCASE(META_SELECTOBJECT); + MRCASE(META_SETTEXTALIGN); + MRCASE(META_DRAWTEXT); + MRCASE(META_CHORD); + MRCASE(META_SETMAPPERFLAGS); + MRCASE(META_EXTTEXTOUT); + MRCASE(META_SETDIBTODEV); + MRCASE(META_SELECTPALETTE); + MRCASE(META_REALIZEPALETTE); + MRCASE(META_ANIMATEPALETTE); + MRCASE(META_SETPALENTRIES); + MRCASE(META_POLYPOLYGON); + MRCASE(META_RESIZEPALETTE); + MRCASE(META_DIBBITBLT); + MRCASE(META_DIBSTRETCHBLT); + MRCASE(META_DIBCREATEPATTERNBRUSH); + MRCASE(META_STRETCHDIB); + MRCASE(META_EXTFLOODFILL); + MRCASE(META_RESETDC); + MRCASE(META_STARTDOC); + MRCASE(META_STARTPAGE); + MRCASE(META_ENDPAGE); + MRCASE(META_ABORTDOC); + MRCASE(META_ENDDOC); + MRCASE(META_SETLAYOUT); + MRCASE(META_DELETEOBJECT); + MRCASE(META_CREATEPALETTE); + MRCASE(META_CREATEBRUSH); + MRCASE(META_CREATEPATTERNBRUSH); + MRCASE(META_CREATEPENINDIRECT); + MRCASE(META_CREATEFONTINDIRECT); + MRCASE(META_CREATEBRUSHINDIRECT); + MRCASE(META_CREATEBITMAPINDIRECT); + MRCASE(META_CREATEBITMAP); + MRCASE(META_CREATEREGION); + MRCASE(META_UNKNOWN); + MRCASE(META_EOF); + + default: + printf("%u %08x\n", type, size); + break; + } + +#undef MRCASE + + if ((size < 6) || (size % 2)) + return -1; + + /* METARECORD */ + if (offset) + { + size -= 6; + offset += 6; + } + + for (i = 0; i < size; i += 2) + { + if (i % 16 == 0) + printf(" "); + if (!(ptr = PRD(offset, 2))) + return -1; + offset += 2; + printf("%04x ", read_word(ptr)); + if ((i % 16 == 14) || (i + 2 == size)) + printf("\n"); + } + + return 0; +} + +enum FileSig get_kind_mf(void) +{ + const METAHEADER *hdr; + + hdr = PRD(0, sizeof(*hdr)); + if (hdr && (hdr->mtType == METAFILE_MEMORY || hdr->mtType == METAFILE_DISK) + && hdr->mtHeaderSize == sizeof(METAHEADER) / sizeof(WORD) + && (hdr->mtVersion == 0x0100 || hdr->mtVersion == 0x0300)) + return SIG_MF; + return SIG_UNKNOWN; +} + +void mf_dump(void) +{ + offset = 0; + while (!dump_mfrecord()) + ; +} diff --git a/tools/winedump/winedump.h b/tools/winedump/winedump.h index 240f31d2f2d..16b9cdc7cf8 100644 --- a/tools/winedump/winedump.h +++ b/tools/winedump/winedump.h @@ -216,7 +216,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_FNT, SIG_TLB, SIG_NLS}; + SIG_EMF, SIG_MF, SIG_FNT, SIG_TLB, SIG_NLS}; const void* PRD(unsigned long prd, unsigned long len); unsigned long Offset(const void* ptr); @@ -251,6 +251,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_mf(void); +void mf_dump(void); enum FileSig get_kind_pdb(void); void pdb_dump(void); enum FileSig get_kind_fnt(void);