1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright (C) 1997-2015 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support.
4 Rewritten by Kai Tietz, Onevision.
6 This file is part of GNU Binutils.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
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. */
31 #include "libiberty.h"
34 /* Local functions. */
36 static void toosmall (const char *);
38 static unichar *get_unicode (windres_bfd *, const bfd_byte *, rc_uint_type, rc_uint_type *);
39 static int get_resid (windres_bfd *, rc_res_id *, const bfd_byte *, rc_uint_type);
40 static rc_res_resource *bin_to_res_generic (windres_bfd *, enum rc_res_type,
41 const bfd_byte *, rc_uint_type);
42 static rc_res_resource *bin_to_res_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
43 static rc_res_resource *bin_to_res_menu (windres_bfd *,const bfd_byte *, rc_uint_type);
44 static rc_menuitem *bin_to_res_menuitems (windres_bfd *, const bfd_byte *, rc_uint_type,
46 static rc_menuitem *bin_to_res_menuexitems (windres_bfd *, const bfd_byte *, rc_uint_type,
48 static rc_res_resource *bin_to_res_dialog (windres_bfd *, const bfd_byte *, rc_uint_type);
49 static rc_res_resource *bin_to_res_string (windres_bfd *,const bfd_byte *, rc_uint_type);
50 static rc_res_resource *bin_to_res_fontdir (windres_bfd *, const bfd_byte *, rc_uint_type);
51 static rc_res_resource *bin_to_res_accelerators (windres_bfd *, const bfd_byte *, rc_uint_type);
52 static rc_res_resource *bin_to_res_rcdata (windres_bfd *, const bfd_byte *, rc_uint_type, int);
53 static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
54 static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type);
55 static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type);
56 static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type);
57 static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type);
58 static 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 *,
62 /* Given a resource type ID, a pointer to data, a length, return a
63 rc_res_resource structure which represents that resource. The caller
64 is responsible for initializing the res_info and coff_info fields
65 of the returned structure. */
68 bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data,
72 return bin_to_res_userdata (wrbfd, data, length);
78 return bin_to_res_userdata (wrbfd, data, length);
80 return bin_to_res_cursor (wrbfd, data, length);
82 return bin_to_res_generic (wrbfd, RES_TYPE_BITMAP, data, length);
84 return bin_to_res_generic (wrbfd, RES_TYPE_ICON, data, length);
86 return bin_to_res_menu (wrbfd, data, length);
88 return bin_to_res_dialog (wrbfd, data, length);
90 return bin_to_res_string (wrbfd, data, length);
92 return bin_to_res_fontdir (wrbfd, data, length);
94 return bin_to_res_generic (wrbfd, RES_TYPE_FONT, data, length);
96 return bin_to_res_accelerators (wrbfd, data, length);
98 return bin_to_res_rcdata (wrbfd, data, length, RES_TYPE_RCDATA);
100 return bin_to_res_generic (wrbfd, RES_TYPE_MESSAGETABLE, data, length);
101 case RT_GROUP_CURSOR:
102 return bin_to_res_group_cursor (wrbfd, data, length);
104 return bin_to_res_group_icon (wrbfd, data, length);
106 return bin_to_res_version (wrbfd, data, length);
108 return bin_to_res_toolbar (wrbfd, data, length);
114 /* Give an error if the binary data is too small. */
117 toosmall (const char *msg)
119 fatal (_("%s: not enough binary data"), msg);
122 /* Swap in a NULL terminated unicode string. */
125 get_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
126 rc_uint_type *retlen)
134 if (length < c * 2 + 2)
135 toosmall (_("null terminated unicode string"));
136 if (windres_get_16 (wrbfd, data + c * 2, 2) == 0)
141 ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
143 for (i = 0; i < c; i++)
144 ret[i] = windres_get_16 (wrbfd, data + i * 2, 2);
153 /* Get a resource identifier. This returns the number of bytes used. */
156 get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data,
162 toosmall (_("resource ID"));
164 first = windres_get_16 (wrbfd, data, 2);
168 toosmall (_("resource ID"));
170 id->u.id = windres_get_16 (wrbfd, data + 2, 2);
176 id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length);
177 return id->u.n.length * 2 + 2;
181 /* Convert a resource which just stores uninterpreted data from
185 bin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type,
186 const bfd_byte *data, rc_uint_type length)
190 r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
192 r->u.data.data = data;
193 r->u.data.length = length;
198 /* Convert a cursor resource from binary. */
201 bin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
207 toosmall (_("cursor"));
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);
212 c->length = length - 4;
215 r = (rc_res_resource *) res_alloc (sizeof *r);
216 r->type = RES_TYPE_CURSOR;
222 /* Convert a menu resource from binary. */
225 bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
229 rc_uint_type version, got;
231 r = (rc_res_resource *) res_alloc (sizeof *r);
232 r->type = RES_TYPE_MENU;
234 m = (rc_menu *) res_alloc (sizeof (rc_menu));
238 toosmall (_("menu header"));
240 version = windres_get_16 (wrbfd, data, 2);
245 toosmall (_("menu header"));
247 m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &got);
249 else if (version == 1)
254 toosmall (_("menuex header"));
255 m->help = windres_get_32 (wrbfd, data + 4, 4);
256 offset = windres_get_16 (wrbfd, data + 2, 2);
257 if (offset + 4 >= length)
258 toosmall (_("menuex offset"));
259 m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset,
260 length - (4 + offset), &got);
263 fatal (_("unsupported menu version %d"), (int) version);
268 /* Convert menu items from binary. */
271 bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
274 rc_menuitem *first, **pp;
283 rc_uint_type flags, slen, itemlen;
288 toosmall (_("menuitem header"));
290 mi = (rc_menuitem *) res_alloc (sizeof *mi);
294 flags = windres_get_16 (wrbfd, data, 2);
295 mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
297 if ((flags & MENUITEM_POPUP) == 0)
302 if (length < stroff + 2)
303 toosmall (_("menuitem header"));
305 if (windres_get_16 (wrbfd, data + stroff, 2) == 0)
311 mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen);
313 itemlen = stroff + slen * 2 + 2;
315 if ((flags & MENUITEM_POPUP) == 0)
318 mi->id = windres_get_16 (wrbfd, data + 2, 2);
322 rc_uint_type subread;
325 mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen,
338 if ((flags & MENUITEM_ENDMENU) != 0)
345 /* Convert menuex items from binary. */
348 bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
351 rc_menuitem *first, **pp;
360 rc_uint_type flags, slen;
361 rc_uint_type itemlen;
365 toosmall (_("menuitem header"));
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);
372 flags = windres_get_16 (wrbfd, data + 12, 2);
374 if (windres_get_16 (wrbfd, data + 14, 2) == 0)
380 mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen);
382 itemlen = 14 + slen * 2 + 2;
383 itemlen = (itemlen + 3) &~ 3;
385 if ((flags & 1) == 0)
392 rc_uint_type subread;
394 if (length < itemlen + 4)
395 toosmall (_("menuitem"));
396 mi->help = windres_get_32 (wrbfd, data + itemlen, 4);
399 mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen,
400 length - itemlen, &subread);
412 if ((flags & 0x80) != 0)
419 /* Convert a dialog resource from binary. */
421 static rc_res_resource *
422 bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
424 rc_uint_type signature;
426 rc_uint_type c, sublen, i;
428 rc_dialog_control **pp;
432 toosmall (_("dialog header"));
434 d = (rc_dialog *) res_alloc (sizeof (rc_dialog));
436 signature = windres_get_16 (wrbfd, data + 2, 2);
437 if (signature != 0xffff)
440 d->style = windres_get_32 (wrbfd, data, 4);
441 d->exstyle = windres_get_32 (wrbfd, data + 4, 4);
448 version = windres_get_16 (wrbfd, data, 2);
450 fatal (_("unexpected DIALOGEX version %d"), version);
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);
459 if (length < off + 10)
460 toosmall (_("dialog header"));
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);
470 sublen = get_resid (wrbfd, &d->menu, data + off, length - off);
473 sublen = get_resid (wrbfd, &d->class, data + off, length - off);
476 d->caption = get_unicode (wrbfd, data + off, length - off, &sublen);
477 off += sublen * 2 + 2;
481 if ((d->style & DS_SETFONT) == 0)
489 d->ex->charset = 1; /* Default charset. */
494 if (length < off + 2)
495 toosmall (_("dialog font point size"));
497 d->pointsize = windres_get_16 (wrbfd, data + off, 2);
502 if (length < off + 4)
503 toosmall (_("dialogex font information"));
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);
510 d->font = get_unicode (wrbfd, data + off, length - off, &sublen);
511 off += sublen * 2 + 2;
517 for (i = 0; i < c; i++)
519 rc_dialog_control *dc;
522 off = (off + 3) &~ 3;
524 dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
528 if (length < off + 8)
529 toosmall (_("dialog control"));
531 dc->style = windres_get_32 (wrbfd, data + off, 4);
532 dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
538 if (length < off + 12)
539 toosmall (_("dialogex control"));
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);
546 if (length < off + (d->ex != NULL ? 2 : 0) + 10)
547 toosmall (_("dialog control"));
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);
555 dc->id = windres_get_32 (wrbfd, data + off + 8, 4);
557 dc->id = windres_get_16 (wrbfd, data + off + 8, 2);
559 off += 10 + (d->ex != NULL ? 2 : 0);
561 sublen = get_resid (wrbfd, &dc->class, data + off, length - off);
564 sublen = get_resid (wrbfd, &dc->text, data + off, length - off);
567 if (length < off + 2)
568 toosmall (_("dialog control end"));
570 datalen = windres_get_16 (wrbfd, data + off, 2);
577 off = (off + 3) &~ 3;
579 if (length < off + datalen)
580 toosmall (_("dialog control data"));
582 dc->data = ((rc_rcdata_item *)
583 res_alloc (sizeof (rc_rcdata_item)));
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;
597 r = (rc_res_resource *) res_alloc (sizeof *r);
598 r->type = RES_TYPE_DIALOG;
604 /* Convert a stringtable resource from binary. */
606 static rc_res_resource *
607 bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
613 st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable));
615 for (i = 0; i < 16; i++)
620 toosmall (_("stringtable string length"));
621 slen = windres_get_16 (wrbfd, data, 2);
622 st->strings[i].length = slen;
629 if (length < 2 + 2 * slen)
630 toosmall (_("stringtable string"));
632 s = (unichar *) res_alloc (slen * sizeof (unichar));
633 st->strings[i].string = s;
635 for (j = 0; j < slen; j++)
636 s[j] = windres_get_16 (wrbfd, data + 2 + j * 2, 2);
639 data += 2 + 2 * slen;
640 length -= 2 + 2 * slen;
643 r = (rc_res_resource *) res_alloc (sizeof *r);
644 r->type = RES_TYPE_STRINGTABLE;
645 r->u.stringtable = st;
650 /* Convert a fontdir resource from binary. */
652 static rc_res_resource *
653 bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
656 rc_fontdir *first, **pp;
660 toosmall (_("fontdir header"));
662 c = windres_get_16 (wrbfd, data, 2);
667 for (i = 0; i < c; i++)
669 const struct bin_fontdir_item *bfi;
674 toosmall (_("fontdir"));
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);
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
682 we don't store them in the rc_fontdir. The
683 documentation says that these are NULL terminated char
684 strings, not Unicode strings. */
688 while (off < length && data[off] != '\0')
691 toosmall (_("fontdir device name"));
694 while (off < length && data[off] != '\0')
697 toosmall (_("fontdir face name"));
707 /* The documentation does not indicate that any rounding is
714 r = (rc_res_resource *) res_alloc (sizeof *r);
715 r->type = RES_TYPE_FONTDIR;
716 r->u.fontdir = first;
721 /* Convert an accelerators resource from binary. */
723 static rc_res_resource *
724 bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
726 rc_accelerator *first, **pp;
737 toosmall (_("accelerator"));
739 a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator));
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);
749 if ((a->flags & ACC_LAST) != 0)
756 r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
757 r->type = RES_TYPE_ACCELERATOR;
763 /* Convert an rcdata resource from binary. */
765 static rc_res_resource *
766 bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
767 rc_uint_type length, int rctyp)
772 ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
775 ri->type = RCDATA_BUFFER;
776 ri->u.buffer.length = length;
777 ri->u.buffer.data = data;
779 r = (rc_res_resource *) res_alloc (sizeof *r);
786 /* Convert a group cursor resource from binary. */
788 static rc_res_resource *
789 bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
792 rc_group_cursor *first, **pp;
796 toosmall (_("group cursor header"));
798 type = windres_get_16 (wrbfd, data + 2, 2);
800 fatal (_("unexpected group cursor type %d"), type);
802 c = windres_get_16 (wrbfd, data + 4, 2);
810 for (i = 0; i < c; i++)
815 toosmall (_("group cursor"));
817 gc = (rc_group_cursor *) res_alloc (sizeof *gc);
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);
834 r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
835 r->type = RES_TYPE_GROUP_CURSOR;
836 r->u.group_cursor = first;
841 /* Convert a group icon resource from binary. */
843 static rc_res_resource *
844 bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
847 rc_group_icon *first, **pp;
851 toosmall (_("group icon header"));
853 type = windres_get_16 (wrbfd, data + 2, 2);
855 fatal (_("unexpected group icon type %d"), type);
857 c = windres_get_16 (wrbfd, data + 4, 2);
865 for (i = 0; i < c; i++)
870 toosmall (_("group icon"));
872 gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
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);
890 r = (rc_res_resource *) res_alloc (sizeof *r);
891 r->type = RES_TYPE_GROUP_ICON;
892 r->u.group_icon = first;
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. */
903 get_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,
911 *len = (windres_get_16 (wrbfd, data, 2) + 3) & ~3;
912 *vallen = windres_get_16 (wrbfd, data + 2, 2);
913 *type = windres_get_16 (wrbfd, data + 4, 2);
924 *pkey = get_unicode (wrbfd, data, length, &sublen);
925 *off += (sublen + 1) * sizeof (unichar);
933 if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key)
934 fatal (_("unexpected version string"));
947 *off = (*off + 3) &~ 3;
950 /* Convert a version resource from binary. */
952 static rc_res_resource *
953 bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
955 rc_uint_type verlen, vallen, type, off;
956 rc_fixed_versioninfo *fi;
957 rc_ver_info *first, **pp;
961 get_version_header (wrbfd, data, length, "VS_VERSION_INFO",
962 (unichar **) NULL, &verlen, &vallen, &type, &off);
964 if ((unsigned int) verlen != length)
965 fatal (_("version length %d does not match resource length %lu"),
966 (int) verlen, (unsigned long) length);
969 fatal (_("unexpected version type %d"), (int) type);
978 unsigned long signature, fiv;
981 fatal (_("unexpected fixed version information length %ld"), (long) vallen);
984 toosmall (_("fixed version info"));
986 signature = windres_get_32 (wrbfd, data, 4);
987 if (signature != 0xfeef04bd)
988 fatal (_("unexpected fixed version signature %lu"), signature);
990 fiv = windres_get_32 (wrbfd, data + 4, 4);
991 if (fiv != 0 && fiv != 0x10000)
992 fatal (_("unexpected fixed version info version %lu"), fiv);
994 fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo));
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);
1021 toosmall (_("version var info"));
1023 vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
1025 ch = windres_get_16 (wrbfd, data + 6, 2);
1029 rc_ver_stringtable **ppvst;
1031 vi->type = VERINFO_STRING;
1033 get_version_header (wrbfd, data, length, "StringFileInfo",
1034 (unichar **) NULL, &verlen, &vallen, &type,
1038 fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen);
1045 vi->u.string.stringtables = NULL;
1046 ppvst = &vi->u.string.stringtables;
1050 rc_ver_stringtable *vst;
1051 rc_uint_type stverlen;
1052 rc_ver_stringinfo **ppvs;
1055 toosmall (_("version stringtable"));
1057 vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable));
1059 get_version_header (wrbfd, data, length, (const char *) NULL,
1060 &vst->language, &stverlen, &vallen, &type, &off);
1063 fatal (_("unexpected version stringtable value length %ld"), (long) vallen);
1071 vst->strings = NULL;
1072 ppvs = &vst->strings;
1074 while (stverlen > 0)
1076 rc_ver_stringinfo *vs;
1077 rc_uint_type sverlen, vslen, valoff;
1080 toosmall (_("version string"));
1082 vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo));
1084 get_version_header (wrbfd, data, length, (const char *) NULL,
1085 &vs->key, &sverlen, &vallen, &type, &off);
1090 vs->value = get_unicode (wrbfd, data, length, &vslen);
1091 valoff = vslen * 2 + 2;
1092 valoff = (valoff + 3) & ~3;
1094 if (off + valoff != sverlen)
1095 fatal (_("unexpected version string length %ld != %ld + %ld"),
1096 (long) sverlen, (long) off, (long) valoff);
1101 if (stverlen < sverlen)
1102 fatal (_("unexpected version string length %ld < %ld"),
1103 (long) verlen, (long) sverlen);
1104 stverlen -= sverlen;
1119 rc_ver_varinfo **ppvv;
1121 vi->type = VERINFO_VAR;
1123 get_version_header (wrbfd, data, length, "VarFileInfo",
1124 (unichar **) NULL, &verlen, &vallen, &type,
1128 fatal (_("unexpected varfileinfo value length %ld"), (long) vallen);
1133 get_version_header (wrbfd, data, length, (const char *) NULL,
1134 &vi->u.var.key, &verlen, &vallen, &type, &off);
1139 vi->u.var.var = NULL;
1140 ppvv = &vi->u.var.var;
1147 toosmall (_("version varfileinfo"));
1149 vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
1151 vv->language = windres_get_16 (wrbfd, data, 2);
1152 vv->charset = windres_get_16 (wrbfd, data + 2, 2);
1162 fatal (_("unexpected version value length %ld"), (long) vallen);
1168 fatal (_("unexpected version string"));
1175 v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo));
1179 r = (rc_res_resource *) res_alloc (sizeof *r);
1180 r->type = RES_TYPE_VERSIONINFO;
1181 r->u.versioninfo = v;
1186 /* Convert an arbitrary user defined resource from binary. */
1188 static rc_res_resource *
1189 bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
1190 rc_uint_type length)
1195 ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1198 ri->type = RCDATA_BUFFER;
1199 ri->u.buffer.length = length;
1200 ri->u.buffer.data = data;
1202 r = (rc_res_resource *) res_alloc (sizeof *r);
1203 r->type = RES_TYPE_USERDATA;
1209 static rc_res_resource *
1210 bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
1216 ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
1217 ri->button_width = windres_get_32 (wrbfd, data, 4);
1218 ri->button_height = windres_get_32 (wrbfd, data + 4, 4);
1219 ri->nitems = windres_get_32 (wrbfd, data + 8, 4);
1224 for (i=0 ; i < ri->nitems; i++)
1226 rc_toolbar_item *it;
1227 it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item));
1229 it->id.u.id = (int) windres_get_32 (wrbfd, data, 4);
1230 it->prev = it->next = NULL;
1234 rc_toolbar_item *ii = ri->items;
1235 while (ii->next != NULL)
1243 r = (rc_res_resource *) res_alloc (sizeof *r);
1244 r->type = RES_TYPE_TOOLBAR;
1250 /* Local functions used to convert resources to binary format. */
1252 static rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id);
1253 static rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *);
1254 static rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *);
1255 static rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *);
1256 static rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *);
1257 static rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *);
1258 static rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *);
1259 static rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *);
1260 static rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *);
1261 static rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
1262 static rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
1263 static rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *);
1264 static rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *);
1265 static rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *);
1266 static rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb);
1267 static rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *);
1268 static rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type,
1271 /* Convert a resource to binary. */
1274 res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res)
1278 case RES_TYPE_BITMAP:
1281 case RES_TYPE_MESSAGETABLE:
1282 return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data);
1283 case RES_TYPE_ACCELERATOR:
1284 return res_to_bin_accelerator (wrbfd, off, res->u.acc);
1285 case RES_TYPE_CURSOR:
1286 return res_to_bin_cursor (wrbfd, off, res->u.cursor);
1287 case RES_TYPE_GROUP_CURSOR:
1288 return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor);
1289 case RES_TYPE_DIALOG:
1290 return res_to_bin_dialog (wrbfd, off, res->u.dialog);
1291 case RES_TYPE_FONTDIR:
1292 return res_to_bin_fontdir (wrbfd, off, res->u.fontdir);
1293 case RES_TYPE_GROUP_ICON:
1294 return res_to_bin_group_icon (wrbfd, off, res->u.group_icon);
1296 return res_to_bin_menu (wrbfd, off, res->u.menu);
1297 case RES_TYPE_STRINGTABLE:
1298 return res_to_bin_stringtable (wrbfd, off, res->u.stringtable);
1299 case RES_TYPE_VERSIONINFO:
1300 return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo);
1301 case RES_TYPE_TOOLBAR:
1302 return res_to_bin_toolbar (wrbfd, off, res->u.toolbar);
1303 case RES_TYPE_USERDATA:
1304 case RES_TYPE_RCDATA:
1306 return res_to_bin_rcdata (wrbfd, off, res->u.rcdata);
1310 /* Convert a resource ID to binary. This always returns exactly one
1311 bindata structure. */
1314 resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id)
1320 struct bin_res_id bri;
1322 windres_put_16 (wrbfd, bri.sig, 0xffff);
1323 windres_put_16 (wrbfd, bri.id, id.u.id);
1324 set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID);
1330 rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0);
1333 bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
1335 for (i = 0; i < len; i++)
1336 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]);
1337 windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
1338 set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
1340 off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1345 /* Convert a null terminated unicode string to binary. This always
1346 returns exactly one bindata structure. */
1349 unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str)
1351 rc_uint_type len = 0;
1354 len = unichar_len (str);
1360 d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar));
1361 for (i = 0; i < len; i++)
1362 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]);
1363 windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
1364 set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
1366 off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1371 /* Convert an accelerator resource to binary. */
1374 res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off,
1375 const rc_accelerator *accelerators)
1377 const rc_accelerator *a;
1379 for (a = accelerators; a != NULL; a = a->next)
1383 struct bin_accelerator ba;
1385 windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST));
1386 windres_put_16 (wrbfd, ba.key, a->key);
1387 windres_put_16 (wrbfd, ba.id, a->id);
1388 windres_put_16 (wrbfd, ba.pad, 0);
1389 set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE);
1391 off += BIN_ACCELERATOR_SIZE;
1396 /* Convert a cursor resource to binary. */
1399 res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c)
1403 struct bin_cursor bc;
1405 windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot);
1406 windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot);
1407 set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE);
1409 set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length);
1411 off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length);
1415 /* Convert a group cursor resource to binary. */
1418 res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off,
1419 const rc_group_cursor *group_cursors)
1422 const rc_group_cursor *gc;
1423 struct bin_group_cursor bgc;
1424 struct bin_group_cursor_item bgci;
1425 rc_uint_type start = off;
1427 off += BIN_GROUP_CURSOR_SIZE;
1429 for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++)
1433 windres_put_16 (wrbfd, bgci.width, gc->width);
1434 windres_put_16 (wrbfd, bgci.height, gc->height);
1435 windres_put_16 (wrbfd, bgci.planes, gc->planes);
1436 windres_put_16 (wrbfd, bgci.bits, gc->bits);
1437 windres_put_32 (wrbfd, bgci.bytes, gc->bytes);
1438 windres_put_16 (wrbfd, bgci.index, gc->index);
1439 set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE);
1442 off += BIN_GROUP_CURSOR_ITEM_SIZE;
1446 windres_put_16 (wrbfd, bgc.sig1, 0);
1447 windres_put_16 (wrbfd, bgc.sig2, 2);
1448 windres_put_16 (wrbfd, bgc.nitems, c);
1449 set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE);
1454 /* Convert a dialog resource to binary. */
1457 res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog)
1459 rc_uint_type off_delta;
1460 rc_uint_type start, marker;
1463 rc_dialog_control *dc;
1464 struct bin_dialogex bdx;
1465 struct bin_dialog bd;
1469 dialogex = extended_dialog (dialog);
1475 windres_put_32 (wrbfd, bd.style, dialog->style);
1476 windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle);
1477 windres_put_16 (wrbfd, bd.x, dialog->x);
1478 windres_put_16 (wrbfd, bd.y, dialog->y);
1479 windres_put_16 (wrbfd, bd.width, dialog->width);
1480 windres_put_16 (wrbfd, bd.height, dialog->height);
1484 windres_put_16 (wrbfd, bdx.sig1, 1);
1485 windres_put_16 (wrbfd, bdx.sig2, 0xffff);
1486 windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0));
1487 windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle);
1488 windres_put_32 (wrbfd, bdx.style, dialog->style);
1489 windres_put_16 (wrbfd, bdx.x, dialog->x);
1490 windres_put_16 (wrbfd, bdx.y, dialog->y);
1491 windres_put_16 (wrbfd, bdx.width, dialog->width);
1492 windres_put_16 (wrbfd, bdx.height, dialog->height);
1496 off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE);
1498 off = resid_to_bin (wrbfd, off, dialog->menu);
1499 off = resid_to_bin (wrbfd, off, dialog->class);
1500 off = unicode_to_bin (wrbfd, off, dialog->caption);
1502 if ((dialog->style & DS_SETFONT) != 0)
1508 struct bin_dialogfont bdf;
1509 windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize);
1510 set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE);
1514 struct bin_dialogexfont bdxf;
1515 windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize);
1516 windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight));
1517 windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic));
1518 windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset));
1519 set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE);
1522 off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE);
1523 off = unicode_to_bin (wrbfd, off, dialog->font);
1525 for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++)
1527 bfd_byte dc_rclen[2];
1529 off += (4 - ((off - off_delta) & 3)) & 3;
1534 struct bin_dialog_control bdc;
1536 windres_put_32 (wrbfd, bdc.style, dc->style);
1537 windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
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_16 (wrbfd, bdc.id, dc->id);
1543 set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE);
1547 struct bin_dialogex_control bdc;
1549 windres_put_32 (wrbfd, bdc.help, dc->help);
1550 windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
1551 windres_put_32 (wrbfd, bdc.style, dc->style);
1552 windres_put_16 (wrbfd, bdc.x, dc->x);
1553 windres_put_16 (wrbfd, bdc.y, dc->y);
1554 windres_put_16 (wrbfd, bdc.width, dc->width);
1555 windres_put_16 (wrbfd, bdc.height, dc->height);
1556 windres_put_32 (wrbfd, bdc.id, dc->id);
1557 set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE);
1560 off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE);
1562 off = resid_to_bin (wrbfd, off, dc->class);
1563 off = resid_to_bin (wrbfd, off, dc->text);
1565 marker = off; /* Save two bytes for size of optional data. */
1568 if (dc->data == NULL)
1571 windres_put_16 (wrbfd, dc_rclen, 0);
1575 rc_uint_type saved_off = off;
1576 rc_uint_type old_off;
1577 off += (4 - ((off - off_delta) & 3)) & 3;
1580 off = res_to_bin_rcdata (wrbfd, off, dc->data);
1581 if ((off - old_off) == 0)
1582 old_off = off = saved_off;
1584 windres_put_16 (wrbfd, dc_rclen, off - old_off);
1587 set_windres_bfd_content (wrbfd, dc_rclen, marker, 2);
1592 windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c);
1594 set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE);
1596 set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE);
1602 /* Convert a fontdir resource to binary. */
1604 res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs)
1608 const rc_fontdir *fd;
1613 for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++)
1618 windres_put_16 (wrbfd, d, fd->index);
1619 set_windres_bfd_content (wrbfd, d, off, 2);
1621 set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length);
1623 off += (rc_uint_type) fd->length + 2;
1629 windres_put_16 (wrbfd, d, c);
1630 set_windres_bfd_content (wrbfd, d, start, 2);
1635 /* Convert a group icon resource to binary. */
1638 res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons)
1641 struct bin_group_icon bgi;
1643 const rc_group_icon *gi;
1646 off += BIN_GROUP_ICON_SIZE;
1648 for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++)
1650 struct bin_group_icon_item bgii;
1654 windres_put_8 (wrbfd, bgii.width, gi->width);
1655 windres_put_8 (wrbfd, bgii.height, gi->height);
1656 windres_put_8 (wrbfd, bgii.colors, gi->colors);
1657 windres_put_8 (wrbfd, bgii.pad, 0);
1658 windres_put_16 (wrbfd, bgii.planes, gi->planes);
1659 windres_put_16 (wrbfd, bgii.bits, gi->bits);
1660 windres_put_32 (wrbfd, bgii.bytes, gi->bytes);
1661 windres_put_16 (wrbfd, bgii.index, gi->index);
1662 set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE);
1664 off += BIN_GROUP_ICON_ITEM_SIZE;
1669 windres_put_16 (wrbfd, bgi.sig1, 0);
1670 windres_put_16 (wrbfd, bgi.sig2, 1);
1671 windres_put_16 (wrbfd, bgi.count, c);
1672 set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE);
1677 /* Convert a menu resource to binary. */
1680 res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu)
1684 menuex = extended_menu (menu);
1691 windres_put_16 (wrbfd, bm.sig1, 0);
1692 windres_put_16 (wrbfd, bm.sig2, 0);
1693 set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE);
1697 struct bin_menuex bm;
1698 windres_put_16 (wrbfd, bm.sig1, 1);
1699 windres_put_16 (wrbfd, bm.sig2, 4);
1700 windres_put_32 (wrbfd, bm.help, menu->help);
1701 set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE);
1704 off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE);
1707 off = res_to_bin_menuitems (wrbfd, off, menu->items);
1711 off = res_to_bin_menuexitems (wrbfd, off, menu->items);
1716 /* Convert menu items to binary. */
1719 res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
1721 const rc_menuitem *mi;
1723 for (mi = items; mi != NULL; mi = mi->next)
1725 struct bin_menuitem bmi;
1729 if (mi->next == NULL)
1730 flags |= MENUITEM_ENDMENU;
1731 if (mi->popup != NULL)
1732 flags |= MENUITEM_POPUP;
1736 windres_put_16 (wrbfd, bmi.flags, flags);
1737 if (mi->popup == NULL)
1738 windres_put_16 (wrbfd, bmi.id, mi->id);
1739 set_windres_bfd_content (wrbfd, &bmi, off,
1740 mi->popup == NULL ? BIN_MENUITEM_SIZE
1741 : BIN_MENUITEM_POPUP_SIZE);
1743 off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE);
1745 off = unicode_to_bin (wrbfd, off, mi->text);
1747 if (mi->popup != NULL)
1749 off = res_to_bin_menuitems (wrbfd, off, mi->popup);
1755 /* Convert menuex items to binary. */
1758 res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
1760 rc_uint_type off_delta = off;
1761 const rc_menuitem *mi;
1763 for (mi = items; mi != NULL; mi = mi->next)
1765 struct bin_menuitemex bmi;
1768 off += (4 - ((off - off_delta) & 3)) & 3;
1771 if (mi->next == NULL)
1773 if (mi->popup != NULL)
1778 windres_put_32 (wrbfd, bmi.type, mi->type);
1779 windres_put_32 (wrbfd, bmi.state, mi->state);
1780 windres_put_32 (wrbfd, bmi.id, mi->id);
1781 windres_put_16 (wrbfd, bmi.flags, flags);
1782 set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE);
1784 off += BIN_MENUITEMEX_SIZE;
1786 off = unicode_to_bin (wrbfd, off, mi->text);
1788 if (mi->popup != NULL)
1792 off += (4 - ((off - off_delta) & 3)) & 3;
1796 windres_put_32 (wrbfd, help, mi->help);
1797 set_windres_bfd_content (wrbfd, help, off, 4);
1800 off = res_to_bin_menuexitems (wrbfd, off, mi->popup);
1806 /* Convert an rcdata resource to binary. This is also used to convert
1807 other information which happens to be stored in rc_rcdata_item lists
1811 res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items)
1813 const rc_rcdata_item *ri;
1815 for (ri = items; ri != NULL; ri = ri->next)
1829 len = ri->u.string.length;
1831 case RCDATA_WSTRING:
1832 len = ri->u.wstring.length * sizeof (unichar);
1835 len = ri->u.buffer.length;
1841 bfd_byte *hp = &h[0];
1845 windres_put_16 (wrbfd, hp, ri->u.word);
1848 windres_put_32 (wrbfd, hp, ri->u.dword);
1851 hp = (bfd_byte *) ri->u.string.s;
1853 case RCDATA_WSTRING:
1857 hp = (bfd_byte *) reswr_alloc (len);
1858 for (i = 0; i < ri->u.wstring.length; i++)
1859 windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]);
1863 hp = (bfd_byte *) ri->u.buffer.data;
1866 set_windres_bfd_content (wrbfd, hp, off, len);
1873 /* Convert a stringtable resource to binary. */
1876 res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off,
1877 const rc_stringtable *st)
1881 for (i = 0; i < 16; i++)
1883 rc_uint_type slen, length;
1886 slen = (rc_uint_type) st->strings[i].length;
1887 if (slen == 0xffffffff) slen = 0;
1888 s = st->strings[i].string;
1890 length = 2 + slen * 2;
1896 hp = (bfd_byte *) reswr_alloc (length);
1897 windres_put_16 (wrbfd, hp, slen);
1899 for (j = 0; j < slen; j++)
1900 windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]);
1901 set_windres_bfd_content (wrbfd, hp, off, length);
1908 /* Convert an ASCII string to a unicode binary string. This always
1909 returns exactly one bindata structure. */
1912 string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s)
1916 len = (rc_uint_type) strlen (s);
1923 hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
1925 for (i = 0; i < len; i++)
1926 windres_put_16 (wrbfd, hp + i * 2, s[i]);
1927 windres_put_16 (wrbfd, hp + i * 2, 0);
1928 set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar));
1930 off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1935 res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb)
1939 struct bin_toolbar bt;
1940 windres_put_32 (wrbfd, bt.button_width, tb->button_width);
1941 windres_put_32 (wrbfd, bt.button_height, tb->button_height);
1942 windres_put_32 (wrbfd, bt.nitems, tb->nitems);
1943 set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE);
1946 rc_toolbar_item *it;
1950 ids = (bfd_byte *) reswr_alloc (tb->nitems * 4);
1954 windres_put_32 (wrbfd, ids + i, it->id.u.id);
1958 set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i);
1961 off += BIN_TOOLBAR_SIZE + tb->nitems * 4;
1966 /* Convert a versioninfo resource to binary. */
1969 res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off,
1970 const rc_versioninfo *versioninfo)
1972 rc_uint_type off_delta = off;
1974 struct bin_versioninfo bvi;
1978 off += BIN_VERSIONINFO_SIZE;
1979 off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO");
1980 off += (4 - ((off - off_delta) & 3)) & 3;
1982 if (versioninfo->fixed != NULL)
1986 struct bin_fixed_versioninfo bfv;
1987 const rc_fixed_versioninfo *fi;
1989 fi = versioninfo->fixed;
1990 windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd);
1991 windres_put_32 (wrbfd, bfv.sig2, 0x10000);
1992 windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms);
1993 windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls);
1994 windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms);
1995 windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls);
1996 windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask);
1997 windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags);
1998 windres_put_32 (wrbfd, bfv.file_os, fi->file_os);
1999 windres_put_32 (wrbfd, bfv.file_type, fi->file_type);
2000 windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype);
2001 windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms);
2002 windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls);
2003 set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE);
2005 off += BIN_FIXED_VERSIONINFO_SIZE;
2008 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2010 struct bin_ver_info bv;
2011 rc_uint_type bv_off;
2013 off += (4 - ((off - off_delta) & 3)) & 3;
2017 off += BIN_VER_INFO_SIZE;
2023 case VERINFO_STRING:
2025 const rc_ver_stringtable *vst;
2027 off = string_to_unicode_bin (wrbfd, off, "StringFileInfo");
2029 if (!vi->u.string.stringtables)
2030 off += (4 - ((off - off_delta) & 3)) & 3;
2032 for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next)
2034 struct bin_ver_info bvst;
2035 rc_uint_type vst_off;
2036 const rc_ver_stringinfo *vs;
2038 off += (4 - ((off - off_delta) & 3)) & 3;
2041 off += BIN_VER_INFO_SIZE;
2043 off = unicode_to_bin (wrbfd, off, vst->language);
2045 for (vs = vst->strings; vs != NULL; vs = vs->next)
2047 struct bin_ver_info bvs;
2048 rc_uint_type vs_off, str_off;
2050 off += (4 - ((off - off_delta) & 3)) & 3;
2053 off += BIN_VER_INFO_SIZE;
2055 off = unicode_to_bin (wrbfd, off, vs->key);
2057 off += (4 - ((off - off_delta) & 3)) & 3;
2060 off = unicode_to_bin (wrbfd, off, vs->value);
2064 windres_put_16 (wrbfd, bvs.size, off - vs_off);
2065 windres_put_16 (wrbfd, bvs.sig1, (off - str_off) / 2);
2066 windres_put_16 (wrbfd, bvs.sig2, 1);
2067 set_windres_bfd_content (wrbfd, &bvs, vs_off,
2074 windres_put_16 (wrbfd, bvst.size, off - vst_off);
2075 windres_put_16 (wrbfd, bvst.sig1, 0);
2076 windres_put_16 (wrbfd, bvst.sig2, 1);
2077 set_windres_bfd_content (wrbfd, &bvst, vst_off,
2086 rc_uint_type vvd_off, vvvd_off;
2087 struct bin_ver_info bvvd;
2088 const rc_ver_varinfo *vv;
2090 off = string_to_unicode_bin (wrbfd, off, "VarFileInfo");
2092 off += (4 - ((off - off_delta) & 3)) & 3;
2095 off += BIN_VER_INFO_SIZE;
2097 off = unicode_to_bin (wrbfd, off, vi->u.var.key);
2099 off += (4 - ((off - off_delta) & 3)) & 3;
2103 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2109 windres_put_16 (wrbfd, &vvsd[0], vv->language);
2110 windres_put_16 (wrbfd, &vvsd[2], vv->charset);
2111 set_windres_bfd_content (wrbfd, vvsd, off, 4);
2117 windres_put_16 (wrbfd, bvvd.size, off - vvd_off);
2118 windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off);
2119 windres_put_16 (wrbfd, bvvd.sig2, 0);
2120 set_windres_bfd_content (wrbfd, &bvvd, vvd_off,
2130 windres_put_16 (wrbfd, bv.size, off - bv_off);
2131 windres_put_16 (wrbfd, bv.sig1, 0);
2132 windres_put_16 (wrbfd, bv.sig2, 1);
2133 set_windres_bfd_content (wrbfd, &bv, bv_off,
2140 windres_put_16 (wrbfd, bvi.size, off - start);
2141 windres_put_16 (wrbfd, bvi.fixed_size,
2142 versioninfo->fixed == NULL ? 0
2143 : BIN_FIXED_VERSIONINFO_SIZE);
2144 windres_put_16 (wrbfd, bvi.sig2, 0);
2145 set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE);
2150 /* Convert a generic resource to binary. */
2153 res_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length,
2154 const bfd_byte *data)
2156 if (wrbfd && length != 0)
2157 set_windres_bfd_content (wrbfd, data, off, length);
2158 return off + (rc_uint_type) length;