Zhiyi Zhang : winedump: Support dumping Windows Metafiles.

Alexandre Julliard julliard at winehq.org
Tue Apr 20 16:27:47 CDT 2021


Module: wine
Branch: master
Commit: 788fd4ee44fc9877b01888fdd3cd72b9ac88228e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=788fd4ee44fc9877b01888fdd3cd72b9ac88228e

Author: Zhiyi Zhang <zzhang at codeweavers.com>
Date:   Mon Apr 19 15:17:48 2021 +0800

winedump: Support dumping Windows Metafiles.

Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 tools/winedump/Makefile.in |   1 +
 tools/winedump/dump.c      |   1 +
 tools/winedump/mf.c        | 219 +++++++++++++++++++++++++++++++++++++++++++++
 tools/winedump/winedump.h  |   4 +-
 4 files changed, 224 insertions(+), 1 deletion(-)

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);




More information about the wine-cvs mailing list