* elflink.c (_bfd_elf_link_assign_sym_version): Improve error
[deliverable/binutils-gdb.git] / binutils / resbin.c
CommitLineData
252b5132 1/* resbin.c -- manipulate the Windows binary resource format.
3db64b00 2 Copyright 1997, 1998, 1999, 2002, 2003, 2007
2da42df6 3 Free Software Foundation, Inc.
252b5132 4 Written by Ian Lance Taylor, Cygnus Support.
4a594fce 5 Rewritten by Kai Tietz, Onevision.
252b5132
RH
6
7 This file is part of GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
b43b5d5f
NC
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22 02110-1301, USA. */
252b5132
RH
23
24/* This file contains functions to convert between the binary resource
25 format and the internal structures that we want to use. The same
26 binary resource format is used in both res and COFF files. */
27
3db64b00 28#include "sysdep.h"
252b5132 29#include "bfd.h"
3db64b00 30#include "bucomm.h"
4a594fce 31#include "libiberty.h"
252b5132
RH
32#include "windres.h"
33
252b5132
RH
34/* Local functions. */
35
2da42df6
AJ
36static void toosmall (const char *);
37
4a594fce
NC
38static unichar *get_unicode (windres_bfd *, const bfd_byte *, rc_uint_type, rc_uint_type *);
39static int get_resid (windres_bfd *, rc_res_id *, const bfd_byte *, rc_uint_type);
40static rc_res_resource *bin_to_res_generic (windres_bfd *, enum rc_res_type,
41 const bfd_byte *, rc_uint_type);
42static rc_res_resource *bin_to_res_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
43static rc_res_resource *bin_to_res_menu (windres_bfd *,const bfd_byte *, rc_uint_type);
44static rc_menuitem *bin_to_res_menuitems (windres_bfd *, const bfd_byte *, rc_uint_type,
45 rc_uint_type *);
46static rc_menuitem *bin_to_res_menuexitems (windres_bfd *, const bfd_byte *, rc_uint_type,
47 rc_uint_type *);
48static rc_res_resource *bin_to_res_dialog (windres_bfd *, const bfd_byte *, rc_uint_type);
49static rc_res_resource *bin_to_res_string (windres_bfd *,const bfd_byte *, rc_uint_type);
50static rc_res_resource *bin_to_res_fontdir (windres_bfd *, const bfd_byte *, rc_uint_type);
51static rc_res_resource *bin_to_res_accelerators (windres_bfd *, const bfd_byte *, rc_uint_type);
52static rc_res_resource *bin_to_res_rcdata (windres_bfd *, const bfd_byte *, rc_uint_type, int);
53static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
54static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type);
55static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type);
56static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type);
57static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type);
58static void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *,
59 unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *,
60 rc_uint_type *);
252b5132
RH
61
62/* Given a resource type ID, a pointer to data, a length, return a
4a594fce 63 rc_res_resource structure which represents that resource. The caller
252b5132
RH
64 is responsible for initializing the res_info and coff_info fields
65 of the returned structure. */
66
4a594fce
NC
67rc_res_resource *
68bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data,
69 rc_uint_type length)
252b5132
RH
70{
71 if (type.named)
4a594fce 72 return bin_to_res_userdata (wrbfd, data, length);
252b5132
RH
73 else
74 {
75 switch (type.u.id)
76 {
77 default:
4a594fce 78 return bin_to_res_userdata (wrbfd, data, length);
252b5132 79 case RT_CURSOR:
4a594fce 80 return bin_to_res_cursor (wrbfd, data, length);
252b5132 81 case RT_BITMAP:
4a594fce 82 return bin_to_res_generic (wrbfd, RES_TYPE_BITMAP, data, length);
252b5132 83 case RT_ICON:
4a594fce 84 return bin_to_res_generic (wrbfd, RES_TYPE_ICON, data, length);
252b5132 85 case RT_MENU:
4a594fce 86 return bin_to_res_menu (wrbfd, data, length);
252b5132 87 case RT_DIALOG:
4a594fce 88 return bin_to_res_dialog (wrbfd, data, length);
252b5132 89 case RT_STRING:
4a594fce 90 return bin_to_res_string (wrbfd, data, length);
252b5132 91 case RT_FONTDIR:
4a594fce 92 return bin_to_res_fontdir (wrbfd, data, length);
252b5132 93 case RT_FONT:
4a594fce 94 return bin_to_res_generic (wrbfd, RES_TYPE_FONT, data, length);
252b5132 95 case RT_ACCELERATOR:
4a594fce 96 return bin_to_res_accelerators (wrbfd, data, length);
252b5132 97 case RT_RCDATA:
4a594fce 98 return bin_to_res_rcdata (wrbfd, data, length, RES_TYPE_RCDATA);
252b5132 99 case RT_MESSAGETABLE:
4a594fce 100 return bin_to_res_generic (wrbfd, RES_TYPE_MESSAGETABLE, data, length);
252b5132 101 case RT_GROUP_CURSOR:
4a594fce 102 return bin_to_res_group_cursor (wrbfd, data, length);
252b5132 103 case RT_GROUP_ICON:
4a594fce 104 return bin_to_res_group_icon (wrbfd, data, length);
252b5132 105 case RT_VERSION:
4a594fce
NC
106 return bin_to_res_version (wrbfd, data, length);
107 case RT_TOOLBAR:
108 return bin_to_res_toolbar (wrbfd, data, length);
109
252b5132
RH
110 }
111 }
112}
113
114/* Give an error if the binary data is too small. */
115
116static void
2da42df6 117toosmall (const char *msg)
252b5132
RH
118{
119 fatal (_("%s: not enough binary data"), msg);
120}
121
122/* Swap in a NULL terminated unicode string. */
123
124static unichar *
4a594fce
NC
125get_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
126 rc_uint_type *retlen)
252b5132 127{
4a594fce 128 rc_uint_type c, i;
252b5132
RH
129 unichar *ret;
130
131 c = 0;
132 while (1)
133 {
4a594fce 134 if (length < c * 2 + 2)
252b5132 135 toosmall (_("null terminated unicode string"));
4a594fce 136 if (windres_get_16 (wrbfd, data + c * 2, 2) == 0)
252b5132
RH
137 break;
138 ++c;
139 }
140
141 ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
142
143 for (i = 0; i < c; i++)
4a594fce 144 ret[i] = windres_get_16 (wrbfd, data + i * 2, 2);
252b5132
RH
145 ret[i] = 0;
146
147 if (retlen != NULL)
148 *retlen = c;
149
150 return ret;
151}
152
153/* Get a resource identifier. This returns the number of bytes used. */
154
155static int
4a594fce
NC
156get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data,
157 rc_uint_type length)
252b5132 158{
4a594fce 159 rc_uint_type first;
252b5132
RH
160
161 if (length < 2)
162 toosmall (_("resource ID"));
163
4a594fce 164 first = windres_get_16 (wrbfd, data, 2);
252b5132
RH
165 if (first == 0xffff)
166 {
167 if (length < 4)
168 toosmall (_("resource ID"));
169 id->named = 0;
4a594fce 170 id->u.id = windres_get_16 (wrbfd, data + 2, 2);
252b5132
RH
171 return 4;
172 }
173 else
174 {
175 id->named = 1;
4a594fce 176 id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length);
252b5132
RH
177 return id->u.n.length * 2 + 2;
178 }
179}
180
181/* Convert a resource which just stores uninterpreted data from
182 binary. */
183
4a594fce
NC
184rc_res_resource *
185bin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type,
186 const bfd_byte *data, rc_uint_type length)
252b5132 187{
4a594fce 188 rc_res_resource *r;
252b5132 189
4a594fce 190 r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
252b5132
RH
191 r->type = type;
192 r->u.data.data = data;
193 r->u.data.length = length;
194
195 return r;
196}
197
198/* Convert a cursor resource from binary. */
199
4a594fce
NC
200rc_res_resource *
201bin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
252b5132 202{
4a594fce
NC
203 rc_cursor *c;
204 rc_res_resource *r;
252b5132
RH
205
206 if (length < 4)
207 toosmall (_("cursor"));
208
4a594fce
NC
209 c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
210 c->xhotspot = windres_get_16 (wrbfd, data, 2);
211 c->yhotspot = windres_get_16 (wrbfd, data + 2, 2);
252b5132
RH
212 c->length = length - 4;
213 c->data = data + 4;
214
4a594fce 215 r = (rc_res_resource *) res_alloc (sizeof *r);
252b5132
RH
216 r->type = RES_TYPE_CURSOR;
217 r->u.cursor = c;
218
219 return r;
220}
221
222/* Convert a menu resource from binary. */
223
4a594fce
NC
224rc_res_resource *
225bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
252b5132 226{
4a594fce
NC
227 rc_res_resource *r;
228 rc_menu *m;
229 rc_uint_type version, read;
252b5132 230
4a594fce 231 r = (rc_res_resource *) res_alloc (sizeof *r);
252b5132
RH
232 r->type = RES_TYPE_MENU;
233
4a594fce 234 m = (rc_menu *) res_alloc (sizeof (rc_menu));
252b5132
RH
235 r->u.menu = m;
236
237 if (length < 2)
238 toosmall (_("menu header"));
239
4a594fce 240 version = windres_get_16 (wrbfd, data, 2);
252b5132
RH
241
242 if (version == 0)
243 {
244 if (length < 4)
245 toosmall (_("menu header"));
246 m->help = 0;
4a594fce 247 m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &read);
252b5132
RH
248 }
249 else if (version == 1)
250 {
4a594fce 251 rc_uint_type offset;
252b5132
RH
252
253 if (length < 8)
254 toosmall (_("menuex header"));
4a594fce
NC
255 m->help = windres_get_32 (wrbfd, data + 4, 4);
256 offset = windres_get_16 (wrbfd, data + 2, 2);
252b5132
RH
257 if (offset + 4 >= length)
258 toosmall (_("menuex offset"));
4a594fce
NC
259 m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset,
260 length - (4 + offset), &read);
252b5132
RH
261 }
262 else
4a594fce 263 fatal (_("unsupported menu version %d"), (int) version);
252b5132
RH
264
265 return r;
266}
267
268/* Convert menu items from binary. */
269
4a594fce
NC
270static rc_menuitem *
271bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
272 rc_uint_type *read)
252b5132 273{
4a594fce 274 rc_menuitem *first, **pp;
252b5132
RH
275
276 first = NULL;
277 pp = &first;
278
279 *read = 0;
280
281 while (length > 0)
282 {
4a594fce
NC
283 rc_uint_type flags, slen, itemlen;
284 rc_uint_type stroff;
285 rc_menuitem *mi;
252b5132
RH
286
287 if (length < 4)
288 toosmall (_("menuitem header"));
289
4a594fce 290 mi = (rc_menuitem *) res_alloc (sizeof *mi);
252b5132
RH
291 mi->state = 0;
292 mi->help = 0;
293
4a594fce 294 flags = windres_get_16 (wrbfd, data, 2);
252b5132
RH
295 mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
296
297 if ((flags & MENUITEM_POPUP) == 0)
298 stroff = 4;
299 else
300 stroff = 2;
301
302 if (length < stroff + 2)
303 toosmall (_("menuitem header"));
304
4a594fce 305 if (windres_get_16 (wrbfd, data + stroff, 2) == 0)
252b5132
RH
306 {
307 slen = 0;
308 mi->text = NULL;
309 }
310 else
4a594fce 311 mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen);
252b5132
RH
312
313 itemlen = stroff + slen * 2 + 2;
314
315 if ((flags & MENUITEM_POPUP) == 0)
316 {
317 mi->popup = NULL;
4a594fce 318 mi->id = windres_get_16 (wrbfd, data + 2, 2);
252b5132
RH
319 }
320 else
321 {
4a594fce 322 rc_uint_type subread;
252b5132
RH
323
324 mi->id = 0;
4a594fce
NC
325 mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen,
326 &subread);
252b5132
RH
327 itemlen += subread;
328 }
329
330 mi->next = NULL;
331 *pp = mi;
332 pp = &mi->next;
333
334 data += itemlen;
335 length -= itemlen;
336 *read += itemlen;
337
338 if ((flags & MENUITEM_ENDMENU) != 0)
339 return first;
340 }
341
342 return first;
343}
344
345/* Convert menuex items from binary. */
346
4a594fce
NC
347static rc_menuitem *
348bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
349 rc_uint_type *read)
252b5132 350{
4a594fce 351 rc_menuitem *first, **pp;
252b5132
RH
352
353 first = NULL;
354 pp = &first;
355
356 *read = 0;
357
358 while (length > 0)
359 {
4a594fce
NC
360 rc_uint_type flags, slen;
361 rc_uint_type itemlen;
362 rc_menuitem *mi;
252b5132 363
4a594fce 364 if (length < 16)
252b5132
RH
365 toosmall (_("menuitem header"));
366
4a594fce
NC
367 mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
368 mi->type = windres_get_32 (wrbfd, data, 4);
369 mi->state = windres_get_32 (wrbfd, data + 4, 4);
370 mi->id = windres_get_32 (wrbfd, data + 8, 4);
252b5132 371
4a594fce 372 flags = windres_get_16 (wrbfd, data + 12, 2);
252b5132 373
4a594fce 374 if (windres_get_16 (wrbfd, data + 14, 2) == 0)
252b5132
RH
375 {
376 slen = 0;
377 mi->text = NULL;
378 }
379 else
4a594fce 380 mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen);
252b5132 381
4a594fce 382 itemlen = 14 + slen * 2 + 2;
252b5132
RH
383 itemlen = (itemlen + 3) &~ 3;
384
385 if ((flags & 1) == 0)
386 {
387 mi->popup = NULL;
388 mi->help = 0;
389 }
390 else
391 {
4a594fce 392 rc_uint_type subread;
252b5132
RH
393
394 if (length < itemlen + 4)
395 toosmall (_("menuitem"));
4a594fce 396 mi->help = windres_get_32 (wrbfd, data + itemlen, 4);
252b5132
RH
397 itemlen += 4;
398
4a594fce
NC
399 mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen,
400 length - itemlen, &subread);
252b5132
RH
401 itemlen += subread;
402 }
403
404 mi->next = NULL;
405 *pp = mi;
406 pp = &mi->next;
407
408 data += itemlen;
409 length -= itemlen;
410 *read += itemlen;
411
412 if ((flags & 0x80) != 0)
413 return first;
414 }
415
416 return first;
417}
418
419/* Convert a dialog resource from binary. */
420
4a594fce
NC
421static rc_res_resource *
422bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
252b5132 423{
4a594fce
NC
424 rc_uint_type signature;
425 rc_dialog *d;
426 rc_uint_type c, sublen, i;
427 rc_uint_type off;
428 rc_dialog_control **pp;
429 rc_res_resource *r;
252b5132
RH
430
431 if (length < 18)
432 toosmall (_("dialog header"));
433
4a594fce 434 d = (rc_dialog *) res_alloc (sizeof (rc_dialog));
252b5132 435
4a594fce 436 signature = windres_get_16 (wrbfd, data + 2, 2);
7e8d45b7 437 if (signature != 0xffff)
252b5132
RH
438 {
439 d->ex = NULL;
4a594fce
NC
440 d->style = windres_get_32 (wrbfd, data, 4);
441 d->exstyle = windres_get_32 (wrbfd, data + 4, 4);
252b5132
RH
442 off = 8;
443 }
444 else
445 {
7e8d45b7 446 int version;
53c7db4b 447
4a594fce 448 version = windres_get_16 (wrbfd, data, 2);
7e8d45b7
NC
449 if (version != 1)
450 fatal (_("unexpected DIALOGEX version %d"), version);
252b5132 451
4a594fce
NC
452 d->ex = (rc_dialog_ex *) res_alloc (sizeof (rc_dialog_ex));
453 d->ex->help = windres_get_32 (wrbfd, data + 4, 4);
454 d->exstyle = windres_get_32 (wrbfd, data + 8, 4);
455 d->style = windres_get_32 (wrbfd, data + 12, 4);
252b5132
RH
456 off = 16;
457 }
458
459 if (length < off + 10)
460 toosmall (_("dialog header"));
461
4a594fce
NC
462 c = windres_get_16 (wrbfd, data + off, 2);
463 d->x = windres_get_16 (wrbfd, data + off + 2, 2);
464 d->y = windres_get_16 (wrbfd, data + off + 4, 2);
465 d->width = windres_get_16 (wrbfd, data + off + 6, 2);
466 d->height = windres_get_16 (wrbfd, data + off + 8, 2);
252b5132
RH
467
468 off += 10;
469
4a594fce 470 sublen = get_resid (wrbfd, &d->menu, data + off, length - off);
252b5132
RH
471 off += sublen;
472
4a594fce 473 sublen = get_resid (wrbfd, &d->class, data + off, length - off);
252b5132
RH
474 off += sublen;
475
4a594fce 476 d->caption = get_unicode (wrbfd, data + off, length - off, &sublen);
252b5132 477 off += sublen * 2 + 2;
53c7db4b 478 if (sublen == 0)
420380ba 479 d->caption = NULL;
252b5132
RH
480
481 if ((d->style & DS_SETFONT) == 0)
482 {
483 d->pointsize = 0;
484 d->font = NULL;
485 if (d->ex != NULL)
486 {
487 d->ex->weight = 0;
488 d->ex->italic = 0;
45b99827 489 d->ex->charset = 1; /* Default charset. */
252b5132
RH
490 }
491 }
492 else
493 {
494 if (length < off + 2)
495 toosmall (_("dialog font point size"));
496
4a594fce 497 d->pointsize = windres_get_16 (wrbfd, data + off, 2);
252b5132
RH
498 off += 2;
499
500 if (d->ex != NULL)
501 {
502 if (length < off + 4)
503 toosmall (_("dialogex font information"));
4a594fce
NC
504 d->ex->weight = windres_get_16 (wrbfd, data + off, 2);
505 d->ex->italic = windres_get_8 (wrbfd, data + off + 2, 1);
506 d->ex->charset = windres_get_8 (wrbfd, data + off + 3, 1);
252b5132
RH
507 off += 4;
508 }
509
4a594fce 510 d->font = get_unicode (wrbfd, data + off, length - off, &sublen);
252b5132
RH
511 off += sublen * 2 + 2;
512 }
513
514 d->controls = NULL;
515 pp = &d->controls;
516
517 for (i = 0; i < c; i++)
518 {
4a594fce 519 rc_dialog_control *dc;
252b5132
RH
520 int datalen;
521
522 off = (off + 3) &~ 3;
523
4a594fce 524 dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
252b5132
RH
525
526 if (d->ex == NULL)
527 {
528 if (length < off + 8)
529 toosmall (_("dialog control"));
530
4a594fce
NC
531 dc->style = windres_get_32 (wrbfd, data + off, 4);
532 dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
252b5132
RH
533 dc->help = 0;
534 off += 8;
535 }
536 else
537 {
538 if (length < off + 12)
539 toosmall (_("dialogex control"));
4a594fce
NC
540 dc->help = windres_get_32 (wrbfd, data + off, 4);
541 dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
542 dc->style = windres_get_32 (wrbfd, data + off + 8, 4);
252b5132
RH
543 off += 12;
544 }
545
4a594fce 546 if (length < off + (d->ex != NULL ? 2 : 0) + 10)
252b5132
RH
547 toosmall (_("dialog control"));
548
4a594fce
NC
549 dc->x = windres_get_16 (wrbfd, data + off, 2);
550 dc->y = windres_get_16 (wrbfd, data + off + 2, 2);
551 dc->width = windres_get_16 (wrbfd, data + off + 4, 2);
552 dc->height = windres_get_16 (wrbfd, data + off + 6, 2);
252b5132
RH
553
554 if (d->ex != NULL)
4a594fce 555 dc->id = windres_get_32 (wrbfd, data + off + 8, 4);
252b5132 556 else
4a594fce 557 dc->id = windres_get_16 (wrbfd, data + off + 8, 2);
252b5132
RH
558
559 off += 10 + (d->ex != NULL ? 2 : 0);
560
4a594fce 561 sublen = get_resid (wrbfd, &dc->class, data + off, length - off);
252b5132
RH
562 off += sublen;
563
4a594fce 564 sublen = get_resid (wrbfd, &dc->text, data + off, length - off);
252b5132
RH
565 off += sublen;
566
567 if (length < off + 2)
568 toosmall (_("dialog control end"));
569
4a594fce 570 datalen = windres_get_16 (wrbfd, data + off, 2);
252b5132
RH
571 off += 2;
572
573 if (datalen == 0)
574 dc->data = NULL;
575 else
576 {
577 off = (off + 3) &~ 3;
578
579 if (length < off + datalen)
580 toosmall (_("dialog control data"));
581
4a594fce
NC
582 dc->data = ((rc_rcdata_item *)
583 res_alloc (sizeof (rc_rcdata_item)));
252b5132
RH
584 dc->data->next = NULL;
585 dc->data->type = RCDATA_BUFFER;
586 dc->data->u.buffer.length = datalen;
587 dc->data->u.buffer.data = data + off;
588
53c7db4b 589 off += datalen;
252b5132
RH
590 }
591
592 dc->next = NULL;
593 *pp = dc;
594 pp = &dc->next;
595 }
596
4a594fce 597 r = (rc_res_resource *) res_alloc (sizeof *r);
252b5132
RH
598 r->type = RES_TYPE_DIALOG;
599 r->u.dialog = d;
600
601 return r;
602}
603
604/* Convert a stringtable resource from binary. */
605
4a594fce
NC
606static rc_res_resource *
607bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
252b5132 608{
4a594fce 609 rc_stringtable *st;
252b5132 610 int i;
4a594fce 611 rc_res_resource *r;
252b5132 612
4a594fce 613 st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable));
252b5132
RH
614
615 for (i = 0; i < 16; i++)
616 {
617 unsigned int slen;
618
619 if (length < 2)
620 toosmall (_("stringtable string length"));
4a594fce 621 slen = windres_get_16 (wrbfd, data, 2);
252b5132
RH
622 st->strings[i].length = slen;
623
624 if (slen > 0)
625 {
626 unichar *s;
627 unsigned int j;
628
629 if (length < 2 + 2 * slen)
630 toosmall (_("stringtable string"));
631
632 s = (unichar *) res_alloc (slen * sizeof (unichar));
633 st->strings[i].string = s;
634
635 for (j = 0; j < slen; j++)
4a594fce 636 s[j] = windres_get_16 (wrbfd, data + 2 + j * 2, 2);
252b5132
RH
637 }
638
639 data += 2 + 2 * slen;
640 length -= 2 + 2 * slen;
641 }
642
4a594fce 643 r = (rc_res_resource *) res_alloc (sizeof *r);
252b5132
RH
644 r->type = RES_TYPE_STRINGTABLE;
645 r->u.stringtable = st;
646
647 return r;
648}
649
650/* Convert a fontdir resource from binary. */
651
4a594fce
NC
652static rc_res_resource *
653bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
252b5132 654{
4a594fce
NC
655 rc_uint_type c, i;
656 rc_fontdir *first, **pp;
657 rc_res_resource *r;
252b5132
RH
658
659 if (length < 2)
660 toosmall (_("fontdir header"));
661
4a594fce 662 c = windres_get_16 (wrbfd, data, 2);
252b5132
RH
663
664 first = NULL;
665 pp = &first;
666
667 for (i = 0; i < c; i++)
668 {
4a594fce
NC
669 const struct bin_fontdir_item *bfi;
670 rc_fontdir *fd;
252b5132
RH
671 unsigned int off;
672
673 if (length < 56)
674 toosmall (_("fontdir"));
675
4a594fce
NC
676 bfi = (const struct bin_fontdir_item *) data;
677 fd = (rc_fontdir *) res_alloc (sizeof *fd);
678 fd->index = windres_get_16 (wrbfd, bfi->index, 2);
252b5132
RH
679
680 /* To work out the length of the fontdir data, we must get the
681 length of the device name and face name strings, even though
4a594fce 682 we don't store them in the rc_fontdir. The
252b5132
RH
683 documentation says that these are NULL terminated char
684 strings, not Unicode strings. */
685
686 off = 56;
687
688 while (off < length && data[off] != '\0')
689 ++off;
690 if (off >= length)
691 toosmall (_("fontdir device name"));
692 ++off;
693
694 while (off < length && data[off] != '\0')
695 ++off;
696 if (off >= length)
697 toosmall (_("fontdir face name"));
698 ++off;
699
700 fd->length = off;
701 fd->data = data;
702
703 fd->next = NULL;
704 *pp = fd;
705 pp = &fd->next;
706
707 /* The documentation does not indicate that any rounding is
708 required. */
709
710 data += off;
711 length -= off;
712 }
713
4a594fce 714 r = (rc_res_resource *) res_alloc (sizeof *r);
252b5132
RH
715 r->type = RES_TYPE_FONTDIR;
716 r->u.fontdir = first;
717
718 return r;
719}
720
721/* Convert an accelerators resource from binary. */
722
4a594fce
NC
723static rc_res_resource *
724bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
252b5132 725{
4a594fce
NC
726 rc_accelerator *first, **pp;
727 rc_res_resource *r;
252b5132
RH
728
729 first = NULL;
730 pp = &first;
731
732 while (1)
733 {
4a594fce 734 rc_accelerator *a;
252b5132
RH
735
736 if (length < 8)
737 toosmall (_("accelerator"));
738
4a594fce 739 a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator));
252b5132 740
4a594fce
NC
741 a->flags = windres_get_16 (wrbfd, data, 2);
742 a->key = windres_get_16 (wrbfd, data + 2, 2);
743 a->id = windres_get_16 (wrbfd, data + 4, 2);
252b5132
RH
744
745 a->next = NULL;
746 *pp = a;
747 pp = &a->next;
748
749 if ((a->flags & ACC_LAST) != 0)
750 break;
751
752 data += 8;
753 length -= 8;
754 }
755
4a594fce 756 r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
252b5132
RH
757 r->type = RES_TYPE_ACCELERATOR;
758 r->u.acc = first;
759
760 return r;
761}
762
763/* Convert an rcdata resource from binary. */
764
4a594fce
NC
765static rc_res_resource *
766bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
767 rc_uint_type length, int rctyp)
252b5132 768{
4a594fce
NC
769 rc_rcdata_item *ri;
770 rc_res_resource *r;
252b5132 771
4a594fce 772 ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
252b5132
RH
773
774 ri->next = NULL;
775 ri->type = RCDATA_BUFFER;
776 ri->u.buffer.length = length;
777 ri->u.buffer.data = data;
778
4a594fce
NC
779 r = (rc_res_resource *) res_alloc (sizeof *r);
780 r->type = rctyp;
252b5132
RH
781 r->u.rcdata = ri;
782
783 return r;
784}
785
786/* Convert a group cursor resource from binary. */
787
4a594fce
NC
788static rc_res_resource *
789bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
252b5132
RH
790{
791 int type, c, i;
4a594fce
NC
792 rc_group_cursor *first, **pp;
793 rc_res_resource *r;
252b5132
RH
794
795 if (length < 6)
796 toosmall (_("group cursor header"));
797
4a594fce 798 type = windres_get_16 (wrbfd, data + 2, 2);
252b5132
RH
799 if (type != 2)
800 fatal (_("unexpected group cursor type %d"), type);
801
4a594fce 802 c = windres_get_16 (wrbfd, data + 4, 2);
252b5132
RH
803
804 data += 6;
805 length -= 6;
806
807 first = NULL;
808 pp = &first;
809
810 for (i = 0; i < c; i++)
811 {
4a594fce 812 rc_group_cursor *gc;
252b5132
RH
813
814 if (length < 14)
815 toosmall (_("group cursor"));
816
4a594fce 817 gc = (rc_group_cursor *) res_alloc (sizeof *gc);
252b5132 818
4a594fce
NC
819 gc->width = windres_get_16 (wrbfd, data, 2);
820 gc->height = windres_get_16 (wrbfd, data + 2, 2);
821 gc->planes = windres_get_16 (wrbfd, data + 4, 2);
822 gc->bits = windres_get_16 (wrbfd, data + 6, 2);
823 gc->bytes = windres_get_32 (wrbfd, data + 8, 4);
824 gc->index = windres_get_16 (wrbfd, data + 12, 2);
252b5132
RH
825
826 gc->next = NULL;
827 *pp = gc;
828 pp = &gc->next;
829
830 data += 14;
831 length -= 14;
832 }
833
4a594fce 834 r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
252b5132
RH
835 r->type = RES_TYPE_GROUP_CURSOR;
836 r->u.group_cursor = first;
837
838 return r;
839}
840
841/* Convert a group icon resource from binary. */
842
4a594fce
NC
843static rc_res_resource *
844bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
252b5132
RH
845{
846 int type, c, i;
4a594fce
NC
847 rc_group_icon *first, **pp;
848 rc_res_resource *r;
252b5132
RH
849
850 if (length < 6)
851 toosmall (_("group icon header"));
852
4a594fce 853 type = windres_get_16 (wrbfd, data + 2, 2);
252b5132
RH
854 if (type != 1)
855 fatal (_("unexpected group icon type %d"), type);
856
4a594fce 857 c = windres_get_16 (wrbfd, data + 4, 2);
252b5132
RH
858
859 data += 6;
860 length -= 6;
861
862 first = NULL;
863 pp = &first;
864
865 for (i = 0; i < c; i++)
866 {
4a594fce 867 rc_group_icon *gi;
252b5132
RH
868
869 if (length < 14)
870 toosmall (_("group icon"));
871
4a594fce 872 gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
252b5132 873
4a594fce
NC
874 gi->width = windres_get_8 (wrbfd, data, 1);
875 gi->height = windres_get_8 (wrbfd, data + 1, 1);
876 gi->colors = windres_get_8 (wrbfd, data + 2, 1);
877 gi->planes = windres_get_16 (wrbfd, data + 4, 2);
878 gi->bits = windres_get_16 (wrbfd, data + 6, 2);
879 gi->bytes = windres_get_32 (wrbfd, data + 8, 4);
880 gi->index = windres_get_16 (wrbfd, data + 12, 2);
252b5132
RH
881
882 gi->next = NULL;
883 *pp = gi;
884 pp = &gi->next;
885
886 data += 14;
887 length -= 14;
888 }
889
4a594fce 890 r = (rc_res_resource *) res_alloc (sizeof *r);
252b5132
RH
891 r->type = RES_TYPE_GROUP_ICON;
892 r->u.group_icon = first;
893
894 return r;
895}
896
897/* Extract data from a version header. If KEY is not NULL, then the
898 key must be KEY; otherwise, the key is returned in *PKEY. This
899 sets *LEN to the total length, *VALLEN to the value length, *TYPE
900 to the type, and *OFF to the offset to the children. */
901
902static void
4a594fce
NC
903get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
904 const char *key, unichar **pkey,
905 rc_uint_type *len, rc_uint_type *vallen, rc_uint_type *type,
906 rc_uint_type *off)
252b5132
RH
907{
908 if (length < 8)
909 toosmall (key);
910
4a594fce
NC
911 *len = windres_get_16 (wrbfd, data, 2);
912 *vallen = windres_get_16 (wrbfd, data + 2, 2);
913 *type = windres_get_16 (wrbfd, data + 4, 2);
252b5132
RH
914
915 *off = 6;
916
917 length -= 6;
918 data += 6;
919
920 if (key == NULL)
921 {
4a594fce 922 rc_uint_type sublen;
252b5132 923
4a594fce
NC
924 *pkey = get_unicode (wrbfd, data, length, &sublen);
925 *off += (sublen + 1) * sizeof (unichar);
252b5132
RH
926 }
927 else
928 {
929 while (1)
930 {
931 if (length < 2)
932 toosmall (key);
4a594fce 933 if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key)
252b5132
RH
934 fatal (_("unexpected version string"));
935
936 *off += 2;
937 length -= 2;
938 data += 2;
939
940 if (*key == '\0')
941 break;
942
943 ++key;
944 }
945 }
946
947 *off = (*off + 3) &~ 3;
948}
949
950/* Convert a version resource from binary. */
951
4a594fce
NC
952static rc_res_resource *
953bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
252b5132 954{
4a594fce
NC
955 rc_uint_type verlen, vallen, type, off;
956 rc_fixed_versioninfo *fi;
957 rc_ver_info *first, **pp;
958 rc_versioninfo *v;
959 rc_res_resource *r;
252b5132 960
4a594fce 961 get_version_header (wrbfd, data, length, "VS_VERSION_INFO",
7e8d45b7 962 (unichar **) NULL, &verlen, &vallen, &type, &off);
252b5132
RH
963
964 if ((unsigned int) verlen != length)
965 fatal (_("version length %d does not match resource length %lu"),
4a594fce 966 (int) verlen, (unsigned long) length);
252b5132
RH
967
968 if (type != 0)
4a594fce 969 fatal (_("unexpected version type %d"), (int) type);
252b5132
RH
970
971 data += off;
972 length -= off;
973
974 if (vallen == 0)
975 fi = NULL;
976 else
977 {
978 unsigned long signature, fiv;
979
980 if (vallen != 52)
4a594fce 981 fatal (_("unexpected fixed version information length %ld"), (long) vallen);
252b5132
RH
982
983 if (length < 52)
984 toosmall (_("fixed version info"));
985
4a594fce 986 signature = windres_get_32 (wrbfd, data, 4);
252b5132
RH
987 if (signature != 0xfeef04bd)
988 fatal (_("unexpected fixed version signature %lu"), signature);
989
4a594fce 990 fiv = windres_get_32 (wrbfd, data + 4, 4);
252b5132
RH
991 if (fiv != 0 && fiv != 0x10000)
992 fatal (_("unexpected fixed version info version %lu"), fiv);
993
4a594fce 994 fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo));
252b5132 995
4a594fce
NC
996 fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4);
997 fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4);
998 fi->product_version_ms = windres_get_32 (wrbfd, data + 16, 4);
999 fi->product_version_ls = windres_get_32 (wrbfd, data + 20, 4);
1000 fi->file_flags_mask = windres_get_32 (wrbfd, data + 24, 4);
1001 fi->file_flags = windres_get_32 (wrbfd, data + 28, 4);
1002 fi->file_os = windres_get_32 (wrbfd, data + 32, 4);
1003 fi->file_type = windres_get_32 (wrbfd, data + 36, 4);
1004 fi->file_subtype = windres_get_32 (wrbfd, data + 40, 4);
1005 fi->file_date_ms = windres_get_32 (wrbfd, data + 44, 4);
1006 fi->file_date_ls = windres_get_32 (wrbfd, data + 48, 4);
252b5132
RH
1007
1008 data += 52;
1009 length -= 52;
1010 }
1011
1012 first = NULL;
1013 pp = &first;
1014
1015 while (length > 0)
1016 {
4a594fce 1017 rc_ver_info *vi;
252b5132
RH
1018 int ch;
1019
1020 if (length < 8)
1021 toosmall (_("version var info"));
1022
4a594fce 1023 vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
252b5132 1024
4a594fce 1025 ch = windres_get_16 (wrbfd, data + 6, 2);
252b5132
RH
1026
1027 if (ch == 'S')
1028 {
4a594fce 1029 rc_ver_stringinfo **ppvs;
252b5132
RH
1030
1031 vi->type = VERINFO_STRING;
1032
4a594fce 1033 get_version_header (wrbfd, data, length, "StringFileInfo",
7e8d45b7 1034 (unichar **) NULL, &verlen, &vallen, &type,
252b5132
RH
1035 &off);
1036
1037 if (vallen != 0)
4a594fce 1038 fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen);
252b5132
RH
1039
1040 data += off;
1041 length -= off;
1042
4a594fce 1043 get_version_header (wrbfd, data, length, (const char *) NULL,
252b5132
RH
1044 &vi->u.string.language, &verlen, &vallen,
1045 &type, &off);
1046
1047 if (vallen != 0)
4a594fce 1048 fatal (_("unexpected version stringtable value length %ld"), (long) vallen);
252b5132
RH
1049
1050 data += off;
1051 length -= off;
1052 verlen -= off;
1053
1054 vi->u.string.strings = NULL;
1055 ppvs = &vi->u.string.strings;
1056
1057 /* It's convenient to round verlen to a 4 byte alignment,
1058 since we round the subvariables in the loop. */
1059 verlen = (verlen + 3) &~ 3;
1060
1061 while (verlen > 0)
1062 {
4a594fce
NC
1063 rc_ver_stringinfo *vs;
1064 rc_uint_type subverlen, vslen, valoff;
252b5132 1065
4a594fce 1066 vs = (rc_ver_stringinfo *) res_alloc (sizeof *vs);
252b5132 1067
4a594fce 1068 get_version_header (wrbfd, data, length,
252b5132
RH
1069 (const char *) NULL, &vs->key, &subverlen,
1070 &vallen, &type, &off);
1071
1072 subverlen = (subverlen + 3) &~ 3;
1073
1074 data += off;
1075 length -= off;
1076
4a594fce 1077 vs->value = get_unicode (wrbfd, data, length, &vslen);
252b5132
RH
1078 valoff = vslen * 2 + 2;
1079 valoff = (valoff + 3) &~ 3;
1080
1081 if (off + valoff != subverlen)
4a594fce
NC
1082 fatal (_("unexpected version string length %ld != %ld + %ld"),
1083 (long) subverlen, (long) off, (long) valoff);
252b5132
RH
1084
1085 vs->next = NULL;
1086 *ppvs = vs;
1087 ppvs = &vs->next;
1088
1089 data += valoff;
1090 length -= valoff;
1091
1092 if (verlen < subverlen)
4a594fce
NC
1093 fatal (_("unexpected version string length %ld < %ld"),
1094 (long) verlen, (long) subverlen);
252b5132
RH
1095
1096 verlen -= subverlen;
1097 }
1098 }
1099 else if (ch == 'V')
1100 {
4a594fce 1101 rc_ver_varinfo **ppvv;
252b5132
RH
1102
1103 vi->type = VERINFO_VAR;
1104
4a594fce 1105 get_version_header (wrbfd, data, length, "VarFileInfo",
7e8d45b7 1106 (unichar **) NULL, &verlen, &vallen, &type,
252b5132
RH
1107 &off);
1108
1109 if (vallen != 0)
4a594fce 1110 fatal (_("unexpected varfileinfo value length %ld"), (long) vallen);
252b5132
RH
1111
1112 data += off;
1113 length -= off;
1114
4a594fce 1115 get_version_header (wrbfd, data, length, (const char *) NULL,
252b5132
RH
1116 &vi->u.var.key, &verlen, &vallen, &type, &off);
1117
1118 data += off;
1119 length -= off;
1120
1121 vi->u.var.var = NULL;
1122 ppvv = &vi->u.var.var;
1123
1124 while (vallen > 0)
1125 {
4a594fce 1126 rc_ver_varinfo *vv;
252b5132
RH
1127
1128 if (length < 4)
1129 toosmall (_("version varfileinfo"));
1130
4a594fce 1131 vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
252b5132 1132
4a594fce
NC
1133 vv->language = windres_get_16 (wrbfd, data, 2);
1134 vv->charset = windres_get_16 (wrbfd, data + 2, 2);
252b5132
RH
1135
1136 vv->next = NULL;
1137 *ppvv = vv;
1138 ppvv = &vv->next;
1139
1140 data += 4;
1141 length -= 4;
1142
1143 if (vallen < 4)
4a594fce 1144 fatal (_("unexpected version value length %ld"), (long) vallen);
252b5132
RH
1145
1146 vallen -= 4;
1147 }
1148 }
1149 else
1150 fatal (_("unexpected version string"));
1151
1152 vi->next = NULL;
1153 *pp = vi;
53c7db4b 1154 pp = &vi->next;
252b5132
RH
1155 }
1156
4a594fce 1157 v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo));
252b5132
RH
1158 v->fixed = fi;
1159 v->var = first;
1160
4a594fce 1161 r = (rc_res_resource *) res_alloc (sizeof *r);
252b5132
RH
1162 r->type = RES_TYPE_VERSIONINFO;
1163 r->u.versioninfo = v;
1164
53c7db4b 1165 return r;
252b5132
RH
1166}
1167
1168/* Convert an arbitrary user defined resource from binary. */
1169
4a594fce
NC
1170static rc_res_resource *
1171bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
1172 rc_uint_type length)
252b5132 1173{
4a594fce
NC
1174 rc_rcdata_item *ri;
1175 rc_res_resource *r;
252b5132 1176
4a594fce 1177 ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
252b5132
RH
1178
1179 ri->next = NULL;
1180 ri->type = RCDATA_BUFFER;
1181 ri->u.buffer.length = length;
1182 ri->u.buffer.data = data;
1183
4a594fce 1184 r = (rc_res_resource *) res_alloc (sizeof *r);
252b5132
RH
1185 r->type = RES_TYPE_USERDATA;
1186 r->u.rcdata = ri;
1187
1188 return r;
1189}
1190\f
4a594fce
NC
1191static rc_res_resource *
1192bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
1193{
1194 rc_toolbar *ri;
1195 rc_res_resource *r;
1196 rc_uint_type i;
1197
1198 ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
1199 ri->button_width = windres_get_32 (wrbfd, data, 4);
1200 ri->button_height = windres_get_32 (wrbfd, data + 4, 4);
1201 ri->nitems = windres_get_32 (wrbfd, data + 8, 4);
1202 ri->items = NULL;
1203
1204 data += 12;
1205 length -= 12;
1206 for (i=0 ; i < ri->nitems; i++)
1207 {
1208 rc_toolbar_item *it;
1209 it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item));
1210 it->id.named = 0;
1211 it->id.u.id = (int) windres_get_32 (wrbfd, data, 4);
1212 it->prev = it->next = NULL;
1213 data += 4;
1214 length -= 4;
1215 if(ri->items) {
1216 rc_toolbar_item *ii = ri->items;
1217 while (ii->next != NULL)
1218 ii = ii->next;
1219 it->prev = ii;
1220 ii->next = it;
1221 }
1222 else
1223 ri->items = it;
1224 }
1225 r = (rc_res_resource *) res_alloc (sizeof *r);
1226 r->type = RES_TYPE_TOOLBAR;
1227 r->u.toolbar = ri;
1228 return r;
1229}
252b5132 1230
252b5132
RH
1231
1232/* Local functions used to convert resources to binary format. */
1233
4a594fce
NC
1234static rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id);
1235static rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *);
1236static rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *);
1237static rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *);
1238static rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *);
1239static rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *);
1240static rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *);
1241static rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *);
1242static rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *);
1243static rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
1244static rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
1245static rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *);
1246static rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *);
1247static rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *);
1248static rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb);
1249static rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *);
1250static rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type,
1251 const bfd_byte *);
252b5132
RH
1252
1253/* Convert a resource to binary. */
1254
4a594fce
NC
1255rc_uint_type
1256res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res)
252b5132
RH
1257{
1258 switch (res->type)
1259 {
252b5132
RH
1260 case RES_TYPE_BITMAP:
1261 case RES_TYPE_FONT:
1262 case RES_TYPE_ICON:
1263 case RES_TYPE_MESSAGETABLE:
4a594fce 1264 return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data);
252b5132 1265 case RES_TYPE_ACCELERATOR:
4a594fce 1266 return res_to_bin_accelerator (wrbfd, off, res->u.acc);
252b5132 1267 case RES_TYPE_CURSOR:
4a594fce 1268 return res_to_bin_cursor (wrbfd, off, res->u.cursor);
252b5132 1269 case RES_TYPE_GROUP_CURSOR:
4a594fce 1270 return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor);
252b5132 1271 case RES_TYPE_DIALOG:
4a594fce 1272 return res_to_bin_dialog (wrbfd, off, res->u.dialog);
252b5132 1273 case RES_TYPE_FONTDIR:
4a594fce 1274 return res_to_bin_fontdir (wrbfd, off, res->u.fontdir);
252b5132 1275 case RES_TYPE_GROUP_ICON:
4a594fce 1276 return res_to_bin_group_icon (wrbfd, off, res->u.group_icon);
252b5132 1277 case RES_TYPE_MENU:
4a594fce 1278 return res_to_bin_menu (wrbfd, off, res->u.menu);
252b5132 1279 case RES_TYPE_STRINGTABLE:
4a594fce 1280 return res_to_bin_stringtable (wrbfd, off, res->u.stringtable);
252b5132 1281 case RES_TYPE_VERSIONINFO:
4a594fce
NC
1282 return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo);
1283 case RES_TYPE_TOOLBAR:
1284 return res_to_bin_toolbar (wrbfd, off, res->u.toolbar);
1285 case RES_TYPE_USERDATA:
1286 case RES_TYPE_RCDATA:
1287 default:
1288 return res_to_bin_rcdata (wrbfd, off, res->u.rcdata);
252b5132
RH
1289 }
1290}
1291
252b5132
RH
1292/* Convert a resource ID to binary. This always returns exactly one
1293 bindata structure. */
1294
4a594fce
NC
1295static rc_uint_type
1296resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id)
252b5132 1297{
252b5132
RH
1298 if (! id.named)
1299 {
4a594fce
NC
1300 if (wrbfd)
1301 {
1302 struct bin_res_id bri;
1303
1304 windres_put_16 (wrbfd, bri.sig, 0xffff);
1305 windres_put_16 (wrbfd, bri.id, id.u.id);
1306 set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID);
1307 }
1308 off += BIN_RES_ID;
252b5132
RH
1309 }
1310 else
1311 {
4a594fce
NC
1312 rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0);
1313 if (wrbfd)
1314 {
1315 bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
1316 rc_uint_type i;
1317 for (i = 0; i < len; i++)
1318 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]);
1319 windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
1320 set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
252b5132 1321 }
4a594fce
NC
1322 off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1323 }
1324 return off;
252b5132
RH
1325}
1326
1327/* Convert a null terminated unicode string to binary. This always
1328 returns exactly one bindata structure. */
1329
4a594fce
NC
1330static rc_uint_type
1331unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str)
252b5132 1332{
4a594fce 1333 rc_uint_type len = 0;
252b5132 1334
252b5132 1335 if (str != NULL)
4a594fce 1336 len = unichar_len (str);
252b5132 1337
4a594fce 1338 if (wrbfd)
252b5132 1339 {
4a594fce
NC
1340 bfd_byte *d;
1341 rc_uint_type i;
1342 d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar));
1343 for (i = 0; i < len; i++)
1344 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]);
1345 windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
1346 set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
252b5132 1347 }
4a594fce 1348 off += (rc_uint_type) ((len + 1) * sizeof (unichar));
252b5132 1349
4a594fce 1350 return off;
252b5132
RH
1351}
1352
1353/* Convert an accelerator resource to binary. */
1354
4a594fce
NC
1355static rc_uint_type
1356res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off,
1357 const rc_accelerator *accelerators)
252b5132 1358{
4a594fce
NC
1359 bindata *first, **pp;
1360 const rc_accelerator *a;
252b5132
RH
1361
1362 first = NULL;
1363 pp = &first;
1364
1365 for (a = accelerators; a != NULL; a = a->next)
1366 {
4a594fce
NC
1367 if (wrbfd)
1368 {
1369 struct bin_accelerator ba;
252b5132 1370
4a594fce
NC
1371 windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST));
1372 windres_put_16 (wrbfd, ba.key, a->key);
1373 windres_put_16 (wrbfd, ba.id, a->id);
1374 windres_put_16 (wrbfd, ba.pad, 0);
1375 set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE);
1376 }
1377 off += BIN_ACCELERATOR_SIZE;
1378 }
1379 return off;
252b5132
RH
1380}
1381
1382/* Convert a cursor resource to binary. */
1383
4a594fce
NC
1384static rc_uint_type
1385res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c)
252b5132 1386{
4a594fce
NC
1387 if (wrbfd)
1388 {
1389 struct bin_cursor bc;
252b5132 1390
4a594fce
NC
1391 windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot);
1392 windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot);
1393 set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE);
1394 if (c->length)
1395 set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length);
1396 }
1397 off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length);
1398 return off;
252b5132
RH
1399}
1400
1401/* Convert a group cursor resource to binary. */
1402
4a594fce
NC
1403static rc_uint_type
1404res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off,
1405 const rc_group_cursor *group_cursors)
252b5132 1406{
4a594fce
NC
1407 int c = 0;
1408 const rc_group_cursor *gc;
1409 struct bin_group_cursor bgc;
1410 struct bin_group_cursor_item bgci;
1411 rc_uint_type start = off;
252b5132 1412
4a594fce 1413 off += BIN_GROUP_CURSOR_SIZE;
252b5132 1414
4a594fce 1415 for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++)
252b5132 1416 {
4a594fce
NC
1417 if (wrbfd)
1418 {
1419 windres_put_16 (wrbfd, bgci.width, gc->width);
1420 windres_put_16 (wrbfd, bgci.height, gc->height);
1421 windres_put_16 (wrbfd, bgci.planes, gc->planes);
1422 windres_put_16 (wrbfd, bgci.bits, gc->bits);
1423 windres_put_32 (wrbfd, bgci.bytes, gc->bytes);
1424 windres_put_16 (wrbfd, bgci.index, gc->index);
1425 set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE);
252b5132
RH
1426 }
1427
4a594fce
NC
1428 off += BIN_GROUP_CURSOR_ITEM_SIZE;
1429 }
1430 if (wrbfd)
1431 {
1432 windres_put_16 (wrbfd, bgc.sig1, 0);
1433 windres_put_16 (wrbfd, bgc.sig2, 2);
1434 windres_put_16 (wrbfd, bgc.nitems, c);
1435 set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE);
1436 }
1437 return off;
252b5132
RH
1438}
1439
1440/* Convert a dialog resource to binary. */
1441
4a594fce
NC
1442static rc_uint_type
1443res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog)
252b5132 1444{
4a594fce
NC
1445 rc_uint_type off_delta;
1446 rc_uint_type start, marker;
252b5132 1447 int dialogex;
4a594fce
NC
1448 int c;
1449 rc_dialog_control *dc;
1450 struct bin_dialogex bdx;
1451 struct bin_dialog bd;
252b5132 1452
4a594fce
NC
1453 off_delta = off;
1454 start = off;
252b5132
RH
1455 dialogex = extended_dialog (dialog);
1456
4a594fce
NC
1457 if (wrbfd)
1458 {
252b5132
RH
1459 if (! dialogex)
1460 {
4a594fce
NC
1461 windres_put_32 (wrbfd, bd.style, dialog->style);
1462 windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle);
1463 windres_put_16 (wrbfd, bd.x, dialog->x);
1464 windres_put_16 (wrbfd, bd.y, dialog->y);
1465 windres_put_16 (wrbfd, bd.width, dialog->width);
1466 windres_put_16 (wrbfd, bd.height, dialog->height);
252b5132
RH
1467 }
1468 else
1469 {
4a594fce
NC
1470 windres_put_16 (wrbfd, bdx.sig1, 1);
1471 windres_put_16 (wrbfd, bdx.sig2, 0xffff);
1472 windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0));
1473 windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle);
1474 windres_put_32 (wrbfd, bdx.style, dialog->style);
1475 windres_put_16 (wrbfd, bdx.x, dialog->x);
1476 windres_put_16 (wrbfd, bdx.y, dialog->y);
1477 windres_put_16 (wrbfd, bdx.width, dialog->width);
1478 windres_put_16 (wrbfd, bdx.height, dialog->height);
1479 }
252b5132
RH
1480 }
1481
4a594fce 1482 off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE);
252b5132 1483
4a594fce
NC
1484 off = resid_to_bin (wrbfd, off, dialog->menu);
1485 off = resid_to_bin (wrbfd, off, dialog->class);
1486 off = unicode_to_bin (wrbfd, off, dialog->caption);
252b5132
RH
1487
1488 if ((dialog->style & DS_SETFONT) != 0)
1489 {
4a594fce 1490 if (wrbfd)
252b5132 1491 {
4a594fce 1492 if (! dialogex)
252b5132 1493 {
4a594fce
NC
1494 struct bin_dialogfont bdf;
1495 windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize);
1496 set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE);
252b5132
RH
1497 }
1498 else
1499 {
4a594fce
NC
1500 struct bin_dialogexfont bdxf;
1501 windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize);
1502 windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight));
1503 windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic));
1504 windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset));
1505 set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE);
252b5132
RH
1506 }
1507 }
4a594fce
NC
1508 off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE);
1509 off = unicode_to_bin (wrbfd, off, dialog->font);
252b5132 1510 }
4a594fce 1511 for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++)
252b5132 1512 {
4a594fce 1513 bfd_byte dc_rclen[2];
252b5132 1514
4a594fce
NC
1515 off += (4 - ((off - off_delta) & 3)) & 3;
1516 if (wrbfd)
1517 {
252b5132
RH
1518 if (! dialogex)
1519 {
4a594fce
NC
1520 struct bin_dialog_control bdc;
1521
1522 windres_put_32 (wrbfd, bdc.style, dc->style);
1523 windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
1524 windres_put_16 (wrbfd, bdc.x, dc->x);
1525 windres_put_16 (wrbfd, bdc.y, dc->y);
1526 windres_put_16 (wrbfd, bdc.width, dc->width);
1527 windres_put_16 (wrbfd, bdc.height, dc->height);
1528 windres_put_16 (wrbfd, bdc.id, dc->id);
1529 set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE);
252b5132
RH
1530 }
1531 else
1532 {
4a594fce
NC
1533 struct bin_dialogex_control bdc;
1534
1535 windres_put_32 (wrbfd, bdc.help, dc->help);
1536 windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
1537 windres_put_32 (wrbfd, bdc.style, dc->style);
1538 windres_put_16 (wrbfd, bdc.x, dc->x);
1539 windres_put_16 (wrbfd, bdc.y, dc->y);
1540 windres_put_16 (wrbfd, bdc.width, dc->width);
1541 windres_put_16 (wrbfd, bdc.height, dc->height);
1542 windres_put_32 (wrbfd, bdc.id, dc->id);
1543 set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE);
1544 }
1545 }
1546 off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE);
252b5132 1547
4a594fce
NC
1548 off = resid_to_bin (wrbfd, off, dc->class);
1549 off = resid_to_bin (wrbfd, off, dc->text);
252b5132 1550
4a594fce
NC
1551 marker = off; /* Save two bytes for size of optional data. */
1552 off += 2;
252b5132
RH
1553
1554 if (dc->data == NULL)
4a594fce
NC
1555 {
1556 if (wrbfd)
1557 windres_put_16 (wrbfd, dc_rclen, 0);
1558 }
252b5132
RH
1559 else
1560 {
4a594fce
NC
1561 rc_uint_type saved_off = off;
1562 rc_uint_type old_off;
1563 off += (4 - ((off - off_delta) & 3)) & 3;
1564
1565 old_off = off;
1566 off = res_to_bin_rcdata (wrbfd, off, dc->data);
1567 if ((off - old_off) == 0)
1568 old_off = off = saved_off;
1569 if (wrbfd)
1570 windres_put_16 (wrbfd, dc_rclen, off - old_off);
252b5132 1571 }
4a594fce
NC
1572 if (wrbfd)
1573 set_windres_bfd_content (wrbfd, dc_rclen, marker, 2);
252b5132 1574 }
4a594fce
NC
1575
1576 if (wrbfd)
1577 {
1578 windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c);
1579 if (! dialogex)
1580 set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE);
1581 else
1582 set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE);
252b5132 1583 }
252b5132 1584
4a594fce 1585 return off;
252b5132
RH
1586}
1587
1588/* Convert a fontdir resource to binary. */
4a594fce
NC
1589static rc_uint_type
1590res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs)
252b5132 1591{
4a594fce 1592 rc_uint_type start;
252b5132 1593 int c;
4a594fce 1594 const rc_fontdir *fd;
252b5132 1595
4a594fce
NC
1596 start = off;
1597 off += 2;
252b5132 1598
4a594fce 1599 for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++)
252b5132 1600 {
4a594fce
NC
1601 if (wrbfd)
1602 {
1603 bfd_byte d[2];
1604 windres_put_16 (wrbfd, d, fd->index);
1605 set_windres_bfd_content (wrbfd, d, off, 2);
1606 if (fd->length)
1607 set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length);
1608 }
1609 off += (rc_uint_type) fd->length + 2;
252b5132
RH
1610 }
1611
4a594fce
NC
1612 if (wrbfd)
1613 {
1614 bfd_byte d[2];
1615 windres_put_16 (wrbfd, d, c);
1616 set_windres_bfd_content (wrbfd, d, start, 2);
1617 }
1618 return off;
252b5132
RH
1619}
1620
1621/* Convert a group icon resource to binary. */
1622
4a594fce
NC
1623static rc_uint_type
1624res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons)
252b5132 1625{
4a594fce
NC
1626 rc_uint_type start;
1627 struct bin_group_icon bgi;
252b5132 1628 int c;
4a594fce 1629 const rc_group_icon *gi;
252b5132 1630
4a594fce
NC
1631 start = off;
1632 off += BIN_GROUP_ICON_SIZE;
252b5132 1633
4a594fce 1634 for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++)
252b5132 1635 {
4a594fce 1636 struct bin_group_icon_item bgii;
252b5132 1637
4a594fce
NC
1638 if (wrbfd)
1639 {
1640 windres_put_8 (wrbfd, bgii.width, gi->width);
1641 windres_put_8 (wrbfd, bgii.height, gi->height);
1642 windres_put_8 (wrbfd, bgii.colors, gi->colors);
1643 windres_put_8 (wrbfd, bgii.pad, 0);
1644 windres_put_16 (wrbfd, bgii.planes, gi->planes);
1645 windres_put_16 (wrbfd, bgii.bits, gi->bits);
1646 windres_put_32 (wrbfd, bgii.bytes, gi->bytes);
1647 windres_put_16 (wrbfd, bgii.index, gi->index);
1648 set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE);
1649 }
1650 off += BIN_GROUP_ICON_ITEM_SIZE;
252b5132
RH
1651 }
1652
4a594fce
NC
1653 if (wrbfd)
1654 {
1655 windres_put_16 (wrbfd, bgi.sig1, 0);
1656 windres_put_16 (wrbfd, bgi.sig2, 1);
1657 windres_put_16 (wrbfd, bgi.count, c);
1658 set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE);
1659 }
1660 return off;
252b5132
RH
1661}
1662
1663/* Convert a menu resource to binary. */
1664
4a594fce
NC
1665static rc_uint_type
1666res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu)
252b5132
RH
1667{
1668 int menuex;
252b5132
RH
1669
1670 menuex = extended_menu (menu);
1671
4a594fce
NC
1672 if (wrbfd)
1673 {
252b5132
RH
1674 if (! menuex)
1675 {
4a594fce
NC
1676 struct bin_menu bm;
1677 windres_put_16 (wrbfd, bm.sig1, 0);
1678 windres_put_16 (wrbfd, bm.sig2, 0);
1679 set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE);
252b5132
RH
1680 }
1681 else
1682 {
4a594fce
NC
1683 struct bin_menuex bm;
1684 windres_put_16 (wrbfd, bm.sig1, 1);
1685 windres_put_16 (wrbfd, bm.sig2, 4);
1686 windres_put_32 (wrbfd, bm.help, menu->help);
1687 set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE);
252b5132 1688 }
4a594fce
NC
1689 }
1690 off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE);
1691 if (! menuex)
1692 {
1693 off = res_to_bin_menuitems (wrbfd, off, menu->items);
1694 }
1695 else
1696 {
1697 off = res_to_bin_menuexitems (wrbfd, off, menu->items);
1698 }
1699 return off;
252b5132
RH
1700}
1701
1702/* Convert menu items to binary. */
1703
4a594fce
NC
1704static rc_uint_type
1705res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
252b5132 1706{
4a594fce 1707 const rc_menuitem *mi;
252b5132
RH
1708
1709 for (mi = items; mi != NULL; mi = mi->next)
1710 {
4a594fce 1711 struct bin_menuitem bmi;
252b5132
RH
1712 int flags;
1713
252b5132
RH
1714 flags = mi->type;
1715 if (mi->next == NULL)
1716 flags |= MENUITEM_ENDMENU;
1717 if (mi->popup != NULL)
1718 flags |= MENUITEM_POPUP;
1719
4a594fce
NC
1720 if (wrbfd)
1721 {
1722 windres_put_16 (wrbfd, bmi.flags, flags);
252b5132 1723 if (mi->popup == NULL)
4a594fce
NC
1724 windres_put_16 (wrbfd, bmi.id, mi->id);
1725 set_windres_bfd_content (wrbfd, &bmi, off,
1726 mi->popup == NULL ? BIN_MENUITEM_SIZE
1727 : BIN_MENUITEM_POPUP_SIZE);
1728 }
1729 off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE);
252b5132 1730
4a594fce 1731 off = unicode_to_bin (wrbfd, off, mi->text);
252b5132
RH
1732
1733 if (mi->popup != NULL)
1734 {
4a594fce 1735 off = res_to_bin_menuitems (wrbfd, off, mi->popup);
252b5132
RH
1736 }
1737 }
4a594fce 1738 return off;
252b5132
RH
1739}
1740
1741/* Convert menuex items to binary. */
1742
4a594fce
NC
1743static rc_uint_type
1744res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
252b5132 1745{
4a594fce
NC
1746 rc_uint_type off_delta = off;
1747 const rc_menuitem *mi;
252b5132
RH
1748
1749 for (mi = items; mi != NULL; mi = mi->next)
1750 {
4a594fce 1751 struct bin_menuitemex bmi;
252b5132
RH
1752 int flags;
1753
4a594fce 1754 off += (4 - ((off - off_delta) & 3)) & 3;
252b5132
RH
1755
1756 flags = 0;
1757 if (mi->next == NULL)
1758 flags |= 0x80;
1759 if (mi->popup != NULL)
1760 flags |= 1;
252b5132 1761
4a594fce
NC
1762 if (wrbfd)
1763 {
1764 windres_put_32 (wrbfd, bmi.type, mi->type);
1765 windres_put_32 (wrbfd, bmi.state, mi->state);
1766 windres_put_32 (wrbfd, bmi.id, mi->id);
1767 windres_put_16 (wrbfd, bmi.flags, flags);
1768 set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE);
1769 }
1770 off += BIN_MENUITEMEX_SIZE;
252b5132 1771
4a594fce 1772 off = unicode_to_bin (wrbfd, off, mi->text);
252b5132
RH
1773
1774 if (mi->popup != NULL)
1775 {
4a594fce 1776 bfd_byte help[4];
252b5132 1777
4a594fce 1778 off += (4 - ((off - off_delta) & 3)) & 3;
252b5132 1779
4a594fce 1780 if (wrbfd)
252b5132 1781 {
4a594fce
NC
1782 windres_put_32 (wrbfd, help, mi->help);
1783 set_windres_bfd_content (wrbfd, help, off, 4);
252b5132 1784 }
4a594fce
NC
1785 off += 4;
1786 off = res_to_bin_menuexitems (wrbfd, off, mi->popup);
252b5132
RH
1787 }
1788 }
4a594fce 1789 return off;
252b5132
RH
1790}
1791
1792/* Convert an rcdata resource to binary. This is also used to convert
4a594fce 1793 other information which happens to be stored in rc_rcdata_item lists
252b5132
RH
1794 to binary. */
1795
4a594fce
NC
1796static rc_uint_type
1797res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items)
252b5132 1798{
4a594fce 1799 const rc_rcdata_item *ri;
252b5132
RH
1800
1801 for (ri = items; ri != NULL; ri = ri->next)
1802 {
4a594fce 1803 rc_uint_type len;
252b5132
RH
1804 switch (ri->type)
1805 {
1806 default:
1807 abort ();
252b5132 1808 case RCDATA_WORD:
4a594fce 1809 len = 2;
252b5132 1810 break;
252b5132 1811 case RCDATA_DWORD:
4a594fce 1812 len = 4;
252b5132 1813 break;
252b5132 1814 case RCDATA_STRING:
4a594fce
NC
1815 len = ri->u.string.length;
1816 break;
1817 case RCDATA_WSTRING:
1818 len = ri->u.wstring.length * sizeof (unichar);
1819 break;
1820 case RCDATA_BUFFER:
1821 len = ri->u.buffer.length;
1822 break;
1823 }
1824 if (wrbfd)
1825 {
1826 bfd_byte h[4];
1827 bfd_byte *hp = &h[0];
1828 switch (ri->type)
1829 {
1830 case RCDATA_WORD:
1831 windres_put_16 (wrbfd, hp, ri->u.word);
1832 break;
1833 case RCDATA_DWORD:
1834 windres_put_32 (wrbfd, hp, ri->u.dword);
1835 break;
1836 case RCDATA_STRING:
1837 hp = (bfd_byte *) ri->u.string.s;
252b5132 1838 break;
252b5132
RH
1839 case RCDATA_WSTRING:
1840 {
4a594fce 1841 rc_uint_type i;
252b5132 1842
4a594fce 1843 hp = (bfd_byte *) reswr_alloc (len);
252b5132 1844 for (i = 0; i < ri->u.wstring.length; i++)
4a594fce 1845 windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]);
252b5132 1846 }
4a594fce 1847 break;
252b5132 1848 case RCDATA_BUFFER:
4a594fce 1849 hp = (bfd_byte *) ri->u.buffer.data;
252b5132
RH
1850 break;
1851 }
4a594fce 1852 set_windres_bfd_content (wrbfd, hp, off, len);
252b5132 1853 }
4a594fce
NC
1854 off += len;
1855 }
1856 return off;
252b5132
RH
1857}
1858
1859/* Convert a stringtable resource to binary. */
1860
4a594fce
NC
1861static rc_uint_type
1862res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off,
1863 const rc_stringtable *st)
252b5132 1864{
252b5132
RH
1865 int i;
1866
252b5132
RH
1867 for (i = 0; i < 16; i++)
1868 {
4a594fce 1869 rc_uint_type slen, length;
252b5132
RH
1870 unichar *s;
1871
4a594fce 1872 slen = (rc_uint_type) st->strings[i].length;
252b5132
RH
1873 s = st->strings[i].string;
1874
4a594fce
NC
1875 length = 2 + slen * 2;
1876 if (wrbfd)
1877 {
1878 bfd_byte *hp;
1879 rc_uint_type j;
252b5132 1880
4a594fce
NC
1881 hp = (bfd_byte *) reswr_alloc (length);
1882 windres_put_16 (wrbfd, hp, slen);
252b5132
RH
1883
1884 for (j = 0; j < slen; j++)
4a594fce
NC
1885 windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]);
1886 set_windres_bfd_content (wrbfd, hp, off, length);
252b5132 1887 }
4a594fce
NC
1888 off += length;
1889 }
1890 return off;
252b5132
RH
1891}
1892
1893/* Convert an ASCII string to a unicode binary string. This always
1894 returns exactly one bindata structure. */
1895
4a594fce
NC
1896static rc_uint_type
1897string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s)
252b5132 1898{
4a594fce 1899 rc_uint_type len;
252b5132 1900
4a594fce 1901 len = (rc_uint_type) strlen (s);
252b5132 1902
4a594fce
NC
1903 if (wrbfd)
1904 {
1905 rc_uint_type i;
1906 bfd_byte *hp;
252b5132 1907
4a594fce 1908 hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
252b5132 1909
4a594fce
NC
1910 for (i = 0; i < len; i++)
1911 windres_put_16 (wrbfd, hp + i * 2, s[i]);
1912 windres_put_16 (wrbfd, hp + i * 2, 0);
1913 set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar));
1914 }
1915 off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1916 return off;
252b5132
RH
1917}
1918
4a594fce
NC
1919static rc_uint_type
1920res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb)
252b5132 1921{
4a594fce
NC
1922 if (wrbfd)
1923 {
1924 struct bin_toolbar bt;
1925 windres_put_32 (wrbfd, bt.button_width, tb->button_width);
1926 windres_put_32 (wrbfd, bt.button_height, tb->button_height);
1927 windres_put_32 (wrbfd, bt.nitems, tb->nitems);
1928 set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE);
1929 if (tb->nitems > 0)
1930 {
1931 rc_toolbar_item *it;
1932 bfd_byte *ids;
1933 rc_uint_type i = 0;
252b5132 1934
4a594fce
NC
1935 ids = (bfd_byte *) reswr_alloc (tb->nitems * 4);
1936 it=tb->items;
1937 while(it != NULL)
1938 {
1939 windres_put_32 (wrbfd, ids + i, it->id.u.id);
1940 i += 4;
1941 it = it->next;
1942 }
1943 set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i);
1944 }
1945 }
1946 off += BIN_TOOLBAR_SIZE + tb->nitems * 4;
252b5132 1947
4a594fce
NC
1948 return off;
1949}
252b5132 1950
4a594fce 1951/* Convert a versioninfo resource to binary. */
252b5132 1952
4a594fce
NC
1953static rc_uint_type
1954res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off,
1955 const rc_versioninfo *versioninfo)
1956{
1957 rc_uint_type off_delta = off;
1958 rc_uint_type start;
1959 struct bin_versioninfo bvi;
1960 rc_ver_info *vi;
252b5132 1961
4a594fce
NC
1962 start = off;
1963 off += BIN_VERSIONINFO_SIZE;
1964 off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO");
1965 off += (4 - ((off - off_delta) & 3)) & 3;
252b5132
RH
1966
1967 if (versioninfo->fixed != NULL)
1968 {
4a594fce
NC
1969 if (wrbfd)
1970 {
1971 struct bin_fixed_versioninfo bfv;
1972 const rc_fixed_versioninfo *fi;
252b5132
RH
1973
1974 fi = versioninfo->fixed;
4a594fce
NC
1975 windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd);
1976 windres_put_32 (wrbfd, bfv.sig2, 0x10000);
1977 windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms);
1978 windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls);
1979 windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms);
1980 windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls);
1981 windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask);
1982 windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags);
1983 windres_put_32 (wrbfd, bfv.file_os, fi->file_os);
1984 windres_put_32 (wrbfd, bfv.file_type, fi->file_type);
1985 windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype);
1986 windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms);
1987 windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls);
1988 set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE);
1989 }
1990 off += BIN_FIXED_VERSIONINFO_SIZE;
252b5132
RH
1991 }
1992
1993 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
1994 {
4a594fce
NC
1995 struct bin_ver_info bv;
1996 rc_uint_type bv_off;
252b5132 1997
4a594fce 1998 off += (4 - ((off - off_delta) & 3)) & 3;
252b5132 1999
4a594fce 2000 bv_off = off;
252b5132 2001
4a594fce 2002 off += BIN_VER_INFO_SIZE;
252b5132
RH
2003
2004 switch (vi->type)
2005 {
2006 default:
2007 abort ();
252b5132
RH
2008 case VERINFO_STRING:
2009 {
4a594fce
NC
2010 struct bin_ver_info bvsd;
2011 rc_uint_type vs_off;
2012 const rc_ver_stringinfo *vs;
252b5132 2013
4a594fce
NC
2014 off = string_to_unicode_bin (wrbfd, off, "StringFileInfo");
2015 off += (4 - ((off - off_delta) & 3)) & 3;
252b5132 2016
4a594fce 2017 vs_off = off;
252b5132 2018
4a594fce 2019 off += BIN_VER_INFO_SIZE;
252b5132 2020
4a594fce 2021 off = unicode_to_bin (wrbfd, off, vi->u.string.language);
252b5132 2022
4a594fce
NC
2023 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2024 {
2025 struct bin_ver_info bvss;
2026 rc_uint_type vss_off,str_off;
252b5132 2027
4a594fce 2028 off += (4 - ((off - off_delta) & 3)) & 3;
252b5132 2029
4a594fce
NC
2030 vss_off = off;
2031 off += BIN_VER_INFO_SIZE;
252b5132 2032
4a594fce 2033 off = unicode_to_bin (wrbfd, off, vs->key);
252b5132 2034
4a594fce 2035 off += (4 - ((off - off_delta) & 3)) & 3;
252b5132 2036
4a594fce
NC
2037 str_off = off;
2038 off = unicode_to_bin (wrbfd, off, vs->value);
2039 if (wrbfd)
2040 {
2041 windres_put_16 (wrbfd, bvss.size, off - vss_off);
2042 windres_put_16 (wrbfd, bvss.sig1, (off - str_off) / 2);
2043 windres_put_16 (wrbfd, bvss.sig2, 1);
2044 set_windres_bfd_content (wrbfd, &bvss, vss_off,
2045 BIN_VER_INFO_SIZE);
2046 }
2047 }
2048 if (wrbfd)
2049 {
2050 windres_put_16 (wrbfd, bvsd.size, off - vs_off);
2051 windres_put_16 (wrbfd, bvsd.sig1, 0);
2052 windres_put_16 (wrbfd, bvsd.sig2, 0);
2053 set_windres_bfd_content (wrbfd, &bvsd, vs_off,
2054 BIN_VER_INFO_SIZE);
2055 }
252b5132
RH
2056 break;
2057 }
2058
2059 case VERINFO_VAR:
2060 {
4a594fce
NC
2061 rc_uint_type vvd_off, vvvd_off;
2062 struct bin_ver_info bvvd;
2063 const rc_ver_varinfo *vv;
252b5132 2064
4a594fce 2065 off = string_to_unicode_bin (wrbfd, off, "VarFileInfo");
252b5132 2066
4a594fce 2067 off += (4 - ((off - off_delta) & 3)) & 3;
252b5132 2068
4a594fce
NC
2069 vvd_off = off;
2070 off += BIN_VER_INFO_SIZE;
252b5132 2071
4a594fce 2072 off = unicode_to_bin (wrbfd, off, vi->u.var.key);
252b5132 2073
4a594fce 2074 off += (4 - ((off - off_delta) & 3)) & 3;
252b5132 2075
4a594fce 2076 vvvd_off = off;
252b5132
RH
2077
2078 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2079 {
4a594fce
NC
2080 if (wrbfd)
2081 {
2082 bfd_byte vvsd[4];
2083
2084 windres_put_16 (wrbfd, &vvsd[0], vv->language);
2085 windres_put_16 (wrbfd, &vvsd[2], vv->charset);
2086 set_windres_bfd_content (wrbfd, vvsd, off, 4);
2087 }
2088 off += 4;
252b5132 2089 }
4a594fce
NC
2090 if (wrbfd)
2091 {
2092 windres_put_16 (wrbfd, bvvd.size, off - vvd_off);
2093 windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off);
2094 windres_put_16 (wrbfd, bvvd.sig2, 0);
2095 set_windres_bfd_content (wrbfd, &bvvd, vvd_off,
2096 BIN_VER_INFO_SIZE);
2097 }
252b5132
RH
2098
2099 break;
2100 }
2101 }
2102
4a594fce
NC
2103 if (wrbfd)
2104 {
2105 windres_put_16 (wrbfd, bv.size, off-bv_off);
2106 windres_put_16 (wrbfd, bv.sig1, 0);
2107 windres_put_16 (wrbfd, bv.sig2, 0);
2108 set_windres_bfd_content (wrbfd, &bv, bv_off,
2109 BIN_VER_INFO_SIZE);
2110 }
252b5132
RH
2111 }
2112
4a594fce
NC
2113 if (wrbfd)
2114 {
2115 windres_put_16 (wrbfd, bvi.size, off - start);
2116 windres_put_16 (wrbfd, bvi.fixed_size,
2117 versioninfo->fixed == NULL ? 0
2118 : BIN_FIXED_VERSIONINFO_SIZE);
2119 windres_put_16 (wrbfd, bvi.sig2, 0);
2120 set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE);
2121 }
2122 return off;
252b5132
RH
2123}
2124
2125/* Convert a generic resource to binary. */
2126
4a594fce
NC
2127static rc_uint_type
2128res_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length,
2129 const bfd_byte *data)
252b5132 2130{
4a594fce
NC
2131 if (wrbfd && length != 0)
2132 set_windres_bfd_content (wrbfd, data, off, length);
2133 return off + (rc_uint_type) length;
252b5132 2134}
This page took 0.455018 seconds and 4 git commands to generate.