mf.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*
  2. * Dump a Windows Metafile
  3. *
  4. * Copyright 2021 Zhiyi Zhang for CodeWeavers
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "config.h"
  21. #include "winedump.h"
  22. #include "windef.h"
  23. #include "winbase.h"
  24. #include "wingdi.h"
  25. #define META_EOF 0
  26. #define METAFILE_MEMORY 1
  27. #define METAFILE_DISK 2
  28. static unsigned offset = 0;
  29. static unsigned short read_word(const unsigned char *buffer)
  30. {
  31. return buffer[0] + (buffer[1] << 8);
  32. }
  33. static unsigned int read_int(const unsigned char *buffer)
  34. {
  35. return buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24);
  36. }
  37. static int dump_mfrecord(void)
  38. {
  39. unsigned int type, size, i;
  40. const unsigned char *ptr;
  41. ptr = PRD(offset, 6);
  42. if (!ptr)
  43. return -1;
  44. /* METAHEADER */
  45. if (offset == 0)
  46. {
  47. type = read_word(ptr);
  48. /* mtHeaderSize is in words */
  49. size = read_word(ptr + 2) * 2;
  50. }
  51. /* METARECORD */
  52. else
  53. {
  54. /* rdSize is in words */
  55. size = read_int(ptr) * 2;
  56. type = read_word(ptr + 4);
  57. }
  58. #define MRCASE(x) \
  59. case x: \
  60. printf("%-20s %08x\n", #x, size); \
  61. break
  62. switch (type)
  63. {
  64. case METAFILE_MEMORY:
  65. case METAFILE_DISK:
  66. {
  67. const METAHEADER *header = PRD(offset, sizeof(*header));
  68. printf("%-20s %08x\n", "METAHEADER", size);
  69. printf("type %d header_size %#x version %#x size %#x object_count %d max_record_size %#x "
  70. "parameter_count %d\n",
  71. header->mtType, header->mtHeaderSize * 2, header->mtVersion, header->mtSize * 2,
  72. header->mtNoObjects, header->mtMaxRecord * 2, header->mtNoParameters);
  73. break;
  74. }
  75. MRCASE(META_SETBKCOLOR);
  76. MRCASE(META_SETBKMODE);
  77. MRCASE(META_SETMAPMODE);
  78. MRCASE(META_SETROP2);
  79. MRCASE(META_SETRELABS);
  80. MRCASE(META_SETPOLYFILLMODE);
  81. MRCASE(META_SETSTRETCHBLTMODE);
  82. MRCASE(META_SETTEXTCHAREXTRA);
  83. MRCASE(META_SETTEXTCOLOR);
  84. MRCASE(META_SETTEXTJUSTIFICATION);
  85. MRCASE(META_SETWINDOWORG);
  86. MRCASE(META_SETWINDOWEXT);
  87. MRCASE(META_SETVIEWPORTORG);
  88. MRCASE(META_SETVIEWPORTEXT);
  89. MRCASE(META_OFFSETWINDOWORG);
  90. MRCASE(META_SCALEWINDOWEXT);
  91. MRCASE(META_OFFSETVIEWPORTORG);
  92. MRCASE(META_SCALEVIEWPORTEXT);
  93. MRCASE(META_LINETO);
  94. MRCASE(META_MOVETO);
  95. MRCASE(META_EXCLUDECLIPRECT);
  96. MRCASE(META_INTERSECTCLIPRECT);
  97. MRCASE(META_ARC);
  98. MRCASE(META_ELLIPSE);
  99. MRCASE(META_FLOODFILL);
  100. MRCASE(META_PIE);
  101. MRCASE(META_RECTANGLE);
  102. MRCASE(META_ROUNDRECT);
  103. MRCASE(META_PATBLT);
  104. MRCASE(META_SAVEDC);
  105. MRCASE(META_SETPIXEL);
  106. MRCASE(META_OFFSETCLIPRGN);
  107. MRCASE(META_TEXTOUT);
  108. MRCASE(META_BITBLT);
  109. MRCASE(META_STRETCHBLT);
  110. MRCASE(META_POLYGON);
  111. MRCASE(META_POLYLINE);
  112. MRCASE(META_ESCAPE);
  113. MRCASE(META_RESTOREDC);
  114. MRCASE(META_FILLREGION);
  115. MRCASE(META_FRAMEREGION);
  116. MRCASE(META_INVERTREGION);
  117. MRCASE(META_PAINTREGION);
  118. MRCASE(META_SELECTCLIPREGION);
  119. MRCASE(META_SELECTOBJECT);
  120. MRCASE(META_SETTEXTALIGN);
  121. MRCASE(META_DRAWTEXT);
  122. MRCASE(META_CHORD);
  123. MRCASE(META_SETMAPPERFLAGS);
  124. MRCASE(META_EXTTEXTOUT);
  125. MRCASE(META_SETDIBTODEV);
  126. MRCASE(META_SELECTPALETTE);
  127. MRCASE(META_REALIZEPALETTE);
  128. MRCASE(META_ANIMATEPALETTE);
  129. MRCASE(META_SETPALENTRIES);
  130. MRCASE(META_POLYPOLYGON);
  131. MRCASE(META_RESIZEPALETTE);
  132. MRCASE(META_DIBBITBLT);
  133. MRCASE(META_DIBSTRETCHBLT);
  134. MRCASE(META_DIBCREATEPATTERNBRUSH);
  135. MRCASE(META_STRETCHDIB);
  136. MRCASE(META_EXTFLOODFILL);
  137. MRCASE(META_RESETDC);
  138. MRCASE(META_STARTDOC);
  139. MRCASE(META_STARTPAGE);
  140. MRCASE(META_ENDPAGE);
  141. MRCASE(META_ABORTDOC);
  142. MRCASE(META_ENDDOC);
  143. MRCASE(META_SETLAYOUT);
  144. MRCASE(META_DELETEOBJECT);
  145. MRCASE(META_CREATEPALETTE);
  146. MRCASE(META_CREATEBRUSH);
  147. MRCASE(META_CREATEPATTERNBRUSH);
  148. MRCASE(META_CREATEPENINDIRECT);
  149. MRCASE(META_CREATEFONTINDIRECT);
  150. MRCASE(META_CREATEBRUSHINDIRECT);
  151. MRCASE(META_CREATEBITMAPINDIRECT);
  152. MRCASE(META_CREATEBITMAP);
  153. MRCASE(META_CREATEREGION);
  154. MRCASE(META_UNKNOWN);
  155. MRCASE(META_EOF);
  156. default:
  157. printf("%u %08x\n", type, size);
  158. break;
  159. }
  160. #undef MRCASE
  161. if ((size < 6) || (size % 2))
  162. return -1;
  163. /* METARECORD */
  164. if (offset)
  165. {
  166. size -= 6;
  167. offset += 6;
  168. }
  169. for (i = 0; i < size; i += 2)
  170. {
  171. if (i % 16 == 0)
  172. printf(" ");
  173. if (!(ptr = PRD(offset, 2)))
  174. return -1;
  175. offset += 2;
  176. printf("%04x ", read_word(ptr));
  177. if ((i % 16 == 14) || (i + 2 == size))
  178. printf("\n");
  179. }
  180. return 0;
  181. }
  182. enum FileSig get_kind_mf(void)
  183. {
  184. const METAHEADER *hdr;
  185. hdr = PRD(0, sizeof(*hdr));
  186. if (hdr && (hdr->mtType == METAFILE_MEMORY || hdr->mtType == METAFILE_DISK)
  187. && hdr->mtHeaderSize == sizeof(METAHEADER) / sizeof(WORD)
  188. && (hdr->mtVersion == 0x0100 || hdr->mtVersion == 0x0300))
  189. return SIG_MF;
  190. return SIG_UNKNOWN;
  191. }
  192. void mf_dump(void)
  193. {
  194. offset = 0;
  195. while (!dump_mfrecord())
  196. ;
  197. }