Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / sdk / tools / geninc / geninc.c
1 /*
2 * Generates assembly definitions from the target headers.
3 */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdint.h>
9
10 #define IMAGE_FILE_MACHINE_I386 0x014c
11 #define IMAGE_FILE_MACHINE_AMD64 0x8664
12 #define IMAGE_FILE_MACHINE_ARMNT 0x01c4
13
14 #ifdef _MSC_VER
15 #define PRIx64 "I64x"
16 #else
17 #include <inttypes.h>
18 #define _stricmp strcasecmp
19 #endif
20
21 typedef struct
22 {
23 char Type;
24 char Name[55];
25 uint64_t Value;
26 } ASMGENDATA;
27
28 #define TYPE_END 0
29 #define TYPE_RAW 1
30 #define TYPE_CONSTANT 2
31 #define TYPE_HEADER 3
32
33 int main(int argc, char* argv[])
34 {
35 FILE *input, *output;
36 ASMGENDATA data;
37 int i, result = -1;
38 int ms_format = 0;
39 char header[20];
40 uint32_t e_lfanew, signature;
41 uint16_t Machine, NumberOfSections, SizeOfOptionalHeader;
42 typedef struct
43 {
44 char Name[8];
45 uint32_t VirtualSize;
46 uint32_t VirtualAddress;
47 uint32_t RawSize;
48 uint32_t RawAddress;
49 uint32_t RelocAddress;
50 uint32_t LineNumbers;
51 uint16_t RelocationsNumber;
52 uint16_t LineNumbersNumber;
53 uint32_t Characteristics;
54 } SECTION;
55 SECTION section;
56
57 if (argc >= 4 && _stricmp(argv[3], "-ms") == 0) ms_format = 1;
58
59 /* Open the input file */
60 input = fopen(argv[1], "rb");
61 if (!input)
62 {
63 fprintf(stderr, "Could not open input file '%s'\n", argv[1]);
64 return -1;
65 }
66
67 /* Open the output file */
68 output = fopen(argv[2], "w");
69 if (!output)
70 {
71 fclose(input);
72 fprintf(stderr, "Could not open output file '%s'\n", argv[2]);
73 return -1;
74 }
75
76 /* Read the DOS header */
77 if (fread(&header, 1, 2, input) != 2)
78 {
79 fprintf(stderr, "Error reading header.\n");
80 goto quit;
81 }
82
83 if (header[0] != 0x4d || header[1] != 0x5a)
84 {
85 fprintf(stderr, "Not a PE file.\n");
86 goto quit;
87 }
88
89 fseek(input, 0x3C, SEEK_SET);
90 if (fread(&e_lfanew, 1, 4, input) != 4)
91 {
92 fprintf(stderr, "Could not read e_lfanew.\n");
93 goto quit;
94 }
95
96 fseek(input, e_lfanew, SEEK_SET);
97 if (fread(&signature, 1, 4, input) != 4)
98 {
99 fprintf(stderr, "Could not read signature.\n");
100 goto quit;
101 }
102
103 /* Verify the PE signature */
104 if (signature != 0x4550)
105 {
106 fprintf(stderr, "Invalid signature: 0x%x.\n", signature);
107 goto quit;
108 }
109
110 /* Read Machine */
111 fseek(input, e_lfanew + 4, SEEK_SET);
112 if (fread(&Machine, 1, 2, input) != 2)
113 {
114 fprintf(stderr, "Could not read ExportDirectoryRVA.\n");
115 goto quit;
116 }
117
118 if ((Machine != IMAGE_FILE_MACHINE_I386) &&
119 (Machine != IMAGE_FILE_MACHINE_AMD64) &&
120 (Machine != IMAGE_FILE_MACHINE_ARMNT))
121 {
122 fprintf(stderr, "Invalid Machine: 0x%x.\n", Machine);
123 goto quit;
124 }
125
126 /* Read NumberOfSections */
127 if (fread(&NumberOfSections, 1, 2, input) != 2)
128 {
129 fprintf(stderr, "Could not read NumberOfSections.\n");
130 goto quit;
131 }
132
133 fseek(input, e_lfanew + 0x14, SEEK_SET);
134 if (fread(&SizeOfOptionalHeader, 1, 2, input) != 2)
135 {
136 fprintf(stderr, "Could not read SizeOfOptionalHeader.\n");
137 goto quit;
138 }
139
140 /* Read the section table */
141 fseek(input, e_lfanew + 0x18 + SizeOfOptionalHeader, SEEK_SET);
142
143 /* Search for the .asmdef section */
144 for (i = 0; i < NumberOfSections; i++)
145 {
146 if (fread(&section, 1, sizeof(SECTION), input) != sizeof(SECTION))
147 {
148 fprintf(stderr, "Could not read section.\n");
149 goto quit;
150 }
151
152 if (strcmp(section.Name, ".asmdef") == 0)
153 {
154 break;
155 }
156 }
157
158 if (i == NumberOfSections)
159 {
160 fprintf(stderr, "Could not find section.\n");
161 goto quit;
162 }
163
164 /* Read the section table */
165 fseek(input, section.RawAddress, SEEK_SET);
166
167 while (1)
168 {
169 /* Read one entry */
170 if (fread(&data, 1, sizeof(data), input) != sizeof(data))
171 {
172 fprintf(stderr, "Error reading input file.\n");
173 goto quit;
174 }
175
176 switch(data.Type)
177 {
178 case TYPE_END:
179 break;
180
181 case TYPE_RAW:
182 fprintf(output, "%s\n", data.Name);
183 continue;
184
185 case TYPE_CONSTANT:
186 if (ms_format)
187 {
188 if (Machine == IMAGE_FILE_MACHINE_ARMNT)
189 {
190 fprintf(output, "%s equ 0x%"PRIx64"\n", data.Name, data.Value);
191 }
192 else
193 {
194 fprintf(output, "%s equ 0%"PRIx64"h\n", data.Name, data.Value);
195 }
196 }
197 else
198 {
199 fprintf(output, "%s = 0x%"PRIx64"\n", data.Name, data.Value);
200 }
201 continue;
202
203 case TYPE_HEADER:
204 if (ms_format)
205 {
206 fprintf(output, "\n; %s\n", data.Name);
207 }
208 else
209 {
210 fprintf(output, "\n/* %s */\n", data.Name);
211 }
212 continue;
213 }
214
215 break;
216 }
217
218 result = 0;
219
220 quit:
221 /* Close files */
222 fclose(input);
223 fclose(output);
224
225 return result;
226 }