2 * Read a .res file and create a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
22 DWORD ressize; /* 0 */
23 DWORD hdrsize; /* 0x20 */
24 WORD restype1; /* 0xffff */
25 WORD restype2; /* 0 */
26 WORD resname1; /* 0xffff */
27 WORD resname2; /* 0 */
28 DWORD dversion; /* 0 */
30 WORD language; /* 0 */
31 DWORD version; /* 0 */
32 DWORD characts; /* 0 */
33 } emptyheader = {0, 0x20, 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0},
34 emptyheaderSWAPPED = {0, BYTESWAP_DWORD(0x20), 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0};
37 *****************************************************************************
44 *****************************************************************************
47 *****************************************************************************
54 *****************************************************************************
57 *****************************************************************************
64 *****************************************************************************
66 int read_data(FILE *fp, size_t size, void *buf)
70 r = fread(buf, 1, size, fp);
73 if(r == 0 && ftell(fp) - pos > 0)
80 *****************************************************************************
87 *****************************************************************************
89 enum res_e res_type_from_id(name_id_t *nid)
91 if(nid->type == name_str)
94 if(nid->type != name_ord)
95 internal_error(__FILE__, __LINE__, "Invalid name_id descriptor %d", nid->type);
97 switch(nid->name.i_name)
99 case WRC_RT_CURSOR: return res_cur;
100 case WRC_RT_BITMAP: return res_bmp;
101 case WRC_RT_ICON: return res_ico;
102 case WRC_RT_MENU: return res_men;
103 case WRC_RT_DIALOG: return res_dlg;
104 case WRC_RT_STRING: return res_stt;
105 case WRC_RT_FONTDIR: return res_fntdir;
106 case WRC_RT_FONT: return res_fnt;
107 case WRC_RT_ACCELERATOR: return res_acc;
108 case WRC_RT_RCDATA: return res_rdt;
109 case WRC_RT_MESSAGETABLE: return res_msg;
110 case WRC_RT_GROUP_CURSOR: return res_curg;
111 case WRC_RT_GROUP_ICON: return res_icog;
112 case WRC_RT_VERSION: return res_ver;
113 case WRC_RT_TOOLBAR: return res_toolbar;
116 case WRC_RT_DLGINCLUDE:
117 case WRC_RT_PLUGPLAY:
119 case WRC_RT_ANICURSOR:
121 warning("Cannot be sure of resource type, using usertype settings");
127 *****************************************************************************
134 *****************************************************************************
136 #define get_word(idx) (*((WORD *)(&res->data[idx])))
137 #define get_dword(idx) (*((DWORD *)(&res->data[idx])))
139 static resource_t *read_res32(FILE *fp)
141 static char wrong_format[] = "Wrong resfile format (32bit)";
150 resource_t *tail = NULL;
151 resource_t *list = NULL;
152 name_id_t *type = NULL;
153 name_id_t *name = NULL;
160 /* Get headersize and resource size */
161 err = read_data(fp, sizeof(ressize), &ressize);
166 err = read_data(fp, sizeof(hdrsize), &hdrsize);
170 /* Align sizes and compute total size */
174 warning("Hu? .res header needed alignment (anything can happen now)");
175 totsize += 4 - (hdrsize & 3);
179 totsize += 4 - (ressize & 3);
181 /* Read in entire data-block */
182 fseek(fp, -8, SEEK_CUR);
184 if(res->allocsize < totsize)
185 grow_res(res, totsize - res->allocsize + 8);
186 err = read_data(fp, totsize, res->data);
190 res->dataidx = hdrsize;
191 res->size = hdrsize + ressize;
193 /* Analyse the content of the header */
196 if(get_word(idx) == 0xffff)
199 type = new_name_id();
200 type->type = name_ord;
201 type->name.i_name = get_word(idx);
204 else if(get_word(idx) == 0)
206 error("ResType name has zero length (32 bit)");
220 str->type = str_unicode;
221 str->size = (idx - tag) / 2;
222 str->str.wstr = (short *)xmalloc(idx-tag+2);
223 memcpy(str->str.wstr, &res->data[tag], idx-tag);
224 str->str.wstr[str->size] = 0;
225 type = new_name_id();
226 type->type = name_str;
227 type->name.s_name = str;
230 if(get_word(idx) == 0xffff)
233 name = new_name_id();
234 name->type = name_ord;
235 name->name.i_name = get_word(idx);
238 else if(get_word(idx) == 0)
240 error("ResName name has zero length (32 bit)");
254 str->type = str_unicode;
255 str->size = (idx - tag) / 2;
256 str->str.wstr = (short *)xmalloc(idx-tag+2);
257 memcpy(str->str.wstr, &res->data[tag], idx-tag);
258 str->str.wstr[str->size] = 0;
259 name = new_name_id();
260 name->type = name_str;
261 name->name.s_name = str;
266 idx += 4 - (idx & 3);
268 idx += sizeof(DWORD); /* Skip DataVersion */
269 memopt = get_word(idx);
271 language = get_word(idx);
273 /* Build a resource_t list */
274 res_type = res_type_from_id(type);
275 if(res_type == res_usr)
277 /* User-type has custom ResType for .[s|h] generation */
278 usrres = new_user(type, NULL, new_int(memopt));
282 rsc = new_resource(res_type,
285 new_language(PRIMARYLANGID(language),
286 SUBLANGID(language)));
289 rsc->c_name = make_c_name(get_c_typename(res_type), name, rsc->lan);
306 *****************************************************************************
313 *****************************************************************************
315 static resource_t *read_res16(FILE *fp)
317 internal_error(__FILE__, __LINE__, "Can't yet read 16 bit .res files");
322 *****************************************************************************
323 * Function : read_resfile
324 * Syntax : resource_t *read_resfile(char *inname)
329 *****************************************************************************
331 resource_t *read_resfile(char *inname)
334 struct resheader32 rh;
338 fp = fopen(inname, "rb");
340 error("Could not open inputfile %s", inname);
342 /* Determine 16 or 32 bit .res file */
343 if(fread(&rh, 1, sizeof(rh), fp) != sizeof(rh))
347 if(!memcmp(&emptyheader, &rh, sizeof(rh)))
349 else if(!memcmp(&emptyheaderSWAPPED, &rh, sizeof(rh)))
350 error("Binary .res-file has its byteorder swapped");
355 if(is32bit && !win32)
356 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)");
358 if(!is32bit && win32)
359 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources");
363 fseek(fp, 0, SEEK_SET);
364 top = read_res16(fp);
368 top = read_res32(fp);