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
22 #include "wine/port.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 */
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 *****************************************************************************
58 *****************************************************************************
61 *****************************************************************************
68 *****************************************************************************
71 *****************************************************************************
78 *****************************************************************************
80 static int read_data(FILE *fp, size_t size, void *buf)
84 r = fread(buf, 1, size, fp);
87 if(r == 0 && ftell(fp) - pos > 0)
94 *****************************************************************************
101 *****************************************************************************
103 static enum res_e res_type_from_id(const name_id_t *nid)
105 if(nid->type == name_str)
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;
130 case WRC_RT_DLGINCLUDE:
131 case WRC_RT_PLUGPLAY:
133 case WRC_RT_ANICURSOR:
135 warning("Cannot be sure of resource type, using usertype settings");
141 *****************************************************************************
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)";
164 resource_t *tail = NULL;
165 resource_t *list = NULL;
166 name_id_t *type = NULL;
167 name_id_t *name = NULL;
174 /* Get headersize and resource size */
175 err = read_data(fp, sizeof(ressize), &ressize);
180 err = read_data(fp, sizeof(hdrsize), &hdrsize);
184 /* Align sizes and compute total size */
188 warning("Hu? .res header needed alignment (anything can happen now)");
189 totsize += 4 - (hdrsize & 3);
193 totsize += 4 - (ressize & 3);
195 /* Read in entire data-block */
196 fseek(fp, -8, SEEK_CUR);
198 if(res->allocsize < totsize)
199 grow_res(res, totsize - res->allocsize + 8);
200 err = read_data(fp, totsize, res->data);
204 res->dataidx = hdrsize;
205 res->size = hdrsize + ressize;
207 /* Analyse the content of the header */
210 if(get_word(idx) == 0xffff)
213 type = new_name_id();
214 type->type = name_ord;
215 type->name.i_name = get_word(idx);
218 else if(get_word(idx) == 0)
220 error("ResType name has zero length (32 bit)");
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;
244 if(get_word(idx) == 0xffff)
247 name = new_name_id();
248 name->type = name_ord;
249 name->name.i_name = get_word(idx);
252 else if(get_word(idx) == 0)
254 error("ResName name has zero length (32 bit)");
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;
280 idx += 4 - (idx & 3);
282 idx += sizeof(DWORD); /* Skip DataVersion */
283 memopt = get_word(idx);
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));
296 rsc = new_resource(res_type,
299 new_language(PRIMARYLANGID(language),
300 SUBLANGID(language)));
303 rsc->c_name = make_c_name(get_c_typename(res_type), name, rsc->lan);
320 *****************************************************************************
327 *****************************************************************************
329 static resource_t *read_res16(FILE *fp)
331 internal_error(__FILE__, __LINE__, "Can't yet read 16 bit .res files");
336 *****************************************************************************
337 * Function : read_resfile
338 * Syntax : resource_t *read_resfile(char *inname)
343 *****************************************************************************
345 resource_t *read_resfile(char *inname)
348 struct resheader32 rh;
352 fp = fopen(inname, "rb");
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))
361 if(!memcmp(&emptyheader, &rh, sizeof(rh)))
363 else if(!memcmp(&emptyheaderSWAPPED, &rh, sizeof(rh)))
364 error("Binary .res-file has its byteorder swapped");
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");
377 fseek(fp, 0, SEEK_SET);
378 top = read_res16(fp);
382 top = read_res32(fp);