Rewrote the collapsing of . and .. in RtlGetFullPathName_U for better
[wine/multimedia.git] / tools / wrc / readres.c
blobd2904113e87477128de6d35082033c59d11622ac
1 /*
2 * Read a .res file and create a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
29 #include "wrc.h"
30 #include "readres.h"
31 #include "newstruc.h"
32 #include "utils.h"
33 #include "genres.h"
35 struct resheader32 {
36 DWORD ressize; /* 0 */
37 DWORD hdrsize; /* 0x20 */
38 WORD restype1; /* 0xffff */
39 WORD restype2; /* 0 */
40 WORD resname1; /* 0xffff */
41 WORD resname2; /* 0 */
42 DWORD dversion; /* 0 */
43 WORD memopt; /* 0 */
44 WORD language; /* 0 */
45 DWORD version; /* 0 */
46 DWORD characts; /* 0 */
47 } emptyheader = {0, 0x20, 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0},
48 emptyheaderSWAPPED = {0, BYTESWAP_DWORD(0x20), 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0};
51 *****************************************************************************
52 * Function :
53 * Syntax :
54 * Input :
55 * Output :
56 * Description :
57 * Remarks :
58 *****************************************************************************
61 *****************************************************************************
62 * Function :
63 * Syntax :
64 * Input :
65 * Output :
66 * Description :
67 * Remarks :
68 *****************************************************************************
71 *****************************************************************************
72 * Function :
73 * Syntax :
74 * Input :
75 * Output :
76 * Description :
77 * Remarks :
78 *****************************************************************************
80 int read_data(FILE *fp, size_t size, void *buf)
82 unsigned int r;
83 int pos = ftell(fp);
84 r = fread(buf, 1, size, fp);
85 if(r == size)
86 return 0;
87 if(r == 0 && ftell(fp) - pos > 0)
88 return 1;
89 else
90 return -1;
94 *****************************************************************************
95 * Function :
96 * Syntax :
97 * Input :
98 * Output :
99 * Description :
100 * Remarks :
101 *****************************************************************************
103 enum res_e res_type_from_id(const name_id_t *nid)
105 if(nid->type == name_str)
106 return res_usr;
108 if(nid->type != name_ord)
109 internal_error(__FILE__, __LINE__, "Invalid name_id descriptor %d", nid->type);
111 switch(nid->name.i_name)
113 case WRC_RT_CURSOR: return res_cur;
114 case WRC_RT_BITMAP: return res_bmp;
115 case WRC_RT_ICON: return res_ico;
116 case WRC_RT_MENU: return res_men;
117 case WRC_RT_DIALOG: return res_dlg;
118 case WRC_RT_STRING: return res_stt;
119 case WRC_RT_FONTDIR: return res_fntdir;
120 case WRC_RT_FONT: return res_fnt;
121 case WRC_RT_ACCELERATOR: return res_acc;
122 case WRC_RT_RCDATA: return res_rdt;
123 case WRC_RT_MESSAGETABLE: return res_msg;
124 case WRC_RT_GROUP_CURSOR: return res_curg;
125 case WRC_RT_GROUP_ICON: return res_icog;
126 case WRC_RT_VERSION: return res_ver;
127 case WRC_RT_TOOLBAR: return res_toolbar;
129 default:
130 case WRC_RT_DLGINCLUDE:
131 case WRC_RT_PLUGPLAY:
132 case WRC_RT_VXD:
133 case WRC_RT_ANICURSOR:
134 case WRC_RT_ANIICON:
135 warning("Cannot be sure of resource type, using usertype settings");
136 return res_usr;
141 *****************************************************************************
142 * Function :
143 * Syntax :
144 * Input :
145 * Output :
146 * Description :
147 * Remarks :
148 *****************************************************************************
150 #define get_word(idx) (*((WORD *)(&res->data[idx])))
151 #define get_dword(idx) (*((DWORD *)(&res->data[idx])))
153 static resource_t *read_res32(FILE *fp)
155 static char wrong_format[] = "Wrong resfile format (32bit)";
156 DWORD ressize;
157 DWORD hdrsize;
158 DWORD totsize;
159 WORD memopt;
160 WORD language;
161 int err;
162 res_t *res;
163 resource_t *rsc;
164 resource_t *tail = NULL;
165 resource_t *list = NULL;
166 name_id_t *type = NULL;
167 name_id_t *name = NULL;
168 int idx;
169 enum res_e res_type;
170 user_t *usrres;
172 while(1)
174 /* Get headersize and resource size */
175 err = read_data(fp, sizeof(ressize), &ressize);
176 if(err < 0)
177 break;
178 else if(err > 0)
179 error(wrong_format);
180 err = read_data(fp, sizeof(hdrsize), &hdrsize);
181 if(err)
182 error(wrong_format);
184 /* Align sizes and compute total size */
185 totsize = hdrsize;
186 if(hdrsize & 3)
188 warning("Hu? .res header needed alignment (anything can happen now)");
189 totsize += 4 - (hdrsize & 3);
191 totsize += ressize;
192 if(ressize & 3)
193 totsize += 4 - (ressize & 3);
195 /* Read in entire data-block */
196 fseek(fp, -8, SEEK_CUR);
197 res = new_res();
198 if(res->allocsize < totsize)
199 grow_res(res, totsize - res->allocsize + 8);
200 err = read_data(fp, totsize, res->data);
201 if(err)
202 error(wrong_format);
204 res->dataidx = hdrsize;
205 res->size = hdrsize + ressize;
207 /* Analyse the content of the header */
208 idx = 8;
209 /* Get restype */
210 if(get_word(idx) == 0xffff)
212 idx += sizeof(WORD);
213 type = new_name_id();
214 type->type = name_ord;
215 type->name.i_name = get_word(idx);
216 idx += sizeof(WORD);
218 else if(get_word(idx) == 0)
220 error("ResType name has zero length (32 bit)");
222 else
224 int tag = idx;
225 string_t *str;
226 while(1)
228 idx += sizeof(WORD);
229 if(!get_word(idx))
230 break;
232 idx += sizeof(WORD);
233 str = new_string();
234 str->type = str_unicode;
235 str->size = (idx - tag) / 2;
236 str->str.wstr = (short *)xmalloc(idx-tag+2);
237 memcpy(str->str.wstr, &res->data[tag], idx-tag);
238 str->str.wstr[str->size] = 0;
239 type = new_name_id();
240 type->type = name_str;
241 type->name.s_name = str;
243 /* Get resname */
244 if(get_word(idx) == 0xffff)
246 idx += sizeof(WORD);
247 name = new_name_id();
248 name->type = name_ord;
249 name->name.i_name = get_word(idx);
250 idx += sizeof(WORD);
252 else if(get_word(idx) == 0)
254 error("ResName name has zero length (32 bit)");
256 else
258 int tag = idx;
259 string_t *str;
260 while(1)
262 idx += sizeof(WORD);
263 if(!get_word(idx))
264 break;
266 idx += sizeof(WORD);
267 str = new_string();
268 str->type = str_unicode;
269 str->size = (idx - tag) / 2;
270 str->str.wstr = (short *)xmalloc(idx-tag+2);
271 memcpy(str->str.wstr, &res->data[tag], idx-tag);
272 str->str.wstr[str->size] = 0;
273 name = new_name_id();
274 name->type = name_str;
275 name->name.s_name = str;
278 /* align */
279 if(idx & 0x3)
280 idx += 4 - (idx & 3);
282 idx += sizeof(DWORD); /* Skip DataVersion */
283 memopt = get_word(idx);
284 idx += sizeof(WORD);
285 language = get_word(idx);
287 /* Build a resource_t list */
288 res_type = res_type_from_id(type);
289 if(res_type == res_usr)
291 /* User-type has custom ResType for .[s|h] generation */
292 usrres = new_user(type, NULL, new_int(memopt));
294 else
295 usrres = NULL;
296 rsc = new_resource(res_type,
297 usrres,
298 memopt,
299 new_language(PRIMARYLANGID(language),
300 SUBLANGID(language)));
301 rsc->binres = res;
302 rsc->name = name;
303 rsc->c_name = make_c_name(get_c_typename(res_type), name, rsc->lan);
304 if(!list)
306 list = rsc;
307 tail = rsc;
309 else
311 rsc->prev = tail;
312 tail->next = rsc;
313 tail = rsc;
316 return list;
320 *****************************************************************************
321 * Function :
322 * Syntax :
323 * Input :
324 * Output :
325 * Description :
326 * Remarks :
327 *****************************************************************************
329 static resource_t *read_res16(FILE *fp)
331 internal_error(__FILE__, __LINE__, "Can't yet read 16 bit .res files");
332 return NULL;
336 *****************************************************************************
337 * Function : read_resfile
338 * Syntax : resource_t *read_resfile(char *inname)
339 * Input :
340 * Output :
341 * Description :
342 * Remarks :
343 *****************************************************************************
345 resource_t *read_resfile(char *inname)
347 FILE *fp;
348 struct resheader32 rh;
349 int is32bit = 1;
350 resource_t *top;
352 fp = fopen(inname, "rb");
353 if(!fp)
354 error("Could not open inputfile %s", inname);
356 /* Determine 16 or 32 bit .res file */
357 if(fread(&rh, 1, sizeof(rh), fp) != sizeof(rh))
358 is32bit = 0;
359 else
361 if(!memcmp(&emptyheader, &rh, sizeof(rh)))
362 is32bit = 1;
363 else if(!memcmp(&emptyheaderSWAPPED, &rh, sizeof(rh)))
364 error("Binary .res-file has its byteorder swapped");
365 else
366 is32bit = 0;
369 if(is32bit && !win32)
370 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)");
372 if(!is32bit && win32)
373 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources");
375 if(!is32bit)
377 fseek(fp, 0, SEEK_SET);
378 top = read_res16(fp);
380 else
382 top = read_res32(fp);
385 fclose(fp);
387 return top;