5 * Created by Alyssa Milburn on Mon Apr 28 2008.
6 * Copyright (c) 2008 Alyssa Milburn. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
21 #include "exceptions.h"
22 #include "streamutils.h"
25 std::string
nameForType(uint32 t
) {
27 case 1: return "Cursor";
28 case 2: return "Bitmap";
29 case 3: return "Icon";
30 case 4: return "Menu";
31 case 5: return "Dialog";
32 case 6: return "String";
33 case 7: return "Fontdir";
34 case 8: return "Font";
35 case 9: return "Accelerator";
36 case 10: return "RCData";
37 case 11: return "MessageTable";
38 case 16: return "Version";
45 * This isn't a full PE parser, but it manages to extract resources from the
46 * .exe files included with both Creatures and Creatures 2.
49 peFile::peFile(fs::path filepath
) {
51 file
.open(path
.native_directory_string().c_str(), std::ios::binary
);
54 throw creaturesException(std::string("couldn't open PE file \"") + path
.native_directory_string() + "\"");
56 // check the signature of the file
59 if (strncmp(majic
, "MZ", 2) != 0)
60 throw creaturesException(std::string("couldn't understand PE file \"") + path
.native_directory_string() + "\" (not a PE file?)");
62 // skip the rest of the DOS header
63 file
.seekg(58, std::ios::cur
);
65 // read the location of the PE header
66 uint32 e_lfanew
= read32(file
);
68 throw creaturesException(std::string("couldn't understand PE file \"") + path
.native_directory_string() + "\" (DOS program?)");
70 // seek to the PE header and check the signature
71 file
.seekg(e_lfanew
, std::ios::beg
);
73 file
.read(pemajic
, 4);
74 if (memcmp(pemajic
, "PE\0\0", 4) != 0)
75 throw creaturesException(std::string("couldn't understand PE file \"") + path
.native_directory_string() + "\" (corrupt?)");
77 // read the necessary data from the PE file header
78 file
.seekg(2, std::ios::cur
);
79 uint16 nosections
= read16(file
);
80 file
.seekg(12, std::ios::cur
);
81 uint16 optionalheadersize
= read16(file
);
82 file
.seekg(2, std::ios::cur
);
84 // skip the optional header
85 file
.seekg(optionalheadersize
, std::ios::cur
);
87 for (unsigned int i
= 0; i
< nosections
; i
++) {
88 char section_name
[9]; section_name
[8] = 0;
89 file
.read(section_name
, 8);
91 file
.seekg(4, std::ios::cur
);
94 section
.vaddr
= read32(file
);
95 section
.size
= read32(file
);
96 section
.offset
= read32(file
);
97 sections
[std::string(section_name
)] = section
;
99 file
.seekg(16, std::ios::cur
);
105 void peFile::parseResources() {
106 std::map
<std::string
, peSection
>::iterator si
= sections
.find(std::string(".rsrc"));
107 if (si
== sections
.end()) return;
108 peSection
&s
= si
->second
;
110 parseResourcesLevel(s
, s
.offset
, 0);
113 unsigned int currtype
, currname
, currlang
;
115 void peFile::parseResourcesLevel(peSection
&s
, unsigned int off
, unsigned int level
) {
116 file
.seekg(off
, std::ios::beg
);
118 file
.seekg(12, std::ios::cur
);
120 uint16 nonamedentries
= read16(file
);
121 uint16 noidentries
= read16(file
);
123 for (unsigned int i
= 0; i
< nonamedentries
+ noidentries
; i
++) {
124 uint32 name
= read32(file
);
125 uint32 offset
= read32(file
);
127 unsigned int here
= file
.tellg();
131 } else if (level
== 1) {
132 /* we don't check for strings here because we don't care :) */
134 } else if (level
== 2) {
139 /* another level, more horror */
141 parseResourcesLevel(s
, s
.offset
+ offset
& 0x7fffffff, level
+ 1);
143 /* bottom level, file data is here */
145 file
.seekg(s
.offset
+ offset
, std::ios::beg
);
147 uint32 offset
= read32(file
);
150 uint32 size
= read32(file
);
152 /*if ((currlang & 0xff) == 0x09) { // LANG_ENGLISH
153 file.seekg(offset, std::ios::beg);
155 char *data = (char*)malloc(size);
156 file.read(data, size);
159 sprintf(buf, "/tmp/oh/%s_%d_%d_%d", nameForType(currtype).c_str(), currname, currlang, offset);
160 std::ofstream f(buf);
167 file
.seekg(here
, std::ios::beg
);