1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright 1997, 1998, 1999, 2002, 2003, 2007
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
5 Rewritten by Kai Tietz, Onevision.
7 This file is part of GNU Binutils.
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.
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.
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
21 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
, read
;
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, &read
);
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
), &read
);
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);
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_stringinfo
**ppvs
;
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
);
1043 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1044 &vi
->u
.string
.language
, &verlen
, &vallen
,
1048 fatal (_("unexpected version stringtable value length %ld"), (long) vallen
);
1054 vi
->u
.string
.strings
= NULL
;
1055 ppvs
= &vi
->u
.string
.strings
;
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;
1063 rc_ver_stringinfo
*vs
;
1064 rc_uint_type subverlen
, vslen
, valoff
;
1066 vs
= (rc_ver_stringinfo
*) res_alloc (sizeof *vs
);
1068 get_version_header (wrbfd
, data
, length
,
1069 (const char *) NULL
, &vs
->key
, &subverlen
,
1070 &vallen
, &type
, &off
);
1072 subverlen
= (subverlen
+ 3) &~ 3;
1077 vs
->value
= get_unicode (wrbfd
, data
, length
, &vslen
);
1078 valoff
= vslen
* 2 + 2;
1079 valoff
= (valoff
+ 3) &~ 3;
1081 if (off
+ valoff
!= subverlen
)
1082 fatal (_("unexpected version string length %ld != %ld + %ld"),
1083 (long) subverlen
, (long) off
, (long) valoff
);
1092 if (verlen
< subverlen
)
1093 fatal (_("unexpected version string length %ld < %ld"),
1094 (long) verlen
, (long) subverlen
);
1096 verlen
-= subverlen
;
1101 rc_ver_varinfo
**ppvv
;
1103 vi
->type
= VERINFO_VAR
;
1105 get_version_header (wrbfd
, data
, length
, "VarFileInfo",
1106 (unichar
**) NULL
, &verlen
, &vallen
, &type
,
1110 fatal (_("unexpected varfileinfo value length %ld"), (long) vallen
);
1115 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1116 &vi
->u
.var
.key
, &verlen
, &vallen
, &type
, &off
);
1121 vi
->u
.var
.var
= NULL
;
1122 ppvv
= &vi
->u
.var
.var
;
1129 toosmall (_("version varfileinfo"));
1131 vv
= (rc_ver_varinfo
*) res_alloc (sizeof (rc_ver_varinfo
));
1133 vv
->language
= windres_get_16 (wrbfd
, data
, 2);
1134 vv
->charset
= windres_get_16 (wrbfd
, data
+ 2, 2);
1144 fatal (_("unexpected version value length %ld"), (long) vallen
);
1150 fatal (_("unexpected version string"));
1157 v
= (rc_versioninfo
*) res_alloc (sizeof (rc_versioninfo
));
1161 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1162 r
->type
= RES_TYPE_VERSIONINFO
;
1163 r
->u
.versioninfo
= v
;
1168 /* Convert an arbitrary user defined resource from binary. */
1170 static rc_res_resource
*
1171 bin_to_res_userdata (windres_bfd
*wrbfd ATTRIBUTE_UNUSED
, const bfd_byte
*data
,
1172 rc_uint_type length
)
1177 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1180 ri
->type
= RCDATA_BUFFER
;
1181 ri
->u
.buffer
.length
= length
;
1182 ri
->u
.buffer
.data
= data
;
1184 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1185 r
->type
= RES_TYPE_USERDATA
;
1191 static rc_res_resource
*
1192 bin_to_res_toolbar (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
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);
1206 for (i
=0 ; i
< ri
->nitems
; i
++)
1208 rc_toolbar_item
*it
;
1209 it
= (rc_toolbar_item
*) res_alloc (sizeof (rc_toolbar_item
));
1211 it
->id
.u
.id
= (int) windres_get_32 (wrbfd
, data
, 4);
1212 it
->prev
= it
->next
= NULL
;
1216 rc_toolbar_item
*ii
= ri
->items
;
1217 while (ii
->next
!= NULL
)
1225 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1226 r
->type
= RES_TYPE_TOOLBAR
;
1232 /* Local functions used to convert resources to binary format. */
1234 static rc_uint_type
resid_to_bin (windres_bfd
*, rc_uint_type
, rc_res_id
);
1235 static rc_uint_type
unicode_to_bin (windres_bfd
*, rc_uint_type
, const unichar
*);
1236 static rc_uint_type
res_to_bin_accelerator (windres_bfd
*, rc_uint_type
, const rc_accelerator
*);
1237 static rc_uint_type
res_to_bin_cursor (windres_bfd
*, rc_uint_type
, const rc_cursor
*);
1238 static rc_uint_type
res_to_bin_group_cursor (windres_bfd
*, rc_uint_type
, const rc_group_cursor
*);
1239 static rc_uint_type
res_to_bin_dialog (windres_bfd
*, rc_uint_type
, const rc_dialog
*);
1240 static rc_uint_type
res_to_bin_fontdir (windres_bfd
*, rc_uint_type
, const rc_fontdir
*);
1241 static rc_uint_type
res_to_bin_group_icon (windres_bfd
*, rc_uint_type
, const rc_group_icon
*);
1242 static rc_uint_type
res_to_bin_menu (windres_bfd
*, rc_uint_type
, const rc_menu
*);
1243 static rc_uint_type
res_to_bin_menuitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1244 static rc_uint_type
res_to_bin_menuexitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1245 static rc_uint_type
res_to_bin_rcdata (windres_bfd
*, rc_uint_type
, const rc_rcdata_item
*);
1246 static rc_uint_type
res_to_bin_stringtable (windres_bfd
*, rc_uint_type
, const rc_stringtable
*);
1247 static rc_uint_type
string_to_unicode_bin (windres_bfd
*, rc_uint_type
, const char *);
1248 static rc_uint_type
res_to_bin_toolbar (windres_bfd
*, rc_uint_type
, rc_toolbar
*tb
);
1249 static rc_uint_type
res_to_bin_versioninfo (windres_bfd
*, rc_uint_type
, const rc_versioninfo
*);
1250 static rc_uint_type
res_to_bin_generic (windres_bfd
*, rc_uint_type
, rc_uint_type
,
1253 /* Convert a resource to binary. */
1256 res_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_res_resource
*res
)
1260 case RES_TYPE_BITMAP
:
1263 case RES_TYPE_MESSAGETABLE
:
1264 return res_to_bin_generic (wrbfd
, off
, res
->u
.data
.length
, res
->u
.data
.data
);
1265 case RES_TYPE_ACCELERATOR
:
1266 return res_to_bin_accelerator (wrbfd
, off
, res
->u
.acc
);
1267 case RES_TYPE_CURSOR
:
1268 return res_to_bin_cursor (wrbfd
, off
, res
->u
.cursor
);
1269 case RES_TYPE_GROUP_CURSOR
:
1270 return res_to_bin_group_cursor (wrbfd
, off
, res
->u
.group_cursor
);
1271 case RES_TYPE_DIALOG
:
1272 return res_to_bin_dialog (wrbfd
, off
, res
->u
.dialog
);
1273 case RES_TYPE_FONTDIR
:
1274 return res_to_bin_fontdir (wrbfd
, off
, res
->u
.fontdir
);
1275 case RES_TYPE_GROUP_ICON
:
1276 return res_to_bin_group_icon (wrbfd
, off
, res
->u
.group_icon
);
1278 return res_to_bin_menu (wrbfd
, off
, res
->u
.menu
);
1279 case RES_TYPE_STRINGTABLE
:
1280 return res_to_bin_stringtable (wrbfd
, off
, res
->u
.stringtable
);
1281 case RES_TYPE_VERSIONINFO
:
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
:
1288 return res_to_bin_rcdata (wrbfd
, off
, res
->u
.rcdata
);
1292 /* Convert a resource ID to binary. This always returns exactly one
1293 bindata structure. */
1296 resid_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, rc_res_id id
)
1302 struct bin_res_id bri
;
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
);
1312 rc_uint_type len
= (id
.u
.n
.name
? unichar_len (id
.u
.n
.name
) : 0);
1315 bfd_byte
*d
= (bfd_byte
*) reswr_alloc ((len
+ 1) * sizeof (unichar
));
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
));
1322 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1327 /* Convert a null terminated unicode string to binary. This always
1328 returns exactly one bindata structure. */
1331 unicode_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const unichar
*str
)
1333 rc_uint_type len
= 0;
1336 len
= unichar_len (str
);
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
));
1348 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1353 /* Convert an accelerator resource to binary. */
1356 res_to_bin_accelerator (windres_bfd
*wrbfd
, rc_uint_type off
,
1357 const rc_accelerator
*accelerators
)
1359 bindata
*first
, **pp
;
1360 const rc_accelerator
*a
;
1365 for (a
= accelerators
; a
!= NULL
; a
= a
->next
)
1369 struct bin_accelerator ba
;
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
);
1377 off
+= BIN_ACCELERATOR_SIZE
;
1382 /* Convert a cursor resource to binary. */
1385 res_to_bin_cursor (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_cursor
*c
)
1389 struct bin_cursor bc
;
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
);
1395 set_windres_bfd_content (wrbfd
, c
->data
, off
+ BIN_CURSOR_SIZE
, c
->length
);
1397 off
= (off
+ BIN_CURSOR_SIZE
+ (rc_uint_type
) c
->length
);
1401 /* Convert a group cursor resource to binary. */
1404 res_to_bin_group_cursor (windres_bfd
*wrbfd
, rc_uint_type off
,
1405 const rc_group_cursor
*group_cursors
)
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
;
1413 off
+= BIN_GROUP_CURSOR_SIZE
;
1415 for (c
= 0, gc
= group_cursors
; gc
!= NULL
; gc
= gc
->next
, c
++)
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
);
1428 off
+= BIN_GROUP_CURSOR_ITEM_SIZE
;
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
);
1440 /* Convert a dialog resource to binary. */
1443 res_to_bin_dialog (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_dialog
*dialog
)
1445 rc_uint_type off_delta
;
1446 rc_uint_type start
, marker
;
1449 rc_dialog_control
*dc
;
1450 struct bin_dialogex bdx
;
1451 struct bin_dialog bd
;
1455 dialogex
= extended_dialog (dialog
);
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
);
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
);
1482 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_SIZE
: BIN_DIALOG_SIZE
);
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
);
1488 if ((dialog
->style
& DS_SETFONT
) != 0)
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
);
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
);
1508 off
+= (dialogex
? BIN_DIALOGEXFONT_SIZE
: BIN_DIALOGFONT_SIZE
);
1509 off
= unicode_to_bin (wrbfd
, off
, dialog
->font
);
1511 for (c
= 0, dc
= dialog
->controls
; dc
!= NULL
; dc
= dc
->next
, c
++)
1513 bfd_byte dc_rclen
[2];
1515 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1520 struct bin_dialog_control bdc
;
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
);
1533 struct bin_dialogex_control bdc
;
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
);
1546 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_CONTROL_SIZE
: BIN_DIALOG_CONTROL_SIZE
);
1548 off
= resid_to_bin (wrbfd
, off
, dc
->class);
1549 off
= resid_to_bin (wrbfd
, off
, dc
->text
);
1551 marker
= off
; /* Save two bytes for size of optional data. */
1554 if (dc
->data
== NULL
)
1557 windres_put_16 (wrbfd
, dc_rclen
, 0);
1561 rc_uint_type saved_off
= off
;
1562 rc_uint_type old_off
;
1563 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1566 off
= res_to_bin_rcdata (wrbfd
, off
, dc
->data
);
1567 if ((off
- old_off
) == 0)
1568 old_off
= off
= saved_off
;
1570 windres_put_16 (wrbfd
, dc_rclen
, off
- old_off
);
1573 set_windres_bfd_content (wrbfd
, dc_rclen
, marker
, 2);
1578 windres_put_16 (wrbfd
, (dialogex
!= 0 ? bdx
.off
: bd
.off
), c
);
1580 set_windres_bfd_content (wrbfd
, &bd
, start
, BIN_DIALOG_SIZE
);
1582 set_windres_bfd_content (wrbfd
, &bdx
, start
, BIN_DIALOGEX_SIZE
);
1588 /* Convert a fontdir resource to binary. */
1590 res_to_bin_fontdir (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_fontdir
*fontdirs
)
1594 const rc_fontdir
*fd
;
1599 for (c
= 0, fd
= fontdirs
; fd
!= NULL
; fd
= fd
->next
, c
++)
1604 windres_put_16 (wrbfd
, d
, fd
->index
);
1605 set_windres_bfd_content (wrbfd
, d
, off
, 2);
1607 set_windres_bfd_content (wrbfd
, fd
->data
, off
+ 2, fd
->length
);
1609 off
+= (rc_uint_type
) fd
->length
+ 2;
1615 windres_put_16 (wrbfd
, d
, c
);
1616 set_windres_bfd_content (wrbfd
, d
, start
, 2);
1621 /* Convert a group icon resource to binary. */
1624 res_to_bin_group_icon (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_group_icon
*group_icons
)
1627 struct bin_group_icon bgi
;
1629 const rc_group_icon
*gi
;
1632 off
+= BIN_GROUP_ICON_SIZE
;
1634 for (c
= 0, gi
= group_icons
; gi
!= NULL
; gi
= gi
->next
, c
++)
1636 struct bin_group_icon_item bgii
;
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
);
1650 off
+= BIN_GROUP_ICON_ITEM_SIZE
;
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
);
1663 /* Convert a menu resource to binary. */
1666 res_to_bin_menu (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menu
*menu
)
1670 menuex
= extended_menu (menu
);
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
);
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
);
1690 off
+= (menuex
!= 0 ? BIN_MENUEX_SIZE
: BIN_MENU_SIZE
);
1693 off
= res_to_bin_menuitems (wrbfd
, off
, menu
->items
);
1697 off
= res_to_bin_menuexitems (wrbfd
, off
, menu
->items
);
1702 /* Convert menu items to binary. */
1705 res_to_bin_menuitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1707 const rc_menuitem
*mi
;
1709 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1711 struct bin_menuitem bmi
;
1715 if (mi
->next
== NULL
)
1716 flags
|= MENUITEM_ENDMENU
;
1717 if (mi
->popup
!= NULL
)
1718 flags
|= MENUITEM_POPUP
;
1722 windres_put_16 (wrbfd
, bmi
.flags
, flags
);
1723 if (mi
->popup
== NULL
)
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
);
1729 off
+= (mi
->popup
== NULL
? BIN_MENUITEM_SIZE
: BIN_MENUITEM_POPUP_SIZE
);
1731 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1733 if (mi
->popup
!= NULL
)
1735 off
= res_to_bin_menuitems (wrbfd
, off
, mi
->popup
);
1741 /* Convert menuex items to binary. */
1744 res_to_bin_menuexitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1746 rc_uint_type off_delta
= off
;
1747 const rc_menuitem
*mi
;
1749 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1751 struct bin_menuitemex bmi
;
1754 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1757 if (mi
->next
== NULL
)
1759 if (mi
->popup
!= NULL
)
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
);
1770 off
+= BIN_MENUITEMEX_SIZE
;
1772 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1774 if (mi
->popup
!= NULL
)
1778 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1782 windres_put_32 (wrbfd
, help
, mi
->help
);
1783 set_windres_bfd_content (wrbfd
, help
, off
, 4);
1786 off
= res_to_bin_menuexitems (wrbfd
, off
, mi
->popup
);
1792 /* Convert an rcdata resource to binary. This is also used to convert
1793 other information which happens to be stored in rc_rcdata_item lists
1797 res_to_bin_rcdata (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_rcdata_item
*items
)
1799 const rc_rcdata_item
*ri
;
1801 for (ri
= items
; ri
!= NULL
; ri
= ri
->next
)
1815 len
= ri
->u
.string
.length
;
1817 case RCDATA_WSTRING
:
1818 len
= ri
->u
.wstring
.length
* sizeof (unichar
);
1821 len
= ri
->u
.buffer
.length
;
1827 bfd_byte
*hp
= &h
[0];
1831 windres_put_16 (wrbfd
, hp
, ri
->u
.word
);
1834 windres_put_32 (wrbfd
, hp
, ri
->u
.dword
);
1837 hp
= (bfd_byte
*) ri
->u
.string
.s
;
1839 case RCDATA_WSTRING
:
1843 hp
= (bfd_byte
*) reswr_alloc (len
);
1844 for (i
= 0; i
< ri
->u
.wstring
.length
; i
++)
1845 windres_put_16 (wrbfd
, hp
+ i
* sizeof (unichar
), ri
->u
.wstring
.w
[i
]);
1849 hp
= (bfd_byte
*) ri
->u
.buffer
.data
;
1852 set_windres_bfd_content (wrbfd
, hp
, off
, len
);
1859 /* Convert a stringtable resource to binary. */
1862 res_to_bin_stringtable (windres_bfd
*wrbfd
, rc_uint_type off
,
1863 const rc_stringtable
*st
)
1867 for (i
= 0; i
< 16; i
++)
1869 rc_uint_type slen
, length
;
1872 slen
= (rc_uint_type
) st
->strings
[i
].length
;
1873 s
= st
->strings
[i
].string
;
1875 length
= 2 + slen
* 2;
1881 hp
= (bfd_byte
*) reswr_alloc (length
);
1882 windres_put_16 (wrbfd
, hp
, slen
);
1884 for (j
= 0; j
< slen
; j
++)
1885 windres_put_16 (wrbfd
, hp
+ 2 + j
* 2, s
[j
]);
1886 set_windres_bfd_content (wrbfd
, hp
, off
, length
);
1893 /* Convert an ASCII string to a unicode binary string. This always
1894 returns exactly one bindata structure. */
1897 string_to_unicode_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const char *s
)
1901 len
= (rc_uint_type
) strlen (s
);
1908 hp
= (bfd_byte
*) reswr_alloc ((len
+ 1) * sizeof (unichar
));
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
));
1915 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1920 res_to_bin_toolbar (windres_bfd
*wrbfd
, rc_uint_type off
, rc_toolbar
*tb
)
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
);
1931 rc_toolbar_item
*it
;
1935 ids
= (bfd_byte
*) reswr_alloc (tb
->nitems
* 4);
1939 windres_put_32 (wrbfd
, ids
+ i
, it
->id
.u
.id
);
1943 set_windres_bfd_content (wrbfd
, ids
, off
+ BIN_TOOLBAR_SIZE
, i
);
1946 off
+= BIN_TOOLBAR_SIZE
+ tb
->nitems
* 4;
1951 /* Convert a versioninfo resource to binary. */
1954 res_to_bin_versioninfo (windres_bfd
*wrbfd
, rc_uint_type off
,
1955 const rc_versioninfo
*versioninfo
)
1957 rc_uint_type off_delta
= off
;
1959 struct bin_versioninfo bvi
;
1963 off
+= BIN_VERSIONINFO_SIZE
;
1964 off
= string_to_unicode_bin (wrbfd
, off
, "VS_VERSION_INFO");
1965 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1967 if (versioninfo
->fixed
!= NULL
)
1971 struct bin_fixed_versioninfo bfv
;
1972 const rc_fixed_versioninfo
*fi
;
1974 fi
= versioninfo
->fixed
;
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
);
1990 off
+= BIN_FIXED_VERSIONINFO_SIZE
;
1993 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
1995 struct bin_ver_info bv
;
1996 rc_uint_type bv_off
;
1998 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2002 off
+= BIN_VER_INFO_SIZE
;
2008 case VERINFO_STRING
:
2010 struct bin_ver_info bvsd
;
2011 rc_uint_type vs_off
;
2012 const rc_ver_stringinfo
*vs
;
2014 off
= string_to_unicode_bin (wrbfd
, off
, "StringFileInfo");
2015 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2019 off
+= BIN_VER_INFO_SIZE
;
2021 off
= unicode_to_bin (wrbfd
, off
, vi
->u
.string
.language
);
2023 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2025 struct bin_ver_info bvss
;
2026 rc_uint_type vss_off
,str_off
;
2028 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2031 off
+= BIN_VER_INFO_SIZE
;
2033 off
= unicode_to_bin (wrbfd
, off
, vs
->key
);
2035 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2038 off
= unicode_to_bin (wrbfd
, off
, vs
->value
);
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
,
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
,
2061 rc_uint_type vvd_off
, vvvd_off
;
2062 struct bin_ver_info bvvd
;
2063 const rc_ver_varinfo
*vv
;
2065 off
= string_to_unicode_bin (wrbfd
, off
, "VarFileInfo");
2067 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2070 off
+= BIN_VER_INFO_SIZE
;
2072 off
= unicode_to_bin (wrbfd
, off
, vi
->u
.var
.key
);
2074 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2078 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
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);
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
,
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
,
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
);
2125 /* Convert a generic resource to binary. */
2128 res_to_bin_generic (windres_bfd
*wrbfd
, rc_uint_type off
, rc_uint_type length
,
2129 const bfd_byte
*data
)
2131 if (wrbfd
&& length
!= 0)
2132 set_windres_bfd_content (wrbfd
, data
, off
, length
);
2133 return off
+ (rc_uint_type
) length
;