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
35 DWORD ressize
; /* 0 */
36 DWORD hdrsize
; /* 0x20 */
37 WORD restype1
; /* 0xffff */
38 WORD restype2
; /* 0 */
39 WORD resname1
; /* 0xffff */
40 WORD resname2
; /* 0 */
41 DWORD dversion
; /* 0 */
43 WORD language
; /* 0 */
44 DWORD version
; /* 0 */
45 DWORD characts
; /* 0 */
46 } emptyheader
= {0, 0x20, 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0},
47 emptyheaderSWAPPED
= {0, BYTESWAP_DWORD(0x20), 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0};
50 *****************************************************************************
57 *****************************************************************************
60 *****************************************************************************
67 *****************************************************************************
70 *****************************************************************************
77 *****************************************************************************
79 static int read_data(FILE *fp
, size_t size
, void *buf
)
83 r
= fread(buf
, 1, size
, fp
);
86 if(r
== 0 && ftell(fp
) - pos
> 0)
93 *****************************************************************************
100 *****************************************************************************
102 static enum res_e
res_type_from_id(const name_id_t
*nid
)
104 if(nid
->type
== name_str
)
107 if(nid
->type
!= name_ord
)
108 internal_error(__FILE__
, __LINE__
, "Invalid name_id descriptor %d", nid
->type
);
110 switch(nid
->name
.i_name
)
112 case WRC_RT_CURSOR
: return res_cur
;
113 case WRC_RT_BITMAP
: return res_bmp
;
114 case WRC_RT_ICON
: return res_ico
;
115 case WRC_RT_MENU
: return res_men
;
116 case WRC_RT_DIALOG
: return res_dlg
;
117 case WRC_RT_STRING
: return res_stt
;
118 case WRC_RT_FONTDIR
: return res_fntdir
;
119 case WRC_RT_FONT
: return res_fnt
;
120 case WRC_RT_ACCELERATOR
: return res_acc
;
121 case WRC_RT_RCDATA
: return res_rdt
;
122 case WRC_RT_MESSAGETABLE
: return res_msg
;
123 case WRC_RT_GROUP_CURSOR
: return res_curg
;
124 case WRC_RT_GROUP_ICON
: return res_icog
;
125 case WRC_RT_VERSION
: return res_ver
;
126 case WRC_RT_TOOLBAR
: return res_toolbar
;
129 case WRC_RT_DLGINCLUDE
:
130 case WRC_RT_PLUGPLAY
:
132 case WRC_RT_ANICURSOR
:
134 warning("Cannot be sure of resource type, using usertype settings");
140 *****************************************************************************
147 *****************************************************************************
149 #define get_word(idx) (*((WORD *)(&res->data[idx])))
150 #define get_dword(idx) (*((DWORD *)(&res->data[idx])))
152 static resource_t
*read_res32(FILE *fp
)
154 static const char wrong_format
[] = "Wrong resfile format (32bit)";
163 resource_t
*tail
= NULL
;
164 resource_t
*list
= NULL
;
165 name_id_t
*type
= NULL
;
166 name_id_t
*name
= NULL
;
173 /* Get headersize and resource size */
174 err
= read_data(fp
, sizeof(ressize
), &ressize
);
179 err
= read_data(fp
, sizeof(hdrsize
), &hdrsize
);
183 /* Align sizes and compute total size */
187 warning("Hu? .res header needed alignment (anything can happen now)");
188 totsize
+= 4 - (hdrsize
& 3);
192 totsize
+= 4 - (ressize
& 3);
194 /* Read in entire data-block */
195 fseek(fp
, -8, SEEK_CUR
);
197 if(res
->allocsize
< totsize
)
198 grow_res(res
, totsize
- res
->allocsize
+ 8);
199 err
= read_data(fp
, totsize
, res
->data
);
203 res
->dataidx
= hdrsize
;
204 res
->size
= hdrsize
+ ressize
;
206 /* Analyse the content of the header */
209 if(get_word(idx
) == 0xffff)
212 type
= new_name_id();
213 type
->type
= name_ord
;
214 type
->name
.i_name
= get_word(idx
);
217 else if(get_word(idx
) == 0)
219 error("ResType name has zero length (32 bit)");
233 str
->type
= str_unicode
;
234 str
->size
= (idx
- tag
) / 2;
235 str
->str
.wstr
= xmalloc(idx
-tag
+2);
236 memcpy(str
->str
.wstr
, &res
->data
[tag
], idx
-tag
);
237 str
->str
.wstr
[str
->size
] = 0;
238 type
= new_name_id();
239 type
->type
= name_str
;
240 type
->name
.s_name
= str
;
243 if(get_word(idx
) == 0xffff)
246 name
= new_name_id();
247 name
->type
= name_ord
;
248 name
->name
.i_name
= get_word(idx
);
251 else if(get_word(idx
) == 0)
253 error("ResName name has zero length (32 bit)");
267 str
->type
= str_unicode
;
268 str
->size
= (idx
- tag
) / 2;
269 str
->str
.wstr
= xmalloc(idx
-tag
+2);
270 memcpy(str
->str
.wstr
, &res
->data
[tag
], idx
-tag
);
271 str
->str
.wstr
[str
->size
] = 0;
272 name
= new_name_id();
273 name
->type
= name_str
;
274 name
->name
.s_name
= str
;
279 idx
+= 4 - (idx
& 3);
281 idx
+= sizeof(DWORD
); /* Skip DataVersion */
282 memopt
= get_word(idx
);
284 language
= get_word(idx
);
286 /* Build a resource_t list */
287 res_type
= res_type_from_id(type
);
288 if(res_type
== res_usr
)
290 /* User-type has custom ResType for .[s|h] generation */
291 usrres
= new_user(type
, NULL
, new_int(memopt
));
295 rsc
= new_resource(res_type
,
298 new_language(PRIMARYLANGID(language
),
299 SUBLANGID(language
)));
302 rsc
->c_name
= make_c_name(get_c_typename(res_type
), name
, rsc
->lan
);
319 *****************************************************************************
326 *****************************************************************************
328 static resource_t
*read_res16(FILE *fp
)
330 internal_error(__FILE__
, __LINE__
, "Can't yet read 16 bit .res files");
335 *****************************************************************************
336 * Function : read_resfile
337 * Syntax : resource_t *read_resfile(char *inname)
342 *****************************************************************************
344 resource_t
*read_resfile(char *inname
)
347 struct resheader32 rh
;
351 fp
= fopen(inname
, "rb");
353 error("Could not open inputfile %s", inname
);
355 /* Determine 16 or 32 bit .res file */
356 if(fread(&rh
, 1, sizeof(rh
), fp
) != sizeof(rh
))
360 if(!memcmp(&emptyheader
, &rh
, sizeof(rh
)))
362 else if(!memcmp(&emptyheaderSWAPPED
, &rh
, sizeof(rh
)))
363 error("Binary .res-file has its byteorder swapped");
368 if(is32bit
&& !win32
)
369 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)");
371 if(!is32bit
&& win32
)
372 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources");
376 fseek(fp
, 0, SEEK_SET
);
377 top
= read_res16(fp
);
381 top
= read_res32(fp
);