2 * Read a .res file and create a resource-tree
4 * Copyright 1998 Bertho A. Stultiens
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 */
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 *****************************************************************************
42 *****************************************************************************
45 *****************************************************************************
52 *****************************************************************************
55 *****************************************************************************
62 *****************************************************************************
64 int read_data(FILE *fp, size_t size, void *buf)
68 r = fread(buf, 1, size, fp);
71 if(r == 0 && ftell(fp) - pos > 0)
78 *****************************************************************************
85 *****************************************************************************
87 enum res_e res_type_from_id(name_id_t *nid)
89 if(nid->type == name_str)
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;
111 case WRC_RT_TOOLBAR: return res_toolbar;
114 case WRC_RT_DLGINCLUDE:
115 case WRC_RT_PLUGPLAY:
117 case WRC_RT_ANICURSOR:
119 warning("Cannot be sure of resource type, using usertype settings");
125 *****************************************************************************
132 *****************************************************************************
134 #define get_word(idx) (*((WORD *)(&res->data[idx])))
135 #define get_dword(idx) (*((DWORD *)(&res->data[idx])))
137 resource_t *read_res32(FILE *fp)
139 static char wrong_format[] = "Wrong resfile format (32bit)";
148 resource_t *tail = NULL;
149 resource_t *list = NULL;
150 name_id_t *type = NULL;
151 name_id_t *name = NULL;
158 /* Get headersize and resource size */
159 err = read_data(fp, sizeof(ressize), &ressize);
164 err = read_data(fp, sizeof(hdrsize), &hdrsize);
168 /* Align sizes and compute total size */
172 warning("Hu? .res header needed alignment (anything can happen now)");
173 totsize += 4 - (hdrsize & 3);
177 totsize += 4 - (ressize & 3);
179 /* Read in entire data-block */
180 fseek(fp, -8, SEEK_CUR);
182 if(res->allocsize < totsize)
183 grow_res(res, totsize - res->allocsize + 8);
184 err = read_data(fp, totsize, res->data);
188 res->dataidx = hdrsize;
189 res->size = hdrsize + ressize;
191 /* Analyse the content of the header */
194 if(get_word(idx) == 0xffff)
197 type = new_name_id();
198 type->type = name_ord;
199 type->name.i_name = get_word(idx);
202 else if(get_word(idx) == 0)
204 error("ResType name has zero length (32 bit)");
218 str->type = str_unicode;
219 str->size = (idx - tag) / 2;
220 str->str.wstr = (short *)xmalloc(idx-tag+2);
221 memcpy(str->str.wstr, &res->data[tag], idx-tag);
222 str->str.wstr[str->size] = 0;
223 type = new_name_id();
224 type->type = name_str;
225 type->name.s_name = str;
228 if(get_word(idx) == 0xffff)
231 name = new_name_id();
232 name->type = name_ord;
233 name->name.i_name = get_word(idx);
236 else if(get_word(idx) == 0)
238 error("ResName name has zero length (32 bit)");
252 str->type = str_unicode;
253 str->size = (idx - tag) / 2;
254 str->str.wstr = (short *)xmalloc(idx-tag+2);
255 memcpy(str->str.wstr, &res->data[tag], idx-tag);
256 str->str.wstr[str->size] = 0;
257 name = new_name_id();
258 name->type = name_str;
259 name->name.s_name = str;
264 idx += 4 - (idx & 3);
266 idx += sizeof(DWORD); /* Skip DataVersion */
267 memopt = get_word(idx);
269 language = get_word(idx);
271 /* Build a resource_t list */
272 res_type = res_type_from_id(type);
273 if(res_type == res_usr)
275 /* User-type has custom ResType for .[s|h] generation */
276 usrres = new_user(type, NULL, new_int(memopt));
280 rsc = new_resource(res_type,
283 new_language(PRIMARYLANGID(language),
284 SUBLANGID(language)));
287 rsc->c_name = make_c_name(get_c_typename(res_type), name, rsc->lan);
304 *****************************************************************************
311 *****************************************************************************
313 resource_t *read_res16(FILE *fp)
315 internal_error(__FILE__, __LINE__, "Can't yet read 16 bit .res files");
320 *****************************************************************************
321 * Function : read_resfile
322 * Syntax : resource_t *read_resfile(char *inname)
327 *****************************************************************************
329 resource_t *read_resfile(char *inname)
332 struct resheader32 rh;
336 fp = fopen(inname, "rb");
338 error("Could not open inputfile %s", inname);
340 /* Determine 16 or 32 bit .res file */
341 if(fread(&rh, 1, sizeof(rh), fp) != sizeof(rh))
345 if(!memcmp(&emptyheader, &rh, sizeof(rh)))
351 if(is32bit && !win32)
352 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)");
354 if(!is32bit && win32)
355 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources");
359 fseek(fp, 0, SEEK_SET);
360 top = read_res16(fp);
364 top = read_res32(fp);