2022-10-15 16:15:25 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2023-01-30 08:31:32 +00:00
|
|
|
#include "config.h"
|
2022-10-15 16:15:25 +00:00
|
|
|
#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;
|
|
|
|
|
2022-10-15 18:52:44 +00:00
|
|
|
static inline void print_longlong(ULONGLONG value)
|
|
|
|
{
|
|
|
|
if (sizeof(value) > sizeof(unsigned long) && value >> 32)
|
|
|
|
printf("0x%lx%08lx", (unsigned long)(value >> 32), (unsigned long)value);
|
|
|
|
else
|
|
|
|
printf("0x%lx", (unsigned long)value);
|
|
|
|
}
|
|
|
|
|
2022-10-15 16:15:25 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-10-15 18:36:33 +00:00
|
|
|
switch (hdr->ulID)
|
|
|
|
{
|
|
|
|
case EMRI_METAFILE:
|
|
|
|
case EMRI_FORM_METAFILE:
|
|
|
|
case EMRI_BW_METAFILE:
|
|
|
|
case EMRI_BW_FORM_METAFILE:
|
|
|
|
case EMRI_METAFILE_DATA:
|
|
|
|
{
|
|
|
|
unsigned long emf_off = off + sizeof(*hdr);
|
2022-10-15 19:13:37 +00:00
|
|
|
while ((emf_off = dump_emfrecord(" ", emf_off)) && emf_off < off + sizeof(*hdr) + hdr->cjSize);
|
2022-10-15 18:36:33 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-10-15 18:52:44 +00:00
|
|
|
case EMRI_METAFILE_EXT:
|
|
|
|
case EMRI_BW_METAFILE_EXT:
|
|
|
|
{
|
|
|
|
const ULONGLONG *emf_off = PRD(off + sizeof(*hdr), sizeof(*emf_off));
|
|
|
|
if (!emf_off)
|
|
|
|
fatal("truncated file\n");
|
|
|
|
printf(" %-20s ", "offset");
|
|
|
|
print_longlong(*emf_off);
|
|
|
|
printf(" (absolute position ");
|
|
|
|
print_longlong(off - *emf_off);
|
|
|
|
printf(")\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-10-15 18:36:33 +00:00
|
|
|
default:
|
|
|
|
dump_data((const unsigned char *)(hdr + 1), hdr->cjSize, "");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2022-10-15 16:15:25 +00:00
|
|
|
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)));
|
|
|
|
}
|