Release 980628
[wine/multimedia.git] / tools / wrc / readres.c
blobc2fdc6d71202ac30fed311f3d343f6279e652f78
1 /*
2 * Read a .res file and create a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <assert.h>
13 #include <config.h>
14 #include "wrc.h"
15 #include "readres.h"
16 #include "newstruc.h"
17 #include "utils.h"
18 #include "genres.h"
20 struct resheader32 {
21 DWORD ressize; /* 0 */
22 DWORD hdrsize; /* 0x20 */
23 WORD restype1; /* 0xffff */
24 WORD restype2; /* 0 */
25 WORD resname1; /* 0xffff */
26 WORD resname2; /* 0 */
27 DWORD dversion; /* 0 */
28 WORD memopt; /* 0 */
29 WORD language; /* 0 */
30 DWORD version; /* 0 */
31 DWORD characts; /* 0 */
32 } emptyheader = {0, 0x20, 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0};
35 *****************************************************************************
36 * Function :
37 * Syntax :
38 * Input :
39 * Output :
40 * Description :
41 * Remarks :
42 *****************************************************************************
45 *****************************************************************************
46 * Function :
47 * Syntax :
48 * Input :
49 * Output :
50 * Description :
51 * Remarks :
52 *****************************************************************************
55 *****************************************************************************
56 * Function :
57 * Syntax :
58 * Input :
59 * Output :
60 * Description :
61 * Remarks :
62 *****************************************************************************
64 int read_data(FILE *fp, size_t size, void *buf)
66 int r;
67 int pos = ftell(fp);
68 r = fread(buf, 1, size, fp);
69 if(r == size)
70 return 0;
71 if(r == 0 && ftell(fp) - pos > 0)
72 return 1;
73 else
74 return -1;
78 *****************************************************************************
79 * Function :
80 * Syntax :
81 * Input :
82 * Output :
83 * Description :
84 * Remarks :
85 *****************************************************************************
87 enum res_e res_type_from_id(name_id_t *nid)
89 if(nid->type == name_str)
90 return res_usr;
92 if(nid->type != name_ord)
93 internal_error(__FILE__, __LINE__, "Invalid name_id descriptor %d", nid->type);
95 switch(nid->name.i_name)
97 case WRC_RT_CURSOR: return res_cur;
98 case WRC_RT_BITMAP: return res_bmp;
99 case WRC_RT_ICON: return res_ico;
100 case WRC_RT_MENU: return res_men;
101 case WRC_RT_DIALOG: return res_dlg;
102 case WRC_RT_STRING: return res_stt;
103 case WRC_RT_FONTDIR: return res_fntdir;
104 case WRC_RT_FONT: return res_fnt;
105 case WRC_RT_ACCELERATOR: return res_acc;
106 case WRC_RT_RCDATA: return res_rdt;
107 case WRC_RT_MESSAGETABLE: return res_msg;
108 case WRC_RT_GROUP_CURSOR: return res_curg;
109 case WRC_RT_GROUP_ICON: return res_icog;
110 case WRC_RT_VERSION: return res_ver;
112 default:
113 case WRC_RT_DLGINCLUDE:
114 case WRC_RT_PLUGPLAY:
115 case WRC_RT_VXD:
116 case WRC_RT_ANICURSOR:
117 case WRC_RT_ANIICON:
118 warning("Cannot be sure of resource type, using usertype settings");
119 return res_usr;
124 *****************************************************************************
125 * Function :
126 * Syntax :
127 * Input :
128 * Output :
129 * Description :
130 * Remarks :
131 *****************************************************************************
133 #define get_word(idx) (*((WORD *)(&res->data[idx])))
134 #define get_dword(idx) (*((DWORD *)(&res->data[idx])))
136 resource_t *read_res32(FILE *fp)
138 static char wrong_format[] = "Wrong resfile format (32bit)";
139 DWORD ressize;
140 DWORD hdrsize;
141 DWORD totsize;
142 WORD memopt;
143 WORD language;
144 int err;
145 res_t *res;
146 resource_t *rsc;
147 resource_t *tail = NULL;
148 resource_t *list = NULL;
149 name_id_t *type = NULL;
150 name_id_t *name = NULL;
151 int idx;
152 enum res_e res_type;
153 user_t *usrres;
155 while(1)
157 /* Get headersize and resource size */
158 err = read_data(fp, sizeof(ressize), &ressize);
159 if(err < 0)
160 break;
161 else if(err > 0)
162 error(wrong_format);
163 err = read_data(fp, sizeof(hdrsize), &hdrsize);
164 if(err)
165 error(wrong_format);
167 /* Align sizes and compute total size */
168 totsize = hdrsize;
169 if(hdrsize & 3)
171 warning("Hu? .res header needed alignment (anything can happen now)");
172 totsize += 4 - (hdrsize & 3);
174 totsize += ressize;
175 if(ressize & 3)
176 totsize += 4 - (ressize & 3);
178 /* Read in entire data-block */
179 fseek(fp, -8, SEEK_CUR);
180 res = new_res();
181 if(res->allocsize < totsize)
182 grow_res(res, totsize - res->allocsize + 8);
183 err = read_data(fp, totsize, res->data);
184 if(err)
185 error(wrong_format);
187 res->dataidx = hdrsize;
188 res->size = hdrsize + ressize;
190 /* Analyse the content of the header */
191 idx = 8;
192 /* Get restype */
193 if(get_word(idx) == 0xffff)
195 idx += sizeof(WORD);
196 type = new_name_id();
197 type->type = name_ord;
198 type->name.i_name = get_word(idx);
199 idx += sizeof(WORD);
201 else if(get_word(idx) == 0)
203 error("ResType name has zero length (32 bit)");
205 else
207 int tag = idx;
208 string_t *str;
209 while(1)
211 idx += sizeof(WORD);
212 if(!get_word(idx))
213 break;
215 idx += sizeof(WORD);
216 str = new_string();
217 str->type = str_unicode;
218 str->size = (idx - tag) / 2;
219 str->str.wstr = (short *)xmalloc(idx-tag+2);
220 memcpy(str->str.wstr, &res->data[tag], idx-tag);
221 str->str.wstr[str->size] = 0;
222 type = new_name_id();
223 type->type = name_str;
224 type->name.s_name = str;
226 /* Get resname */
227 if(get_word(idx) == 0xffff)
229 idx += sizeof(WORD);
230 name = new_name_id();
231 name->type = name_ord;
232 name->name.i_name = get_word(idx);
233 idx += sizeof(WORD);
235 else if(get_word(idx) == 0)
237 error("ResName name has zero length (32 bit)");
239 else
241 int tag = idx;
242 string_t *str;
243 while(1)
245 idx += sizeof(WORD);
246 if(!get_word(idx))
247 break;
249 idx += sizeof(WORD);
250 str = new_string();
251 str->type = str_unicode;
252 str->size = (idx - tag) / 2;
253 str->str.wstr = (short *)xmalloc(idx-tag+2);
254 memcpy(str->str.wstr, &res->data[tag], idx-tag);
255 str->str.wstr[str->size] = 0;
256 name = new_name_id();
257 name->type = name_str;
258 name->name.s_name = str;
261 /* align */
262 if(idx & 0x3)
263 idx += 4 - (idx & 3);
265 idx += sizeof(DWORD); /* Skip DataVersion */
266 memopt = get_word(idx);
267 idx += sizeof(WORD);
268 language = get_word(idx);
270 /* Build a resource_t list */
271 res_type = res_type_from_id(type);
272 if(res_type == res_usr)
274 /* User-type has custom ResType for .[s|h] generation */
275 usrres = new_user(type, NULL, new_int(memopt));
277 else
278 usrres = NULL;
279 rsc = new_resource(res_type,
280 usrres,
281 memopt,
282 new_language(PRIMARYLANGID(language),
283 SUBLANGID(language)));
284 rsc->binres = res;
285 rsc->name = name;
286 rsc->c_name = make_c_name(get_c_typename(res_type), name, rsc->lan);
287 if(!list)
289 list = rsc;
290 tail = rsc;
292 else
294 rsc->prev = tail;
295 tail->next = rsc;
296 tail = rsc;
299 return list;
303 *****************************************************************************
304 * Function :
305 * Syntax :
306 * Input :
307 * Output :
308 * Description :
309 * Remarks :
310 *****************************************************************************
312 resource_t *read_res16(FILE *fp)
314 internal_error(__FILE__, __LINE__, "Can't yet read 16 bit .res files");
315 return NULL;
319 *****************************************************************************
320 * Function : read_resfile
321 * Syntax : resource_t *read_resfile(char *inname)
322 * Input :
323 * Output :
324 * Description :
325 * Remarks :
326 *****************************************************************************
328 resource_t *read_resfile(char *inname)
330 FILE *fp;
331 struct resheader32 rh;
332 int is32bit;
333 resource_t *top;
335 fp = fopen(inname, "rb");
336 if(!fp)
337 error("Could not open inputfile %s", inname);
339 /* Determine 16 or 32 bit .res file */
340 if(fread(&rh, 1, sizeof(rh), fp) != sizeof(rh))
341 is32bit = 0;
342 else
344 if(!memcmp(&emptyheader, &rh, sizeof(rh)))
345 is32bit = 1;
346 else
347 is32bit = 0;
350 if(is32bit && !win32)
351 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)");
353 if(!is32bit && win32)
354 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources");
356 if(!is32bit)
358 fseek(fp, 0, SEEK_SET);
359 top = read_res16(fp);
361 else
363 top = read_res32(fp);
366 fclose(fp);
368 return top;