1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright (C) 1997-2016 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 /* PR 17512: The verlen field does not include padding length. */
966 fatal (_("version length %lu greater than resource length %lu"),
967 (unsigned long) verlen
, (unsigned long) length
);
970 fatal (_("unexpected version type %d"), (int) type
);
979 unsigned long signature
, fiv
;
982 fatal (_("unexpected fixed version information length %ld"), (long) vallen
);
985 toosmall (_("fixed version info"));
987 signature
= windres_get_32 (wrbfd
, data
, 4);
988 if (signature
!= 0xfeef04bd)
989 fatal (_("unexpected fixed version signature %lu"), signature
);
991 fiv
= windres_get_32 (wrbfd
, data
+ 4, 4);
992 if (fiv
!= 0 && fiv
!= 0x10000)
993 fatal (_("unexpected fixed version info version %lu"), fiv
);
995 fi
= (rc_fixed_versioninfo
*) res_alloc (sizeof (rc_fixed_versioninfo
));
997 fi
->file_version_ms
= windres_get_32 (wrbfd
, data
+ 8, 4);
998 fi
->file_version_ls
= windres_get_32 (wrbfd
, data
+ 12, 4);
999 fi
->product_version_ms
= windres_get_32 (wrbfd
, data
+ 16, 4);
1000 fi
->product_version_ls
= windres_get_32 (wrbfd
, data
+ 20, 4);
1001 fi
->file_flags_mask
= windres_get_32 (wrbfd
, data
+ 24, 4);
1002 fi
->file_flags
= windres_get_32 (wrbfd
, data
+ 28, 4);
1003 fi
->file_os
= windres_get_32 (wrbfd
, data
+ 32, 4);
1004 fi
->file_type
= windres_get_32 (wrbfd
, data
+ 36, 4);
1005 fi
->file_subtype
= windres_get_32 (wrbfd
, data
+ 40, 4);
1006 fi
->file_date_ms
= windres_get_32 (wrbfd
, data
+ 44, 4);
1007 fi
->file_date_ls
= windres_get_32 (wrbfd
, data
+ 48, 4);
1022 toosmall (_("version var info"));
1024 vi
= (rc_ver_info
*) res_alloc (sizeof (rc_ver_info
));
1026 ch
= windres_get_16 (wrbfd
, data
+ 6, 2);
1030 rc_ver_stringtable
**ppvst
;
1032 vi
->type
= VERINFO_STRING
;
1034 get_version_header (wrbfd
, data
, length
, "StringFileInfo",
1035 (unichar
**) NULL
, &verlen
, &vallen
, &type
,
1039 fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen
);
1046 vi
->u
.string
.stringtables
= NULL
;
1047 ppvst
= &vi
->u
.string
.stringtables
;
1051 rc_ver_stringtable
*vst
;
1052 rc_uint_type stverlen
;
1053 rc_ver_stringinfo
**ppvs
;
1056 toosmall (_("version stringtable"));
1058 vst
= (rc_ver_stringtable
*) res_alloc (sizeof (rc_ver_stringtable
));
1060 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1061 &vst
->language
, &stverlen
, &vallen
, &type
, &off
);
1064 fatal (_("unexpected version stringtable value length %ld"), (long) vallen
);
1072 vst
->strings
= NULL
;
1073 ppvs
= &vst
->strings
;
1075 while (stverlen
> 0)
1077 rc_ver_stringinfo
*vs
;
1078 rc_uint_type sverlen
, vslen
, valoff
;
1081 toosmall (_("version string"));
1083 vs
= (rc_ver_stringinfo
*) res_alloc (sizeof (rc_ver_stringinfo
));
1085 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1086 &vs
->key
, &sverlen
, &vallen
, &type
, &off
);
1091 vs
->value
= get_unicode (wrbfd
, data
, length
, &vslen
);
1092 valoff
= vslen
* 2 + 2;
1093 valoff
= (valoff
+ 3) & ~3;
1095 if (off
+ valoff
!= sverlen
)
1096 fatal (_("unexpected version string length %ld != %ld + %ld"),
1097 (long) sverlen
, (long) off
, (long) valoff
);
1102 if (stverlen
< sverlen
)
1103 fatal (_("unexpected version string length %ld < %ld"),
1104 (long) verlen
, (long) sverlen
);
1105 stverlen
-= sverlen
;
1120 rc_ver_varinfo
**ppvv
;
1122 vi
->type
= VERINFO_VAR
;
1124 get_version_header (wrbfd
, data
, length
, "VarFileInfo",
1125 (unichar
**) NULL
, &verlen
, &vallen
, &type
,
1129 fatal (_("unexpected varfileinfo value length %ld"), (long) vallen
);
1134 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1135 &vi
->u
.var
.key
, &verlen
, &vallen
, &type
, &off
);
1140 vi
->u
.var
.var
= NULL
;
1141 ppvv
= &vi
->u
.var
.var
;
1148 toosmall (_("version varfileinfo"));
1150 vv
= (rc_ver_varinfo
*) res_alloc (sizeof (rc_ver_varinfo
));
1152 vv
->language
= windres_get_16 (wrbfd
, data
, 2);
1153 vv
->charset
= windres_get_16 (wrbfd
, data
+ 2, 2);
1163 fatal (_("unexpected version value length %ld"), (long) vallen
);
1171 /* Padding - skip. */
1173 fatal (_("nul bytes found in version string"));
1176 fatal (_("unexpected version string character: %x"), ch
);
1183 v
= (rc_versioninfo
*) res_alloc (sizeof (rc_versioninfo
));
1187 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1188 r
->type
= RES_TYPE_VERSIONINFO
;
1189 r
->u
.versioninfo
= v
;
1194 /* Convert an arbitrary user defined resource from binary. */
1196 static rc_res_resource
*
1197 bin_to_res_userdata (windres_bfd
*wrbfd ATTRIBUTE_UNUSED
, const bfd_byte
*data
,
1198 rc_uint_type length
)
1203 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1206 ri
->type
= RCDATA_BUFFER
;
1207 ri
->u
.buffer
.length
= length
;
1208 ri
->u
.buffer
.data
= data
;
1210 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1211 r
->type
= RES_TYPE_USERDATA
;
1217 static rc_res_resource
*
1218 bin_to_res_toolbar (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
1224 ri
= (rc_toolbar
*) res_alloc (sizeof (rc_toolbar
));
1225 ri
->button_width
= windres_get_32 (wrbfd
, data
, 4);
1226 ri
->button_height
= windres_get_32 (wrbfd
, data
+ 4, 4);
1227 ri
->nitems
= windres_get_32 (wrbfd
, data
+ 8, 4);
1232 for (i
=0 ; i
< ri
->nitems
; i
++)
1234 rc_toolbar_item
*it
;
1235 it
= (rc_toolbar_item
*) res_alloc (sizeof (rc_toolbar_item
));
1237 it
->id
.u
.id
= (int) windres_get_32 (wrbfd
, data
, 4);
1238 it
->prev
= it
->next
= NULL
;
1242 rc_toolbar_item
*ii
= ri
->items
;
1243 while (ii
->next
!= NULL
)
1251 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1252 r
->type
= RES_TYPE_TOOLBAR
;
1258 /* Local functions used to convert resources to binary format. */
1260 static rc_uint_type
resid_to_bin (windres_bfd
*, rc_uint_type
, rc_res_id
);
1261 static rc_uint_type
unicode_to_bin (windres_bfd
*, rc_uint_type
, const unichar
*);
1262 static rc_uint_type
res_to_bin_accelerator (windres_bfd
*, rc_uint_type
, const rc_accelerator
*);
1263 static rc_uint_type
res_to_bin_cursor (windres_bfd
*, rc_uint_type
, const rc_cursor
*);
1264 static rc_uint_type
res_to_bin_group_cursor (windres_bfd
*, rc_uint_type
, const rc_group_cursor
*);
1265 static rc_uint_type
res_to_bin_dialog (windres_bfd
*, rc_uint_type
, const rc_dialog
*);
1266 static rc_uint_type
res_to_bin_fontdir (windres_bfd
*, rc_uint_type
, const rc_fontdir
*);
1267 static rc_uint_type
res_to_bin_group_icon (windres_bfd
*, rc_uint_type
, const rc_group_icon
*);
1268 static rc_uint_type
res_to_bin_menu (windres_bfd
*, rc_uint_type
, const rc_menu
*);
1269 static rc_uint_type
res_to_bin_menuitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1270 static rc_uint_type
res_to_bin_menuexitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1271 static rc_uint_type
res_to_bin_rcdata (windres_bfd
*, rc_uint_type
, const rc_rcdata_item
*);
1272 static rc_uint_type
res_to_bin_stringtable (windres_bfd
*, rc_uint_type
, const rc_stringtable
*);
1273 static rc_uint_type
string_to_unicode_bin (windres_bfd
*, rc_uint_type
, const char *);
1274 static rc_uint_type
res_to_bin_toolbar (windres_bfd
*, rc_uint_type
, rc_toolbar
*tb
);
1275 static rc_uint_type
res_to_bin_versioninfo (windres_bfd
*, rc_uint_type
, const rc_versioninfo
*);
1276 static rc_uint_type
res_to_bin_generic (windres_bfd
*, rc_uint_type
, rc_uint_type
,
1279 /* Convert a resource to binary. */
1282 res_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_res_resource
*res
)
1286 case RES_TYPE_BITMAP
:
1289 case RES_TYPE_MESSAGETABLE
:
1290 return res_to_bin_generic (wrbfd
, off
, res
->u
.data
.length
, res
->u
.data
.data
);
1291 case RES_TYPE_ACCELERATOR
:
1292 return res_to_bin_accelerator (wrbfd
, off
, res
->u
.acc
);
1293 case RES_TYPE_CURSOR
:
1294 return res_to_bin_cursor (wrbfd
, off
, res
->u
.cursor
);
1295 case RES_TYPE_GROUP_CURSOR
:
1296 return res_to_bin_group_cursor (wrbfd
, off
, res
->u
.group_cursor
);
1297 case RES_TYPE_DIALOG
:
1298 return res_to_bin_dialog (wrbfd
, off
, res
->u
.dialog
);
1299 case RES_TYPE_FONTDIR
:
1300 return res_to_bin_fontdir (wrbfd
, off
, res
->u
.fontdir
);
1301 case RES_TYPE_GROUP_ICON
:
1302 return res_to_bin_group_icon (wrbfd
, off
, res
->u
.group_icon
);
1304 return res_to_bin_menu (wrbfd
, off
, res
->u
.menu
);
1305 case RES_TYPE_STRINGTABLE
:
1306 return res_to_bin_stringtable (wrbfd
, off
, res
->u
.stringtable
);
1307 case RES_TYPE_VERSIONINFO
:
1308 return res_to_bin_versioninfo (wrbfd
, off
, res
->u
.versioninfo
);
1309 case RES_TYPE_TOOLBAR
:
1310 return res_to_bin_toolbar (wrbfd
, off
, res
->u
.toolbar
);
1311 case RES_TYPE_USERDATA
:
1312 case RES_TYPE_RCDATA
:
1314 return res_to_bin_rcdata (wrbfd
, off
, res
->u
.rcdata
);
1318 /* Convert a resource ID to binary. This always returns exactly one
1319 bindata structure. */
1322 resid_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, rc_res_id id
)
1328 struct bin_res_id bri
;
1330 windres_put_16 (wrbfd
, bri
.sig
, 0xffff);
1331 windres_put_16 (wrbfd
, bri
.id
, id
.u
.id
);
1332 set_windres_bfd_content (wrbfd
, &bri
, off
, BIN_RES_ID
);
1338 rc_uint_type len
= (id
.u
.n
.name
? unichar_len (id
.u
.n
.name
) : 0);
1341 bfd_byte
*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
)), id
.u
.n
.name
[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 a null terminated unicode string to binary. This always
1354 returns exactly one bindata structure. */
1357 unicode_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const unichar
*str
)
1359 rc_uint_type len
= 0;
1362 len
= unichar_len (str
);
1368 d
= (bfd_byte
*) reswr_alloc ( (len
+ 1) * sizeof (unichar
));
1369 for (i
= 0; i
< len
; i
++)
1370 windres_put_16 (wrbfd
, d
+ (i
* sizeof (unichar
)), str
[i
]);
1371 windres_put_16 (wrbfd
, d
+ (len
* sizeof (unichar
)), 0);
1372 set_windres_bfd_content (wrbfd
, d
, off
, (len
+ 1) * sizeof (unichar
));
1374 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1379 /* Convert an accelerator resource to binary. */
1382 res_to_bin_accelerator (windres_bfd
*wrbfd
, rc_uint_type off
,
1383 const rc_accelerator
*accelerators
)
1385 const rc_accelerator
*a
;
1387 for (a
= accelerators
; a
!= NULL
; a
= a
->next
)
1391 struct bin_accelerator ba
;
1393 windres_put_16 (wrbfd
, ba
.flags
, a
->flags
| (a
->next
!= NULL
? 0 : ACC_LAST
));
1394 windres_put_16 (wrbfd
, ba
.key
, a
->key
);
1395 windres_put_16 (wrbfd
, ba
.id
, a
->id
);
1396 windres_put_16 (wrbfd
, ba
.pad
, 0);
1397 set_windres_bfd_content (wrbfd
, &ba
, off
, BIN_ACCELERATOR_SIZE
);
1399 off
+= BIN_ACCELERATOR_SIZE
;
1404 /* Convert a cursor resource to binary. */
1407 res_to_bin_cursor (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_cursor
*c
)
1411 struct bin_cursor bc
;
1413 windres_put_16 (wrbfd
, bc
.xhotspot
, c
->xhotspot
);
1414 windres_put_16 (wrbfd
, bc
.yhotspot
, c
->yhotspot
);
1415 set_windres_bfd_content (wrbfd
, &bc
, off
, BIN_CURSOR_SIZE
);
1417 set_windres_bfd_content (wrbfd
, c
->data
, off
+ BIN_CURSOR_SIZE
, c
->length
);
1419 off
= (off
+ BIN_CURSOR_SIZE
+ (rc_uint_type
) c
->length
);
1423 /* Convert a group cursor resource to binary. */
1426 res_to_bin_group_cursor (windres_bfd
*wrbfd
, rc_uint_type off
,
1427 const rc_group_cursor
*group_cursors
)
1430 const rc_group_cursor
*gc
;
1431 struct bin_group_cursor bgc
;
1432 struct bin_group_cursor_item bgci
;
1433 rc_uint_type start
= off
;
1435 off
+= BIN_GROUP_CURSOR_SIZE
;
1437 for (c
= 0, gc
= group_cursors
; gc
!= NULL
; gc
= gc
->next
, c
++)
1441 windres_put_16 (wrbfd
, bgci
.width
, gc
->width
);
1442 windres_put_16 (wrbfd
, bgci
.height
, gc
->height
);
1443 windres_put_16 (wrbfd
, bgci
.planes
, gc
->planes
);
1444 windres_put_16 (wrbfd
, bgci
.bits
, gc
->bits
);
1445 windres_put_32 (wrbfd
, bgci
.bytes
, gc
->bytes
);
1446 windres_put_16 (wrbfd
, bgci
.index
, gc
->index
);
1447 set_windres_bfd_content (wrbfd
, &bgci
, off
, BIN_GROUP_CURSOR_ITEM_SIZE
);
1450 off
+= BIN_GROUP_CURSOR_ITEM_SIZE
;
1454 windres_put_16 (wrbfd
, bgc
.sig1
, 0);
1455 windres_put_16 (wrbfd
, bgc
.sig2
, 2);
1456 windres_put_16 (wrbfd
, bgc
.nitems
, c
);
1457 set_windres_bfd_content (wrbfd
, &bgc
, start
, BIN_GROUP_CURSOR_SIZE
);
1462 /* Convert a dialog resource to binary. */
1465 res_to_bin_dialog (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_dialog
*dialog
)
1467 rc_uint_type off_delta
;
1468 rc_uint_type start
, marker
;
1471 rc_dialog_control
*dc
;
1472 struct bin_dialogex bdx
;
1473 struct bin_dialog bd
;
1477 dialogex
= extended_dialog (dialog
);
1483 windres_put_32 (wrbfd
, bd
.style
, dialog
->style
);
1484 windres_put_32 (wrbfd
, bd
.exstyle
, dialog
->exstyle
);
1485 windres_put_16 (wrbfd
, bd
.x
, dialog
->x
);
1486 windres_put_16 (wrbfd
, bd
.y
, dialog
->y
);
1487 windres_put_16 (wrbfd
, bd
.width
, dialog
->width
);
1488 windres_put_16 (wrbfd
, bd
.height
, dialog
->height
);
1492 windres_put_16 (wrbfd
, bdx
.sig1
, 1);
1493 windres_put_16 (wrbfd
, bdx
.sig2
, 0xffff);
1494 windres_put_32 (wrbfd
, bdx
.help
, (dialog
->ex
? dialog
->ex
->help
: 0));
1495 windres_put_32 (wrbfd
, bdx
.exstyle
, dialog
->exstyle
);
1496 windres_put_32 (wrbfd
, bdx
.style
, dialog
->style
);
1497 windres_put_16 (wrbfd
, bdx
.x
, dialog
->x
);
1498 windres_put_16 (wrbfd
, bdx
.y
, dialog
->y
);
1499 windres_put_16 (wrbfd
, bdx
.width
, dialog
->width
);
1500 windres_put_16 (wrbfd
, bdx
.height
, dialog
->height
);
1504 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_SIZE
: BIN_DIALOG_SIZE
);
1506 off
= resid_to_bin (wrbfd
, off
, dialog
->menu
);
1507 off
= resid_to_bin (wrbfd
, off
, dialog
->class);
1508 off
= unicode_to_bin (wrbfd
, off
, dialog
->caption
);
1510 if ((dialog
->style
& DS_SETFONT
) != 0)
1516 struct bin_dialogfont bdf
;
1517 windres_put_16 (wrbfd
, bdf
.pointsize
, dialog
->pointsize
);
1518 set_windres_bfd_content (wrbfd
, &bdf
, off
, BIN_DIALOGFONT_SIZE
);
1522 struct bin_dialogexfont bdxf
;
1523 windres_put_16 (wrbfd
, bdxf
.pointsize
, dialog
->pointsize
);
1524 windres_put_16 (wrbfd
, bdxf
.weight
, (dialog
->ex
== NULL
? 0 : dialog
->ex
->weight
));
1525 windres_put_8 (wrbfd
, bdxf
.italic
, (dialog
->ex
== NULL
? 0 : dialog
->ex
->italic
));
1526 windres_put_8 (wrbfd
, bdxf
.charset
, (dialog
->ex
== NULL
? 1 : dialog
->ex
->charset
));
1527 set_windres_bfd_content (wrbfd
, &bdxf
, off
, BIN_DIALOGEXFONT_SIZE
);
1530 off
+= (dialogex
? BIN_DIALOGEXFONT_SIZE
: BIN_DIALOGFONT_SIZE
);
1531 off
= unicode_to_bin (wrbfd
, off
, dialog
->font
);
1533 for (c
= 0, dc
= dialog
->controls
; dc
!= NULL
; dc
= dc
->next
, c
++)
1535 bfd_byte dc_rclen
[2];
1537 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1542 struct bin_dialog_control bdc
;
1544 windres_put_32 (wrbfd
, bdc
.style
, dc
->style
);
1545 windres_put_32 (wrbfd
, bdc
.exstyle
, dc
->exstyle
);
1546 windres_put_16 (wrbfd
, bdc
.x
, dc
->x
);
1547 windres_put_16 (wrbfd
, bdc
.y
, dc
->y
);
1548 windres_put_16 (wrbfd
, bdc
.width
, dc
->width
);
1549 windres_put_16 (wrbfd
, bdc
.height
, dc
->height
);
1550 windres_put_16 (wrbfd
, bdc
.id
, dc
->id
);
1551 set_windres_bfd_content (wrbfd
, &bdc
, off
, BIN_DIALOG_CONTROL_SIZE
);
1555 struct bin_dialogex_control bdc
;
1557 windres_put_32 (wrbfd
, bdc
.help
, dc
->help
);
1558 windres_put_32 (wrbfd
, bdc
.exstyle
, dc
->exstyle
);
1559 windres_put_32 (wrbfd
, bdc
.style
, dc
->style
);
1560 windres_put_16 (wrbfd
, bdc
.x
, dc
->x
);
1561 windres_put_16 (wrbfd
, bdc
.y
, dc
->y
);
1562 windres_put_16 (wrbfd
, bdc
.width
, dc
->width
);
1563 windres_put_16 (wrbfd
, bdc
.height
, dc
->height
);
1564 windres_put_32 (wrbfd
, bdc
.id
, dc
->id
);
1565 set_windres_bfd_content (wrbfd
, &bdc
, off
, BIN_DIALOGEX_CONTROL_SIZE
);
1568 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_CONTROL_SIZE
: BIN_DIALOG_CONTROL_SIZE
);
1570 off
= resid_to_bin (wrbfd
, off
, dc
->class);
1571 off
= resid_to_bin (wrbfd
, off
, dc
->text
);
1573 marker
= off
; /* Save two bytes for size of optional data. */
1576 if (dc
->data
== NULL
)
1579 windres_put_16 (wrbfd
, dc_rclen
, 0);
1583 rc_uint_type saved_off
= off
;
1584 rc_uint_type old_off
;
1585 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1588 off
= res_to_bin_rcdata (wrbfd
, off
, dc
->data
);
1589 if ((off
- old_off
) == 0)
1590 old_off
= off
= saved_off
;
1592 windres_put_16 (wrbfd
, dc_rclen
, off
- old_off
);
1595 set_windres_bfd_content (wrbfd
, dc_rclen
, marker
, 2);
1600 windres_put_16 (wrbfd
, (dialogex
!= 0 ? bdx
.off
: bd
.off
), c
);
1602 set_windres_bfd_content (wrbfd
, &bd
, start
, BIN_DIALOG_SIZE
);
1604 set_windres_bfd_content (wrbfd
, &bdx
, start
, BIN_DIALOGEX_SIZE
);
1610 /* Convert a fontdir resource to binary. */
1612 res_to_bin_fontdir (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_fontdir
*fontdirs
)
1616 const rc_fontdir
*fd
;
1621 for (c
= 0, fd
= fontdirs
; fd
!= NULL
; fd
= fd
->next
, c
++)
1626 windres_put_16 (wrbfd
, d
, fd
->index
);
1627 set_windres_bfd_content (wrbfd
, d
, off
, 2);
1629 set_windres_bfd_content (wrbfd
, fd
->data
, off
+ 2, fd
->length
);
1631 off
+= (rc_uint_type
) fd
->length
+ 2;
1637 windres_put_16 (wrbfd
, d
, c
);
1638 set_windres_bfd_content (wrbfd
, d
, start
, 2);
1643 /* Convert a group icon resource to binary. */
1646 res_to_bin_group_icon (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_group_icon
*group_icons
)
1649 struct bin_group_icon bgi
;
1651 const rc_group_icon
*gi
;
1654 off
+= BIN_GROUP_ICON_SIZE
;
1656 for (c
= 0, gi
= group_icons
; gi
!= NULL
; gi
= gi
->next
, c
++)
1658 struct bin_group_icon_item bgii
;
1662 windres_put_8 (wrbfd
, bgii
.width
, gi
->width
);
1663 windres_put_8 (wrbfd
, bgii
.height
, gi
->height
);
1664 windres_put_8 (wrbfd
, bgii
.colors
, gi
->colors
);
1665 windres_put_8 (wrbfd
, bgii
.pad
, 0);
1666 windres_put_16 (wrbfd
, bgii
.planes
, gi
->planes
);
1667 windres_put_16 (wrbfd
, bgii
.bits
, gi
->bits
);
1668 windres_put_32 (wrbfd
, bgii
.bytes
, gi
->bytes
);
1669 windres_put_16 (wrbfd
, bgii
.index
, gi
->index
);
1670 set_windres_bfd_content (wrbfd
, &bgii
, off
, BIN_GROUP_ICON_ITEM_SIZE
);
1672 off
+= BIN_GROUP_ICON_ITEM_SIZE
;
1677 windres_put_16 (wrbfd
, bgi
.sig1
, 0);
1678 windres_put_16 (wrbfd
, bgi
.sig2
, 1);
1679 windres_put_16 (wrbfd
, bgi
.count
, c
);
1680 set_windres_bfd_content (wrbfd
, &bgi
, start
, BIN_GROUP_ICON_SIZE
);
1685 /* Convert a menu resource to binary. */
1688 res_to_bin_menu (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menu
*menu
)
1692 menuex
= extended_menu (menu
);
1699 windres_put_16 (wrbfd
, bm
.sig1
, 0);
1700 windres_put_16 (wrbfd
, bm
.sig2
, 0);
1701 set_windres_bfd_content (wrbfd
, &bm
, off
, BIN_MENU_SIZE
);
1705 struct bin_menuex bm
;
1706 windres_put_16 (wrbfd
, bm
.sig1
, 1);
1707 windres_put_16 (wrbfd
, bm
.sig2
, 4);
1708 windres_put_32 (wrbfd
, bm
.help
, menu
->help
);
1709 set_windres_bfd_content (wrbfd
, &bm
, off
, BIN_MENUEX_SIZE
);
1712 off
+= (menuex
!= 0 ? BIN_MENUEX_SIZE
: BIN_MENU_SIZE
);
1715 off
= res_to_bin_menuitems (wrbfd
, off
, menu
->items
);
1719 off
= res_to_bin_menuexitems (wrbfd
, off
, menu
->items
);
1724 /* Convert menu items to binary. */
1727 res_to_bin_menuitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1729 const rc_menuitem
*mi
;
1731 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1733 struct bin_menuitem bmi
;
1737 if (mi
->next
== NULL
)
1738 flags
|= MENUITEM_ENDMENU
;
1739 if (mi
->popup
!= NULL
)
1740 flags
|= MENUITEM_POPUP
;
1744 windres_put_16 (wrbfd
, bmi
.flags
, flags
);
1745 if (mi
->popup
== NULL
)
1746 windres_put_16 (wrbfd
, bmi
.id
, mi
->id
);
1747 set_windres_bfd_content (wrbfd
, &bmi
, off
,
1748 mi
->popup
== NULL
? BIN_MENUITEM_SIZE
1749 : BIN_MENUITEM_POPUP_SIZE
);
1751 off
+= (mi
->popup
== NULL
? BIN_MENUITEM_SIZE
: BIN_MENUITEM_POPUP_SIZE
);
1753 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1755 if (mi
->popup
!= NULL
)
1757 off
= res_to_bin_menuitems (wrbfd
, off
, mi
->popup
);
1763 /* Convert menuex items to binary. */
1766 res_to_bin_menuexitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1768 rc_uint_type off_delta
= off
;
1769 const rc_menuitem
*mi
;
1771 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1773 struct bin_menuitemex bmi
;
1776 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1779 if (mi
->next
== NULL
)
1781 if (mi
->popup
!= NULL
)
1786 windres_put_32 (wrbfd
, bmi
.type
, mi
->type
);
1787 windres_put_32 (wrbfd
, bmi
.state
, mi
->state
);
1788 windres_put_32 (wrbfd
, bmi
.id
, mi
->id
);
1789 windres_put_16 (wrbfd
, bmi
.flags
, flags
);
1790 set_windres_bfd_content (wrbfd
, &bmi
, off
, BIN_MENUITEMEX_SIZE
);
1792 off
+= BIN_MENUITEMEX_SIZE
;
1794 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1796 if (mi
->popup
!= NULL
)
1800 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1804 windres_put_32 (wrbfd
, help
, mi
->help
);
1805 set_windres_bfd_content (wrbfd
, help
, off
, 4);
1808 off
= res_to_bin_menuexitems (wrbfd
, off
, mi
->popup
);
1814 /* Convert an rcdata resource to binary. This is also used to convert
1815 other information which happens to be stored in rc_rcdata_item lists
1819 res_to_bin_rcdata (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_rcdata_item
*items
)
1821 const rc_rcdata_item
*ri
;
1823 for (ri
= items
; ri
!= NULL
; ri
= ri
->next
)
1837 len
= ri
->u
.string
.length
;
1839 case RCDATA_WSTRING
:
1840 len
= ri
->u
.wstring
.length
* sizeof (unichar
);
1843 len
= ri
->u
.buffer
.length
;
1849 bfd_byte
*hp
= &h
[0];
1853 windres_put_16 (wrbfd
, hp
, ri
->u
.word
);
1856 windres_put_32 (wrbfd
, hp
, ri
->u
.dword
);
1859 hp
= (bfd_byte
*) ri
->u
.string
.s
;
1861 case RCDATA_WSTRING
:
1865 hp
= (bfd_byte
*) reswr_alloc (len
);
1866 for (i
= 0; i
< ri
->u
.wstring
.length
; i
++)
1867 windres_put_16 (wrbfd
, hp
+ i
* sizeof (unichar
), ri
->u
.wstring
.w
[i
]);
1871 hp
= (bfd_byte
*) ri
->u
.buffer
.data
;
1874 set_windres_bfd_content (wrbfd
, hp
, off
, len
);
1881 /* Convert a stringtable resource to binary. */
1884 res_to_bin_stringtable (windres_bfd
*wrbfd
, rc_uint_type off
,
1885 const rc_stringtable
*st
)
1889 for (i
= 0; i
< 16; i
++)
1891 rc_uint_type slen
, length
;
1894 slen
= (rc_uint_type
) st
->strings
[i
].length
;
1895 if (slen
== 0xffffffff) slen
= 0;
1896 s
= st
->strings
[i
].string
;
1898 length
= 2 + slen
* 2;
1904 hp
= (bfd_byte
*) reswr_alloc (length
);
1905 windres_put_16 (wrbfd
, hp
, slen
);
1907 for (j
= 0; j
< slen
; j
++)
1908 windres_put_16 (wrbfd
, hp
+ 2 + j
* 2, s
[j
]);
1909 set_windres_bfd_content (wrbfd
, hp
, off
, length
);
1916 /* Convert an ASCII string to a unicode binary string. This always
1917 returns exactly one bindata structure. */
1920 string_to_unicode_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const char *s
)
1924 len
= (rc_uint_type
) strlen (s
);
1931 hp
= (bfd_byte
*) reswr_alloc ((len
+ 1) * sizeof (unichar
));
1933 for (i
= 0; i
< len
; i
++)
1934 windres_put_16 (wrbfd
, hp
+ i
* 2, s
[i
]);
1935 windres_put_16 (wrbfd
, hp
+ i
* 2, 0);
1936 set_windres_bfd_content (wrbfd
, hp
, off
, (len
+ 1) * sizeof (unichar
));
1938 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1943 res_to_bin_toolbar (windres_bfd
*wrbfd
, rc_uint_type off
, rc_toolbar
*tb
)
1947 struct bin_toolbar bt
;
1948 windres_put_32 (wrbfd
, bt
.button_width
, tb
->button_width
);
1949 windres_put_32 (wrbfd
, bt
.button_height
, tb
->button_height
);
1950 windres_put_32 (wrbfd
, bt
.nitems
, tb
->nitems
);
1951 set_windres_bfd_content (wrbfd
, &bt
, off
, BIN_TOOLBAR_SIZE
);
1954 rc_toolbar_item
*it
;
1958 ids
= (bfd_byte
*) reswr_alloc (tb
->nitems
* 4);
1962 windres_put_32 (wrbfd
, ids
+ i
, it
->id
.u
.id
);
1966 set_windres_bfd_content (wrbfd
, ids
, off
+ BIN_TOOLBAR_SIZE
, i
);
1969 off
+= BIN_TOOLBAR_SIZE
+ tb
->nitems
* 4;
1974 /* Convert a versioninfo resource to binary. */
1977 res_to_bin_versioninfo (windres_bfd
*wrbfd
, rc_uint_type off
,
1978 const rc_versioninfo
*versioninfo
)
1980 rc_uint_type off_delta
= off
;
1982 struct bin_versioninfo bvi
;
1986 off
+= BIN_VERSIONINFO_SIZE
;
1987 off
= string_to_unicode_bin (wrbfd
, off
, "VS_VERSION_INFO");
1988 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1990 if (versioninfo
->fixed
!= NULL
)
1994 struct bin_fixed_versioninfo bfv
;
1995 const rc_fixed_versioninfo
*fi
;
1997 fi
= versioninfo
->fixed
;
1998 windres_put_32 (wrbfd
, bfv
.sig1
, 0xfeef04bd);
1999 windres_put_32 (wrbfd
, bfv
.sig2
, 0x10000);
2000 windres_put_32 (wrbfd
, bfv
.file_version
, fi
->file_version_ms
);
2001 windres_put_32 (wrbfd
, bfv
.file_version_ls
, fi
->file_version_ls
);
2002 windres_put_32 (wrbfd
, bfv
.product_version_ms
, fi
->product_version_ms
);
2003 windres_put_32 (wrbfd
, bfv
.product_version_ls
, fi
->product_version_ls
);
2004 windres_put_32 (wrbfd
, bfv
.file_flags_mask
, fi
->file_flags_mask
);
2005 windres_put_32 (wrbfd
, bfv
.file_flags
, fi
->file_flags
);
2006 windres_put_32 (wrbfd
, bfv
.file_os
, fi
->file_os
);
2007 windres_put_32 (wrbfd
, bfv
.file_type
, fi
->file_type
);
2008 windres_put_32 (wrbfd
, bfv
.file_subtype
, fi
->file_subtype
);
2009 windres_put_32 (wrbfd
, bfv
.file_date_ms
, fi
->file_date_ms
);
2010 windres_put_32 (wrbfd
, bfv
.file_date_ls
, fi
->file_date_ls
);
2011 set_windres_bfd_content (wrbfd
, &bfv
, off
, BIN_FIXED_VERSIONINFO_SIZE
);
2013 off
+= BIN_FIXED_VERSIONINFO_SIZE
;
2016 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2018 struct bin_ver_info bv
;
2019 rc_uint_type bv_off
;
2021 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2025 off
+= BIN_VER_INFO_SIZE
;
2031 case VERINFO_STRING
:
2033 const rc_ver_stringtable
*vst
;
2035 off
= string_to_unicode_bin (wrbfd
, off
, "StringFileInfo");
2037 if (!vi
->u
.string
.stringtables
)
2038 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2040 for (vst
= vi
->u
.string
.stringtables
; vst
!= NULL
; vst
= vst
->next
)
2042 struct bin_ver_info bvst
;
2043 rc_uint_type vst_off
;
2044 const rc_ver_stringinfo
*vs
;
2046 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2049 off
+= BIN_VER_INFO_SIZE
;
2051 off
= unicode_to_bin (wrbfd
, off
, vst
->language
);
2053 for (vs
= vst
->strings
; vs
!= NULL
; vs
= vs
->next
)
2055 struct bin_ver_info bvs
;
2056 rc_uint_type vs_off
, str_off
;
2058 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2061 off
+= BIN_VER_INFO_SIZE
;
2063 off
= unicode_to_bin (wrbfd
, off
, vs
->key
);
2065 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2068 off
= unicode_to_bin (wrbfd
, off
, vs
->value
);
2072 windres_put_16 (wrbfd
, bvs
.size
, off
- vs_off
);
2073 windres_put_16 (wrbfd
, bvs
.sig1
, (off
- str_off
) / 2);
2074 windres_put_16 (wrbfd
, bvs
.sig2
, 1);
2075 set_windres_bfd_content (wrbfd
, &bvs
, vs_off
,
2082 windres_put_16 (wrbfd
, bvst
.size
, off
- vst_off
);
2083 windres_put_16 (wrbfd
, bvst
.sig1
, 0);
2084 windres_put_16 (wrbfd
, bvst
.sig2
, 1);
2085 set_windres_bfd_content (wrbfd
, &bvst
, vst_off
,
2094 rc_uint_type vvd_off
, vvvd_off
;
2095 struct bin_ver_info bvvd
;
2096 const rc_ver_varinfo
*vv
;
2098 off
= string_to_unicode_bin (wrbfd
, off
, "VarFileInfo");
2100 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2103 off
+= BIN_VER_INFO_SIZE
;
2105 off
= unicode_to_bin (wrbfd
, off
, vi
->u
.var
.key
);
2107 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2111 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2117 windres_put_16 (wrbfd
, &vvsd
[0], vv
->language
);
2118 windres_put_16 (wrbfd
, &vvsd
[2], vv
->charset
);
2119 set_windres_bfd_content (wrbfd
, vvsd
, off
, 4);
2125 windres_put_16 (wrbfd
, bvvd
.size
, off
- vvd_off
);
2126 windres_put_16 (wrbfd
, bvvd
.sig1
, off
- vvvd_off
);
2127 windres_put_16 (wrbfd
, bvvd
.sig2
, 0);
2128 set_windres_bfd_content (wrbfd
, &bvvd
, vvd_off
,
2138 windres_put_16 (wrbfd
, bv
.size
, off
- bv_off
);
2139 windres_put_16 (wrbfd
, bv
.sig1
, 0);
2140 windres_put_16 (wrbfd
, bv
.sig2
, 1);
2141 set_windres_bfd_content (wrbfd
, &bv
, bv_off
,
2148 windres_put_16 (wrbfd
, bvi
.size
, off
- start
);
2149 windres_put_16 (wrbfd
, bvi
.fixed_size
,
2150 versioninfo
->fixed
== NULL
? 0
2151 : BIN_FIXED_VERSIONINFO_SIZE
);
2152 windres_put_16 (wrbfd
, bvi
.sig2
, 0);
2153 set_windres_bfd_content (wrbfd
, &bvi
, start
, BIN_VER_INFO_SIZE
);
2158 /* Convert a generic resource to binary. */
2161 res_to_bin_generic (windres_bfd
*wrbfd
, rc_uint_type off
, rc_uint_type length
,
2162 const bfd_byte
*data
)
2164 if (wrbfd
&& length
!= 0)
2165 set_windres_bfd_content (wrbfd
, data
, off
, length
);
2166 return off
+ (rc_uint_type
) length
;