winedump: Support dumping Windows Metafiles.
Signed-off-by: Zhiyi Zhang <zzhang@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
91c9393b7f
commit
788fd4ee44
|
@ -12,6 +12,7 @@ C_SRCS = \
|
||||||
lib.c \
|
lib.c \
|
||||||
lnk.c \
|
lnk.c \
|
||||||
main.c \
|
main.c \
|
||||||
|
mf.c \
|
||||||
minidump.c \
|
minidump.c \
|
||||||
misc.c \
|
misc.c \
|
||||||
msc.c \
|
msc.c \
|
||||||
|
|
|
@ -265,6 +265,7 @@ dumpers[] =
|
||||||
{SIG_MDMP, get_kind_mdmp, mdmp_dump},
|
{SIG_MDMP, get_kind_mdmp, mdmp_dump},
|
||||||
{SIG_LNK, get_kind_lnk, lnk_dump},
|
{SIG_LNK, get_kind_lnk, lnk_dump},
|
||||||
{SIG_EMF, get_kind_emf, emf_dump},
|
{SIG_EMF, get_kind_emf, emf_dump},
|
||||||
|
{SIG_MF, get_kind_mf, mf_dump},
|
||||||
{SIG_FNT, get_kind_fnt, fnt_dump},
|
{SIG_FNT, get_kind_fnt, fnt_dump},
|
||||||
{SIG_TLB, get_kind_tlb, tlb_dump},
|
{SIG_TLB, get_kind_tlb, tlb_dump},
|
||||||
{SIG_NLS, get_kind_nls, nls_dump},
|
{SIG_NLS, get_kind_nls, nls_dump},
|
||||||
|
|
|
@ -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())
|
||||||
|
;
|
||||||
|
}
|
|
@ -216,7 +216,7 @@ const char *get_machine_str(int mach);
|
||||||
|
|
||||||
/* file dumping functions */
|
/* 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,
|
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);
|
const void* PRD(unsigned long prd, unsigned long len);
|
||||||
unsigned long Offset(const void* ptr);
|
unsigned long Offset(const void* ptr);
|
||||||
|
@ -251,6 +251,8 @@ enum FileSig get_kind_lnk(void);
|
||||||
void lnk_dump( void );
|
void lnk_dump( void );
|
||||||
enum FileSig get_kind_emf(void);
|
enum FileSig get_kind_emf(void);
|
||||||
void emf_dump( void );
|
void emf_dump( void );
|
||||||
|
enum FileSig get_kind_mf(void);
|
||||||
|
void mf_dump(void);
|
||||||
enum FileSig get_kind_pdb(void);
|
enum FileSig get_kind_pdb(void);
|
||||||
void pdb_dump(void);
|
void pdb_dump(void);
|
||||||
enum FileSig get_kind_fnt(void);
|
enum FileSig get_kind_fnt(void);
|
||||||
|
|
Loading…
Reference in New Issue