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};
36 *****************************************************************************
43 *****************************************************************************
46 *****************************************************************************
53 *****************************************************************************
56 *****************************************************************************
63 *****************************************************************************
65 int read_data(FILE *fp
, size_t size
, void *buf
)
69 r
= fread(buf
, 1, size
, fp
);
72 if(r
== 0 && ftell(fp
) - pos
> 0)
79 *****************************************************************************
86 *****************************************************************************
88 enum res_e
res_type_from_id(name_id_t
*nid
)
90 if(nid
->type
== name_str
)
93 if(nid
->type
!= name_ord
)
94 internal_error(__FILE__
, __LINE__
, "Invalid name_id descriptor %d", nid
->type
);
96 switch(nid
->name
.i_name
)
98 case WRC_RT_CURSOR
: return res_cur
;
99 case WRC_RT_BITMAP
: return res_bmp
;
100 case WRC_RT_ICON
: return res_ico
;
101 case WRC_RT_MENU
: return res_men
;
102 case WRC_RT_DIALOG
: return res_dlg
;
103 case WRC_RT_STRING
: return res_stt
;
104 case WRC_RT_FONTDIR
: return res_fntdir
;
105 case WRC_RT_FONT
: return res_fnt
;
106 case WRC_RT_ACCELERATOR
: return res_acc
;
107 case WRC_RT_RCDATA
: return res_rdt
;
108 case WRC_RT_MESSAGETABLE
: return res_msg
;
109 case WRC_RT_GROUP_CURSOR
: return res_curg
;
110 case WRC_RT_GROUP_ICON
: return res_icog
;
111 case WRC_RT_VERSION
: return res_ver
;
112 case WRC_RT_TOOLBAR
: return res_toolbar
;
115 case WRC_RT_DLGINCLUDE
:
116 case WRC_RT_PLUGPLAY
:
118 case WRC_RT_ANICURSOR
:
120 warning("Cannot be sure of resource type, using usertype settings");
126 *****************************************************************************
133 *****************************************************************************
135 #define get_word(idx) (*((WORD *)(&res->data[idx])))
136 #define get_dword(idx) (*((DWORD *)(&res->data[idx])))
138 resource_t
*read_res32(FILE *fp
)
140 static char wrong_format
[] = "Wrong resfile format (32bit)";
149 resource_t
*tail
= NULL
;
150 resource_t
*list
= NULL
;
151 name_id_t
*type
= NULL
;
152 name_id_t
*name
= NULL
;
159 /* Get headersize and resource size */
160 err
= read_data(fp
, sizeof(ressize
), &ressize
);
165 err
= read_data(fp
, sizeof(hdrsize
), &hdrsize
);
169 /* Align sizes and compute total size */
173 warning("Hu? .res header needed alignment (anything can happen now)");
174 totsize
+= 4 - (hdrsize
& 3);
178 totsize
+= 4 - (ressize
& 3);
180 /* Read in entire data-block */
181 fseek(fp
, -8, SEEK_CUR
);
183 if(res
->allocsize
< totsize
)
184 grow_res(res
, totsize
- res
->allocsize
+ 8);
185 err
= read_data(fp
, totsize
, res
->data
);
189 res
->dataidx
= hdrsize
;
190 res
->size
= hdrsize
+ ressize
;
192 /* Analyse the content of the header */
195 if(get_word(idx
) == 0xffff)
198 type
= new_name_id();
199 type
->type
= name_ord
;
200 type
->name
.i_name
= get_word(idx
);
203 else if(get_word(idx
) == 0)
205 error("ResType name has zero length (32 bit)");
219 str
->type
= str_unicode
;
220 str
->size
= (idx
- tag
) / 2;
221 str
->str
.wstr
= (short *)xmalloc(idx
-tag
+2);
222 memcpy(str
->str
.wstr
, &res
->data
[tag
], idx
-tag
);
223 str
->str
.wstr
[str
->size
] = 0;
224 type
= new_name_id();
225 type
->type
= name_str
;
226 type
->name
.s_name
= str
;
229 if(get_word(idx
) == 0xffff)
232 name
= new_name_id();
233 name
->type
= name_ord
;
234 name
->name
.i_name
= get_word(idx
);
237 else if(get_word(idx
) == 0)
239 error("ResName name has zero length (32 bit)");
253 str
->type
= str_unicode
;
254 str
->size
= (idx
- tag
) / 2;
255 str
->str
.wstr
= (short *)xmalloc(idx
-tag
+2);
256 memcpy(str
->str
.wstr
, &res
->data
[tag
], idx
-tag
);
257 str
->str
.wstr
[str
->size
] = 0;
258 name
= new_name_id();
259 name
->type
= name_str
;
260 name
->name
.s_name
= str
;
265 idx
+= 4 - (idx
& 3);
267 idx
+= sizeof(DWORD
); /* Skip DataVersion */
268 memopt
= get_word(idx
);
270 language
= get_word(idx
);
272 /* Build a resource_t list */
273 res_type
= res_type_from_id(type
);
274 if(res_type
== res_usr
)
276 /* User-type has custom ResType for .[s|h] generation */
277 usrres
= new_user(type
, NULL
, new_int(memopt
));
281 rsc
= new_resource(res_type
,
284 new_language(PRIMARYLANGID(language
),
285 SUBLANGID(language
)));
288 rsc
->c_name
= make_c_name(get_c_typename(res_type
), name
, rsc
->lan
);
305 *****************************************************************************
312 *****************************************************************************
314 resource_t
*read_res16(FILE *fp
)
316 internal_error(__FILE__
, __LINE__
, "Can't yet read 16 bit .res files");
321 *****************************************************************************
322 * Function : read_resfile
323 * Syntax : resource_t *read_resfile(char *inname)
328 *****************************************************************************
330 resource_t
*read_resfile(char *inname
)
333 struct resheader32 rh
;
337 fp
= fopen(inname
, "rb");
339 error("Could not open inputfile %s", inname
);
341 /* Determine 16 or 32 bit .res file */
342 if(fread(&rh
, 1, sizeof(rh
), fp
) != sizeof(rh
))
346 if(!memcmp(&emptyheader
, &rh
, sizeof(rh
)))
352 if(is32bit
&& !win32
)
353 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)");
355 if(!is32bit
&& win32
)
356 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources");
360 fseek(fp
, 0, SEEK_SET
);
361 top
= read_res16(fp
);
365 top
= read_res32(fp
);