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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
35 static const struct resheader32
{
36 DWORD ressize
; /* 0 */
37 DWORD hdrsize
; /* 0x20 */
38 WORD restype1
; /* 0xffff */
39 WORD restype2
; /* 0 */
40 WORD resname1
; /* 0xffff */
41 WORD resname2
; /* 0 */
42 DWORD dversion
; /* 0 */
44 WORD language
; /* 0 */
45 DWORD version
; /* 0 */
46 DWORD characts
; /* 0 */
47 } emptyheader
= {0, 0x20, 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0},
48 emptyheaderSWAPPED
= {0, BYTESWAP_DWORD(0x20), 0xffff, 0, 0xffff, 0, 0, 0, 0, 0, 0};
51 *****************************************************************************
58 *****************************************************************************
61 *****************************************************************************
68 *****************************************************************************
71 *****************************************************************************
78 *****************************************************************************
80 static int read_data(FILE *fp
, size_t size
, void *buf
)
84 r
= fread(buf
, 1, size
, fp
);
87 if(r
== 0 && ftell(fp
) - pos
> 0)
94 *****************************************************************************
101 *****************************************************************************
103 static enum res_e
res_type_from_id(const name_id_t
*nid
)
105 if(nid
->type
== name_str
)
108 if(nid
->type
!= name_ord
)
109 internal_error(__FILE__
, __LINE__
, "Invalid name_id descriptor %d\n", nid
->type
);
111 switch(nid
->name
.i_name
)
113 case WRC_RT_CURSOR
: return res_cur
;
114 case WRC_RT_BITMAP
: return res_bmp
;
115 case WRC_RT_ICON
: return res_ico
;
116 case WRC_RT_MENU
: return res_men
;
117 case WRC_RT_DIALOG
: return res_dlg
;
118 case WRC_RT_STRING
: return res_stt
;
119 case WRC_RT_FONTDIR
: return res_fntdir
;
120 case WRC_RT_FONT
: return res_fnt
;
121 case WRC_RT_ACCELERATOR
: return res_acc
;
122 case WRC_RT_RCDATA
: return res_rdt
;
123 case WRC_RT_MESSAGETABLE
: return res_msg
;
124 case WRC_RT_GROUP_CURSOR
: return res_curg
;
125 case WRC_RT_GROUP_ICON
: return res_icog
;
126 case WRC_RT_VERSION
: return res_ver
;
127 case WRC_RT_TOOLBAR
: return res_toolbar
;
130 case WRC_RT_DLGINCLUDE
:
131 case WRC_RT_PLUGPLAY
:
133 case WRC_RT_ANICURSOR
:
135 warning("Cannot be sure of resource type, using usertype settings\n");
141 *****************************************************************************
148 *****************************************************************************
150 #define get_word(idx) (*((WORD *)(&res->data[idx])))
151 #define get_dword(idx) (*((DWORD *)(&res->data[idx])))
153 static resource_t
*read_res32(FILE *fp
)
155 static const char wrong_format
[] = "Wrong resfile format (32bit)";
164 resource_t
*tail
= NULL
;
165 resource_t
*list
= NULL
;
166 name_id_t
*type
= NULL
;
167 name_id_t
*name
= NULL
;
174 /* Get headersize and resource size */
175 err
= read_data(fp
, sizeof(ressize
), &ressize
);
180 err
= read_data(fp
, sizeof(hdrsize
), &hdrsize
);
184 /* Align sizes and compute total size */
188 warning("Hu? .res header needed alignment (anything can happen now)\n");
189 totsize
+= 4 - (hdrsize
& 3);
193 totsize
+= 4 - (ressize
& 3);
195 /* Read in entire data-block */
196 fseek(fp
, -8, SEEK_CUR
);
198 if(res
->allocsize
< totsize
)
199 grow_res(res
, totsize
- res
->allocsize
+ 8);
200 err
= read_data(fp
, totsize
, res
->data
);
204 res
->dataidx
= hdrsize
;
205 res
->size
= hdrsize
+ ressize
;
207 /* Analyse the content of the header */
210 if(get_word(idx
) == 0xffff)
213 type
= new_name_id();
214 type
->type
= name_ord
;
215 type
->name
.i_name
= get_word(idx
);
218 else if(get_word(idx
) == 0)
220 error("ResType name has zero length (32 bit)\n");
234 str
->type
= str_unicode
;
235 str
->size
= (idx
- tag
) / 2;
236 str
->str
.wstr
= xmalloc(idx
-tag
+2);
237 memcpy(str
->str
.wstr
, &res
->data
[tag
], idx
-tag
);
238 str
->str
.wstr
[str
->size
] = 0;
239 type
= new_name_id();
240 type
->type
= name_str
;
241 type
->name
.s_name
= str
;
244 if(get_word(idx
) == 0xffff)
247 name
= new_name_id();
248 name
->type
= name_ord
;
249 name
->name
.i_name
= get_word(idx
);
252 else if(get_word(idx
) == 0)
254 error("ResName name has zero length (32 bit)\n");
268 str
->type
= str_unicode
;
269 str
->size
= (idx
- tag
) / 2;
270 str
->str
.wstr
= xmalloc(idx
-tag
+2);
271 memcpy(str
->str
.wstr
, &res
->data
[tag
], idx
-tag
);
272 str
->str
.wstr
[str
->size
] = 0;
273 name
= new_name_id();
274 name
->type
= name_str
;
275 name
->name
.s_name
= str
;
280 idx
+= 4 - (idx
& 3);
282 idx
+= sizeof(DWORD
); /* Skip DataVersion */
283 memopt
= get_word(idx
);
285 language
= get_word(idx
);
287 /* Build a resource_t list */
288 res_type
= res_type_from_id(type
);
289 if(res_type
== res_usr
)
291 /* User-type has custom ResType for .[s|h] generation */
292 usrres
= new_user(type
, NULL
, new_int(memopt
));
299 rsc
= new_resource(res_type
,
302 new_language(PRIMARYLANGID(language
),
303 SUBLANGID(language
)));
306 rsc
->c_name
= make_c_name(get_c_typename(res_type
), name
, rsc
->lan
);
323 *****************************************************************************
330 *****************************************************************************
332 static resource_t
*read_res16(FILE *fp
)
334 internal_error(__FILE__
, __LINE__
, "Can't yet read 16 bit .res files\n");
339 *****************************************************************************
340 * Function : read_resfile
341 * Syntax : resource_t *read_resfile(char *inname)
346 *****************************************************************************
348 resource_t
*read_resfile(char *inname
)
351 struct resheader32 rh
;
355 fp
= fopen(inname
, "rb");
357 fatal_perror("Could not open %s", inname
);
359 /* Determine 16 or 32 bit .res file */
360 if(fread(&rh
, 1, sizeof(rh
), fp
) != sizeof(rh
))
364 if(!memcmp(&emptyheader
, &rh
, sizeof(rh
)))
366 else if(!memcmp(&emptyheaderSWAPPED
, &rh
, sizeof(rh
)))
367 error("Binary .res-file has its byteorder swapped\n");
372 if(is32bit
&& !win32
)
373 error("Cannot convert 32-bit .res-file into 16-bit resources (and will, hopefully never, implement it)\n");
375 if(!is32bit
&& win32
)
376 error("Cannot (yet) convert 16-bit .res-file into 32-bit resources\n");
380 fseek(fp
, 0, SEEK_SET
);
381 top
= read_res16(fp
);
385 top
= read_res32(fp
);