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
;
113 case WRC_RT_DLGINCLUDE
:
114 case WRC_RT_PLUGPLAY
:
116 case WRC_RT_ANICURSOR
:
118 warning("Cannot be sure of resource type, using usertype settings");
124 *****************************************************************************
131 *****************************************************************************
133 #define get_word(idx) (*((WORD *)(&res->data[idx])))
134 #define get_dword(idx) (*((DWORD *)(&res->data[idx])))
136 resource_t
*read_res32(FILE *fp
)
138 static char wrong_format
[] = "Wrong resfile format (32bit)";
147 resource_t
*tail
= NULL
;
148 resource_t
*list
= NULL
;
149 name_id_t
*type
= NULL
;
150 name_id_t
*name
= NULL
;
157 /* Get headersize and resource size */
158 err
= read_data(fp
, sizeof(ressize
), &ressize
);
163 err
= read_data(fp
, sizeof(hdrsize
), &hdrsize
);
167 /* Align sizes and compute total size */
171 warning("Hu? .res header needed alignment (anything can happen now)");
172 totsize
+= 4 - (hdrsize
& 3);
176 totsize
+= 4 - (ressize
& 3);
178 /* Read in entire data-block */
179 fseek(fp
, -8, SEEK_CUR
);
181 if(res
->allocsize
< totsize
)
182 grow_res(res
, totsize
- res
->allocsize
+ 8);
183 err
= read_data(fp
, totsize
, res
->data
);
187 res
->dataidx
= hdrsize
;
188 res
->size
= hdrsize
+ ressize
;
190 /* Analyse the content of the header */
193 if(get_word(idx
) == 0xffff)
196 type
= new_name_id();
197 type
->type
= name_ord
;
198 type
->name
.i_name
= get_word(idx
);
201 else if(get_word(idx
) == 0)
203 error("ResType name has zero length (32 bit)");
217 str
->type
= str_unicode
;
218 str
->size
= (idx
- tag
) / 2;
219 str
->str
.wstr
= (short *)xmalloc(idx
-tag
+2);
220 memcpy(str
->str
.wstr
, &res
->data
[tag
], idx
-tag
);
221 str
->str
.wstr
[str
->size
] = 0;
222 type
= new_name_id();
223 type
->type
= name_str
;
224 type
->name
.s_name
= str
;
227 if(get_word(idx
) == 0xffff)
230 name
= new_name_id();
231 name
->type
= name_ord
;
232 name
->name
.i_name
= get_word(idx
);
235 else if(get_word(idx
) == 0)
237 error("ResName name has zero length (32 bit)");
251 str
->type
= str_unicode
;
252 str
->size
= (idx
- tag
) / 2;
253 str
->str
.wstr
= (short *)xmalloc(idx
-tag
+2);
254 memcpy(str
->str
.wstr
, &res
->data
[tag
], idx
-tag
);
255 str
->str
.wstr
[str
->size
] = 0;
256 name
= new_name_id();
257 name
->type
= name_str
;
258 name
->name
.s_name
= str
;
263 idx
+= 4 - (idx
& 3);
265 idx
+= sizeof(DWORD
); /* Skip DataVersion */
266 memopt
= get_word(idx
);
268 language
= get_word(idx
);
270 /* Build a resource_t list */
271 res_type
= res_type_from_id(type
);
272 if(res_type
== res_usr
)
274 /* User-type has custom ResType for .[s|h] generation */
275 usrres
= new_user(type
, NULL
, new_int(memopt
));
279 rsc
= new_resource(res_type
,
282 new_language(PRIMARYLANGID(language
),
283 SUBLANGID(language
)));
286 rsc
->c_name
= make_c_name(get_c_typename(res_type
), name
, rsc
->lan
);
303 *****************************************************************************
310 *****************************************************************************
312 resource_t
*read_res16(FILE *fp
)
314 internal_error(__FILE__
, __LINE__
, "Can't yet read 16 bit .res files");
319 *****************************************************************************
320 * Function : read_resfile
321 * Syntax : resource_t *read_resfile(char *inname)
326 *****************************************************************************
328 resource_t
*read_resfile(char *inname
)
331 struct resheader32 rh
;
335 fp
= fopen(inname
, "rb");
337 error("Could not open inputfile %s", inname
);
339 /* Determine 16 or 32 bit .res file */
340 if(fread(&rh
, 1, sizeof(rh
), fp
) != sizeof(rh
))
344 if(!memcmp(&emptyheader
, &rh
, sizeof(rh
)))
350 if(is32bit
&& !win32
)
351 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)");
353 if(!is32bit
&& win32
)
354 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources");
358 fseek(fp
, 0, SEEK_SET
);
359 top
= read_res16(fp
);
363 top
= read_res32(fp
);