msvcrt: Don't duplicate _setmbcp functionality inside _create_locale function.
[wine.git] / tools / wrc / readres.c
blob9e964a6b9c634889ca5e3b249b0f81e8aa49ed57
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 static const 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 static 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 static 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\n", 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\n");
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 const 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)\n");
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)\n");
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 = 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)\n");
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 = 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
296 free (type);
297 usrres = NULL;
299 rsc = new_resource(res_type,
300 usrres,
301 memopt,
302 new_language(PRIMARYLANGID(language),
303 SUBLANGID(language)));
304 rsc->binres = res;
305 rsc->name = name;
306 rsc->c_name = make_c_name(get_c_typename(res_type), name, rsc->lan);
307 if(!list)
309 list = rsc;
310 tail = rsc;
312 else
314 rsc->prev = tail;
315 tail->next = rsc;
316 tail = rsc;
319 return list;
323 *****************************************************************************
324 * Function :
325 * Syntax :
326 * Input :
327 * Output :
328 * Description :
329 * Remarks :
330 *****************************************************************************
332 static resource_t *read_res16(FILE *fp)
334 internal_error(__FILE__, __LINE__, "Can't yet read 16 bit .res files\n");
335 return NULL;
339 *****************************************************************************
340 * Function : read_resfile
341 * Syntax : resource_t *read_resfile(char *inname)
342 * Input :
343 * Output :
344 * Description :
345 * Remarks :
346 *****************************************************************************
348 resource_t *read_resfile(char *inname)
350 FILE *fp;
351 struct resheader32 rh;
352 int is32bit = 1;
353 resource_t *top;
355 fp = fopen(inname, "rb");
356 if(!fp)
357 fatal_perror("Could not open %s", inname);
359 /* Determine 16 or 32 bit .res file */
360 if(fread(&rh, 1, sizeof(rh), fp) != sizeof(rh))
361 is32bit = 0;
362 else
364 if(!memcmp(&emptyheader, &rh, sizeof(rh)))
365 is32bit = 1;
366 else if(!memcmp(&emptyheaderSWAPPED, &rh, sizeof(rh)))
367 error("Binary .res-file has its byteorder swapped\n");
368 else
369 is32bit = 0;
372 if(is32bit && !win32)
373 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)\n");
375 if(!is32bit && win32)
376 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources\n");
378 if(!is32bit)
380 fseek(fp, 0, SEEK_SET);
381 top = read_res16(fp);
383 else
385 top = read_res32(fp);
388 fclose(fp);
390 return top;