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
);