1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright (C) 1997-2023 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
*);
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
);
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 if (length
< off
+ datalen
)
578 toosmall (_("dialog control data"));
580 dc
->data
= ((rc_rcdata_item
*)
581 res_alloc (sizeof (rc_rcdata_item
)));
582 dc
->data
->next
= NULL
;
583 dc
->data
->type
= RCDATA_BUFFER
;
584 dc
->data
->u
.buffer
.length
= datalen
;
585 dc
->data
->u
.buffer
.data
= data
+ off
;
595 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
596 r
->type
= RES_TYPE_DIALOG
;
602 /* Convert a stringtable resource from binary. */
604 static rc_res_resource
*
605 bin_to_res_string (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
611 st
= (rc_stringtable
*) res_alloc (sizeof (rc_stringtable
));
613 for (i
= 0; i
< 16; i
++)
618 toosmall (_("stringtable string length"));
619 slen
= windres_get_16 (wrbfd
, data
, 2);
620 st
->strings
[i
].length
= slen
;
627 if (length
< 2 + 2 * slen
)
628 toosmall (_("stringtable string"));
630 s
= (unichar
*) res_alloc (slen
* sizeof (unichar
));
631 st
->strings
[i
].string
= s
;
633 for (j
= 0; j
< slen
; j
++)
634 s
[j
] = windres_get_16 (wrbfd
, data
+ 2 + j
* 2, 2);
637 data
+= 2 + 2 * slen
;
638 length
-= 2 + 2 * slen
;
641 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
642 r
->type
= RES_TYPE_STRINGTABLE
;
643 r
->u
.stringtable
= st
;
648 /* Convert a fontdir resource from binary. */
650 static rc_res_resource
*
651 bin_to_res_fontdir (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
654 rc_fontdir
*first
, **pp
;
658 toosmall (_("fontdir header"));
660 c
= windres_get_16 (wrbfd
, data
, 2);
665 for (i
= 0; i
< c
; i
++)
667 const struct bin_fontdir_item
*bfi
;
672 toosmall (_("fontdir"));
674 bfi
= (const struct bin_fontdir_item
*) data
;
675 fd
= (rc_fontdir
*) res_alloc (sizeof *fd
);
676 fd
->index
= windres_get_16 (wrbfd
, bfi
->index
, 2);
678 /* To work out the length of the fontdir data, we must get the
679 length of the device name and face name strings, even though
680 we don't store them in the rc_fontdir. The
681 documentation says that these are NULL terminated char
682 strings, not Unicode strings. */
686 while (off
< length
&& data
[off
] != '\0')
689 toosmall (_("fontdir device name"));
692 while (off
< length
&& data
[off
] != '\0')
695 toosmall (_("fontdir face name"));
705 /* The documentation does not indicate that any rounding is
712 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
713 r
->type
= RES_TYPE_FONTDIR
;
714 r
->u
.fontdir
= first
;
719 /* Convert an accelerators resource from binary. */
721 static rc_res_resource
*
722 bin_to_res_accelerators (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
724 rc_accelerator
*first
, **pp
;
735 toosmall (_("accelerator"));
737 a
= (rc_accelerator
*) res_alloc (sizeof (rc_accelerator
));
739 a
->flags
= windres_get_16 (wrbfd
, data
, 2);
740 a
->key
= windres_get_16 (wrbfd
, data
+ 2, 2);
741 a
->id
= windres_get_16 (wrbfd
, data
+ 4, 2);
747 if ((a
->flags
& ACC_LAST
) != 0)
754 r
= (rc_res_resource
*) res_alloc (sizeof (rc_res_resource
));
755 r
->type
= RES_TYPE_ACCELERATOR
;
761 /* Convert an rcdata resource from binary. */
763 static rc_res_resource
*
764 bin_to_res_rcdata (windres_bfd
*wrbfd ATTRIBUTE_UNUSED
, const bfd_byte
*data
,
765 rc_uint_type length
, int rctyp
)
770 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
773 ri
->type
= RCDATA_BUFFER
;
774 ri
->u
.buffer
.length
= length
;
775 ri
->u
.buffer
.data
= data
;
777 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
784 /* Convert a group cursor resource from binary. */
786 static rc_res_resource
*
787 bin_to_res_group_cursor (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
790 rc_group_cursor
*first
, **pp
;
794 toosmall (_("group cursor header"));
796 type
= windres_get_16 (wrbfd
, data
+ 2, 2);
798 fatal (_("unexpected group cursor type %d"), type
);
800 c
= windres_get_16 (wrbfd
, data
+ 4, 2);
808 for (i
= 0; i
< c
; i
++)
813 toosmall (_("group cursor"));
815 gc
= (rc_group_cursor
*) res_alloc (sizeof *gc
);
817 gc
->width
= windres_get_16 (wrbfd
, data
, 2);
818 gc
->height
= windres_get_16 (wrbfd
, data
+ 2, 2);
819 gc
->planes
= windres_get_16 (wrbfd
, data
+ 4, 2);
820 gc
->bits
= windres_get_16 (wrbfd
, data
+ 6, 2);
821 gc
->bytes
= windres_get_32 (wrbfd
, data
+ 8, 4);
822 gc
->index
= windres_get_16 (wrbfd
, data
+ 12, 2);
832 r
= (rc_res_resource
*) res_alloc (sizeof (rc_res_resource
));
833 r
->type
= RES_TYPE_GROUP_CURSOR
;
834 r
->u
.group_cursor
= first
;
839 /* Convert a group icon resource from binary. */
841 static rc_res_resource
*
842 bin_to_res_group_icon (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
845 rc_group_icon
*first
, **pp
;
849 toosmall (_("group icon header"));
851 type
= windres_get_16 (wrbfd
, data
+ 2, 2);
853 fatal (_("unexpected group icon type %d"), type
);
855 c
= windres_get_16 (wrbfd
, data
+ 4, 2);
863 for (i
= 0; i
< c
; i
++)
868 toosmall (_("group icon"));
870 gi
= (rc_group_icon
*) res_alloc (sizeof (rc_group_icon
));
872 gi
->width
= windres_get_8 (wrbfd
, data
, 1);
873 gi
->height
= windres_get_8 (wrbfd
, data
+ 1, 1);
874 gi
->colors
= windres_get_8 (wrbfd
, data
+ 2, 1);
875 gi
->planes
= windres_get_16 (wrbfd
, data
+ 4, 2);
876 gi
->bits
= windres_get_16 (wrbfd
, data
+ 6, 2);
877 gi
->bytes
= windres_get_32 (wrbfd
, data
+ 8, 4);
878 gi
->index
= windres_get_16 (wrbfd
, data
+ 12, 2);
888 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
889 r
->type
= RES_TYPE_GROUP_ICON
;
890 r
->u
.group_icon
= first
;
895 /* Extract data from a version header. If KEY is not NULL, then the
896 key must be KEY; otherwise, the key is returned in *PKEY. This
897 sets *LEN to the total length, *VALLEN to the value length, *TYPE
898 to the type, and *OFF to the offset to the children. */
901 get_version_header (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
,
902 const char *key
, unichar
**pkey
,
903 rc_uint_type
*len
, rc_uint_type
*vallen
, rc_uint_type
*type
,
909 *len
= (windres_get_16 (wrbfd
, data
, 2) + 3) & ~3;
910 *vallen
= windres_get_16 (wrbfd
, data
+ 2, 2);
911 *type
= windres_get_16 (wrbfd
, data
+ 4, 2);
922 *pkey
= get_unicode (wrbfd
, data
, length
, &sublen
);
923 *off
+= (sublen
+ 1) * sizeof (unichar
);
931 if (windres_get_16 (wrbfd
, data
, 2) != (bfd_byte
) *key
)
932 fatal (_("unexpected version string"));
945 *off
= (*off
+ 3) &~ 3;
948 /* Convert a version resource from binary. */
950 static rc_res_resource
*
951 bin_to_res_version (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
953 rc_uint_type verlen
, vallen
, type
, off
;
954 rc_fixed_versioninfo
*fi
;
955 rc_ver_info
*first
, **pp
;
959 get_version_header (wrbfd
, data
, length
, "VS_VERSION_INFO",
960 (unichar
**) NULL
, &verlen
, &vallen
, &type
, &off
);
962 /* PR 17512: The verlen field does not include padding length. */
964 fatal (_("version length %lu greater than resource length %lu"),
965 (unsigned long) verlen
, (unsigned long) length
);
968 fatal (_("unexpected version type %d"), (int) type
);
970 /* PR 27686: Ignore any padding bytes after the end of the version structure. */
980 unsigned long signature
, fiv
;
983 fatal (_("unexpected fixed version information length %ld"), (long) vallen
);
986 toosmall (_("fixed version info"));
988 signature
= windres_get_32 (wrbfd
, data
, 4);
989 if (signature
!= 0xfeef04bd)
990 fatal (_("unexpected fixed version signature %lu"), signature
);
992 fiv
= windres_get_32 (wrbfd
, data
+ 4, 4);
993 if (fiv
!= 0 && fiv
!= 0x10000)
994 fatal (_("unexpected fixed version info version %lu"), fiv
);
996 fi
= (rc_fixed_versioninfo
*) res_alloc (sizeof (rc_fixed_versioninfo
));
998 fi
->file_version_ms
= windres_get_32 (wrbfd
, data
+ 8, 4);
999 fi
->file_version_ls
= windres_get_32 (wrbfd
, data
+ 12, 4);
1000 fi
->product_version_ms
= windres_get_32 (wrbfd
, data
+ 16, 4);
1001 fi
->product_version_ls
= windres_get_32 (wrbfd
, data
+ 20, 4);
1002 fi
->file_flags_mask
= windres_get_32 (wrbfd
, data
+ 24, 4);
1003 fi
->file_flags
= windres_get_32 (wrbfd
, data
+ 28, 4);
1004 fi
->file_os
= windres_get_32 (wrbfd
, data
+ 32, 4);
1005 fi
->file_type
= windres_get_32 (wrbfd
, data
+ 36, 4);
1006 fi
->file_subtype
= windres_get_32 (wrbfd
, data
+ 40, 4);
1007 fi
->file_date_ms
= windres_get_32 (wrbfd
, data
+ 44, 4);
1008 fi
->file_date_ls
= windres_get_32 (wrbfd
, data
+ 48, 4);
1023 toosmall (_("version var info"));
1025 vi
= (rc_ver_info
*) res_alloc (sizeof (rc_ver_info
));
1027 ch
= windres_get_16 (wrbfd
, data
+ 6, 2);
1031 rc_ver_stringtable
**ppvst
;
1033 vi
->type
= VERINFO_STRING
;
1035 get_version_header (wrbfd
, data
, length
, "StringFileInfo",
1036 (unichar
**) NULL
, &verlen
, &vallen
, &type
,
1040 fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen
);
1047 vi
->u
.string
.stringtables
= NULL
;
1048 ppvst
= &vi
->u
.string
.stringtables
;
1052 rc_ver_stringtable
*vst
;
1053 rc_uint_type stverlen
;
1054 rc_ver_stringinfo
**ppvs
;
1057 toosmall (_("version stringtable"));
1059 vst
= (rc_ver_stringtable
*) res_alloc (sizeof (rc_ver_stringtable
));
1061 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1062 &vst
->language
, &stverlen
, &vallen
, &type
, &off
);
1065 fatal (_("unexpected version stringtable value length %ld"), (long) vallen
);
1073 vst
->strings
= NULL
;
1074 ppvs
= &vst
->strings
;
1076 while (stverlen
> 0)
1078 rc_ver_stringinfo
*vs
;
1079 rc_uint_type sverlen
, vslen
, valoff
;
1082 toosmall (_("version string"));
1084 vs
= (rc_ver_stringinfo
*) res_alloc (sizeof (rc_ver_stringinfo
));
1086 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1087 &vs
->key
, &sverlen
, &vallen
, &type
, &off
);
1092 vs
->value
= get_unicode (wrbfd
, data
, length
, &vslen
);
1093 valoff
= vslen
* 2 + 2;
1094 valoff
= (valoff
+ 3) & ~3;
1096 if (off
+ valoff
!= sverlen
)
1097 fatal (_("unexpected version string length %ld != %ld + %ld"),
1098 (long) sverlen
, (long) off
, (long) valoff
);
1103 if (stverlen
< sverlen
)
1104 fatal (_("unexpected version string length %ld < %ld"),
1105 (long) verlen
, (long) sverlen
);
1106 stverlen
-= sverlen
;
1121 rc_ver_varinfo
**ppvv
;
1123 vi
->type
= VERINFO_VAR
;
1125 get_version_header (wrbfd
, data
, length
, "VarFileInfo",
1126 (unichar
**) NULL
, &verlen
, &vallen
, &type
,
1130 fatal (_("unexpected varfileinfo value length %ld"), (long) vallen
);
1135 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1136 &vi
->u
.var
.key
, &verlen
, &vallen
, &type
, &off
);
1141 vi
->u
.var
.var
= NULL
;
1142 ppvv
= &vi
->u
.var
.var
;
1149 toosmall (_("version varfileinfo"));
1151 vv
= (rc_ver_varinfo
*) res_alloc (sizeof (rc_ver_varinfo
));
1153 vv
->language
= windres_get_16 (wrbfd
, data
, 2);
1154 vv
->charset
= windres_get_16 (wrbfd
, data
+ 2, 2);
1164 fatal (_("unexpected version value length %ld"), (long) vallen
);
1172 /* Padding - skip. */
1174 fatal (_("nul bytes found in version string"));
1177 fatal (_("unexpected version string character: %x"), ch
);
1184 v
= (rc_versioninfo
*) res_alloc (sizeof (rc_versioninfo
));
1188 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1189 r
->type
= RES_TYPE_VERSIONINFO
;
1190 r
->u
.versioninfo
= v
;
1195 /* Convert an arbitrary user defined resource from binary. */
1197 static rc_res_resource
*
1198 bin_to_res_userdata (windres_bfd
*wrbfd ATTRIBUTE_UNUSED
, const bfd_byte
*data
,
1199 rc_uint_type length
)
1204 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1207 ri
->type
= RCDATA_BUFFER
;
1208 ri
->u
.buffer
.length
= length
;
1209 ri
->u
.buffer
.data
= data
;
1211 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1212 r
->type
= RES_TYPE_USERDATA
;
1218 static rc_res_resource
*
1219 bin_to_res_toolbar (windres_bfd
*wrbfd
, const bfd_byte
*data
)
1225 ri
= (rc_toolbar
*) res_alloc (sizeof (rc_toolbar
));
1226 ri
->button_width
= windres_get_32 (wrbfd
, data
, 4);
1227 ri
->button_height
= windres_get_32 (wrbfd
, data
+ 4, 4);
1228 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
;
1241 rc_toolbar_item
*ii
= ri
->items
;
1242 while (ii
->next
!= NULL
)
1250 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1251 r
->type
= RES_TYPE_TOOLBAR
;
1257 /* Local functions used to convert resources to binary format. */
1259 static rc_uint_type
resid_to_bin (windres_bfd
*, rc_uint_type
, rc_res_id
);
1260 static rc_uint_type
unicode_to_bin (windres_bfd
*, rc_uint_type
, const unichar
*);
1261 static rc_uint_type
res_to_bin_accelerator (windres_bfd
*, rc_uint_type
, const rc_accelerator
*);
1262 static rc_uint_type
res_to_bin_cursor (windres_bfd
*, rc_uint_type
, const rc_cursor
*);
1263 static rc_uint_type
res_to_bin_group_cursor (windres_bfd
*, rc_uint_type
, const rc_group_cursor
*);
1264 static rc_uint_type
res_to_bin_dialog (windres_bfd
*, rc_uint_type
, const rc_dialog
*);
1265 static rc_uint_type
res_to_bin_fontdir (windres_bfd
*, rc_uint_type
, const rc_fontdir
*);
1266 static rc_uint_type
res_to_bin_group_icon (windres_bfd
*, rc_uint_type
, const rc_group_icon
*);
1267 static rc_uint_type
res_to_bin_menu (windres_bfd
*, rc_uint_type
, const rc_menu
*);
1268 static rc_uint_type
res_to_bin_menuitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1269 static rc_uint_type
res_to_bin_menuexitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1270 static rc_uint_type
res_to_bin_rcdata (windres_bfd
*, rc_uint_type
, const rc_rcdata_item
*);
1271 static rc_uint_type
res_to_bin_stringtable (windres_bfd
*, rc_uint_type
, const rc_stringtable
*);
1272 static rc_uint_type
string_to_unicode_bin (windres_bfd
*, rc_uint_type
, const char *);
1273 static rc_uint_type
res_to_bin_toolbar (windres_bfd
*, rc_uint_type
, rc_toolbar
*tb
);
1274 static rc_uint_type
res_to_bin_versioninfo (windres_bfd
*, rc_uint_type
, const rc_versioninfo
*);
1275 static rc_uint_type
res_to_bin_generic (windres_bfd
*, rc_uint_type
, rc_uint_type
,
1278 /* Convert a resource to binary. */
1281 res_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_res_resource
*res
)
1285 case RES_TYPE_BITMAP
:
1288 case RES_TYPE_MESSAGETABLE
:
1289 return res_to_bin_generic (wrbfd
, off
, res
->u
.data
.length
, res
->u
.data
.data
);
1290 case RES_TYPE_ACCELERATOR
:
1291 return res_to_bin_accelerator (wrbfd
, off
, res
->u
.acc
);
1292 case RES_TYPE_CURSOR
:
1293 return res_to_bin_cursor (wrbfd
, off
, res
->u
.cursor
);
1294 case RES_TYPE_GROUP_CURSOR
:
1295 return res_to_bin_group_cursor (wrbfd
, off
, res
->u
.group_cursor
);
1296 case RES_TYPE_DIALOG
:
1297 return res_to_bin_dialog (wrbfd
, off
, res
->u
.dialog
);
1298 case RES_TYPE_FONTDIR
:
1299 return res_to_bin_fontdir (wrbfd
, off
, res
->u
.fontdir
);
1300 case RES_TYPE_GROUP_ICON
:
1301 return res_to_bin_group_icon (wrbfd
, off
, res
->u
.group_icon
);
1303 return res_to_bin_menu (wrbfd
, off
, res
->u
.menu
);
1304 case RES_TYPE_STRINGTABLE
:
1305 return res_to_bin_stringtable (wrbfd
, off
, res
->u
.stringtable
);
1306 case RES_TYPE_VERSIONINFO
:
1307 return res_to_bin_versioninfo (wrbfd
, off
, res
->u
.versioninfo
);
1308 case RES_TYPE_TOOLBAR
:
1309 return res_to_bin_toolbar (wrbfd
, off
, res
->u
.toolbar
);
1310 case RES_TYPE_USERDATA
:
1311 case RES_TYPE_RCDATA
:
1313 return res_to_bin_rcdata (wrbfd
, off
, res
->u
.rcdata
);
1317 /* Convert a resource ID to binary. This always returns exactly one
1318 bindata structure. */
1321 resid_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, rc_res_id id
)
1327 struct bin_res_id bri
;
1329 windres_put_16 (wrbfd
, bri
.sig
, 0xffff);
1330 windres_put_16 (wrbfd
, bri
.id
, id
.u
.id
);
1331 set_windres_bfd_content (wrbfd
, &bri
, off
, BIN_RES_ID
);
1337 rc_uint_type len
= (id
.u
.n
.name
? unichar_len (id
.u
.n
.name
) : 0);
1340 bfd_byte
*d
= (bfd_byte
*) reswr_alloc ((len
+ 1) * sizeof (unichar
));
1342 for (i
= 0; i
< len
; i
++)
1343 windres_put_16 (wrbfd
, d
+ (i
* sizeof (unichar
)), id
.u
.n
.name
[i
]);
1344 windres_put_16 (wrbfd
, d
+ (len
* sizeof (unichar
)), 0);
1345 set_windres_bfd_content (wrbfd
, d
, off
, (len
+ 1) * sizeof (unichar
));
1347 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1352 /* Convert a null terminated unicode string to binary. This always
1353 returns exactly one bindata structure. */
1356 unicode_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const unichar
*str
)
1358 rc_uint_type len
= 0;
1361 len
= unichar_len (str
);
1367 d
= (bfd_byte
*) reswr_alloc ( (len
+ 1) * sizeof (unichar
));
1368 for (i
= 0; i
< len
; i
++)
1369 windres_put_16 (wrbfd
, d
+ (i
* sizeof (unichar
)), str
[i
]);
1370 windres_put_16 (wrbfd
, d
+ (len
* sizeof (unichar
)), 0);
1371 set_windres_bfd_content (wrbfd
, d
, off
, (len
+ 1) * sizeof (unichar
));
1373 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1378 /* Convert an accelerator resource to binary. */
1381 res_to_bin_accelerator (windres_bfd
*wrbfd
, rc_uint_type off
,
1382 const rc_accelerator
*accelerators
)
1384 const rc_accelerator
*a
;
1386 for (a
= accelerators
; a
!= NULL
; a
= a
->next
)
1390 struct bin_accelerator ba
;
1392 windres_put_16 (wrbfd
, ba
.flags
, a
->flags
| (a
->next
!= NULL
? 0 : ACC_LAST
));
1393 windres_put_16 (wrbfd
, ba
.key
, a
->key
);
1394 windres_put_16 (wrbfd
, ba
.id
, a
->id
);
1395 windres_put_16 (wrbfd
, ba
.pad
, 0);
1396 set_windres_bfd_content (wrbfd
, &ba
, off
, BIN_ACCELERATOR_SIZE
);
1398 off
+= BIN_ACCELERATOR_SIZE
;
1403 /* Convert a cursor resource to binary. */
1406 res_to_bin_cursor (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_cursor
*c
)
1410 struct bin_cursor bc
;
1412 windres_put_16 (wrbfd
, bc
.xhotspot
, c
->xhotspot
);
1413 windres_put_16 (wrbfd
, bc
.yhotspot
, c
->yhotspot
);
1414 set_windres_bfd_content (wrbfd
, &bc
, off
, BIN_CURSOR_SIZE
);
1416 set_windres_bfd_content (wrbfd
, c
->data
, off
+ BIN_CURSOR_SIZE
, c
->length
);
1418 off
= (off
+ BIN_CURSOR_SIZE
+ (rc_uint_type
) c
->length
);
1422 /* Convert a group cursor resource to binary. */
1425 res_to_bin_group_cursor (windres_bfd
*wrbfd
, rc_uint_type off
,
1426 const rc_group_cursor
*group_cursors
)
1429 const rc_group_cursor
*gc
;
1430 struct bin_group_cursor bgc
;
1431 struct bin_group_cursor_item bgci
;
1432 rc_uint_type start
= off
;
1434 off
+= BIN_GROUP_CURSOR_SIZE
;
1436 for (c
= 0, gc
= group_cursors
; gc
!= NULL
; gc
= gc
->next
, c
++)
1440 windres_put_16 (wrbfd
, bgci
.width
, gc
->width
);
1441 windres_put_16 (wrbfd
, bgci
.height
, gc
->height
);
1442 windres_put_16 (wrbfd
, bgci
.planes
, gc
->planes
);
1443 windres_put_16 (wrbfd
, bgci
.bits
, gc
->bits
);
1444 windres_put_32 (wrbfd
, bgci
.bytes
, gc
->bytes
);
1445 windres_put_16 (wrbfd
, bgci
.index
, gc
->index
);
1446 set_windres_bfd_content (wrbfd
, &bgci
, off
, BIN_GROUP_CURSOR_ITEM_SIZE
);
1449 off
+= BIN_GROUP_CURSOR_ITEM_SIZE
;
1453 windres_put_16 (wrbfd
, bgc
.sig1
, 0);
1454 windres_put_16 (wrbfd
, bgc
.sig2
, 2);
1455 windres_put_16 (wrbfd
, bgc
.nitems
, c
);
1456 set_windres_bfd_content (wrbfd
, &bgc
, start
, BIN_GROUP_CURSOR_SIZE
);
1461 /* Convert a dialog resource to binary. */
1464 res_to_bin_dialog (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_dialog
*dialog
)
1466 rc_uint_type off_delta
;
1467 rc_uint_type start
, marker
;
1470 rc_dialog_control
*dc
;
1471 struct bin_dialogex bdx
;
1472 struct bin_dialog bd
;
1476 dialogex
= extended_dialog (dialog
);
1482 windres_put_32 (wrbfd
, bd
.style
, dialog
->style
);
1483 windres_put_32 (wrbfd
, bd
.exstyle
, dialog
->exstyle
);
1484 windres_put_16 (wrbfd
, bd
.x
, dialog
->x
);
1485 windres_put_16 (wrbfd
, bd
.y
, dialog
->y
);
1486 windres_put_16 (wrbfd
, bd
.width
, dialog
->width
);
1487 windres_put_16 (wrbfd
, bd
.height
, dialog
->height
);
1491 windres_put_16 (wrbfd
, bdx
.sig1
, 1);
1492 windres_put_16 (wrbfd
, bdx
.sig2
, 0xffff);
1493 windres_put_32 (wrbfd
, bdx
.help
, (dialog
->ex
? dialog
->ex
->help
: 0));
1494 windres_put_32 (wrbfd
, bdx
.exstyle
, dialog
->exstyle
);
1495 windres_put_32 (wrbfd
, bdx
.style
, dialog
->style
);
1496 windres_put_16 (wrbfd
, bdx
.x
, dialog
->x
);
1497 windres_put_16 (wrbfd
, bdx
.y
, dialog
->y
);
1498 windres_put_16 (wrbfd
, bdx
.width
, dialog
->width
);
1499 windres_put_16 (wrbfd
, bdx
.height
, dialog
->height
);
1503 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_SIZE
: BIN_DIALOG_SIZE
);
1505 off
= resid_to_bin (wrbfd
, off
, dialog
->menu
);
1506 off
= resid_to_bin (wrbfd
, off
, dialog
->class);
1507 off
= unicode_to_bin (wrbfd
, off
, dialog
->caption
);
1509 if ((dialog
->style
& DS_SETFONT
) != 0)
1515 struct bin_dialogfont bdf
;
1516 windres_put_16 (wrbfd
, bdf
.pointsize
, dialog
->pointsize
);
1517 set_windres_bfd_content (wrbfd
, &bdf
, off
, BIN_DIALOGFONT_SIZE
);
1521 struct bin_dialogexfont bdxf
;
1522 windres_put_16 (wrbfd
, bdxf
.pointsize
, dialog
->pointsize
);
1523 windres_put_16 (wrbfd
, bdxf
.weight
, (dialog
->ex
== NULL
? 0 : dialog
->ex
->weight
));
1524 windres_put_8 (wrbfd
, bdxf
.italic
, (dialog
->ex
== NULL
? 0 : dialog
->ex
->italic
));
1525 windres_put_8 (wrbfd
, bdxf
.charset
, (dialog
->ex
== NULL
? 1 : dialog
->ex
->charset
));
1526 set_windres_bfd_content (wrbfd
, &bdxf
, off
, BIN_DIALOGEXFONT_SIZE
);
1529 off
+= (dialogex
? BIN_DIALOGEXFONT_SIZE
: BIN_DIALOGFONT_SIZE
);
1530 off
= unicode_to_bin (wrbfd
, off
, dialog
->font
);
1532 for (c
= 0, dc
= dialog
->controls
; dc
!= NULL
; dc
= dc
->next
, c
++)
1534 bfd_byte dc_rclen
[2];
1536 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1541 struct bin_dialog_control bdc
;
1543 windres_put_32 (wrbfd
, bdc
.style
, dc
->style
);
1544 windres_put_32 (wrbfd
, bdc
.exstyle
, dc
->exstyle
);
1545 windres_put_16 (wrbfd
, bdc
.x
, dc
->x
);
1546 windres_put_16 (wrbfd
, bdc
.y
, dc
->y
);
1547 windres_put_16 (wrbfd
, bdc
.width
, dc
->width
);
1548 windres_put_16 (wrbfd
, bdc
.height
, dc
->height
);
1549 windres_put_16 (wrbfd
, bdc
.id
, dc
->id
);
1550 set_windres_bfd_content (wrbfd
, &bdc
, off
, BIN_DIALOG_CONTROL_SIZE
);
1554 struct bin_dialogex_control bdc
;
1556 windres_put_32 (wrbfd
, bdc
.help
, dc
->help
);
1557 windres_put_32 (wrbfd
, bdc
.exstyle
, dc
->exstyle
);
1558 windres_put_32 (wrbfd
, bdc
.style
, dc
->style
);
1559 windres_put_16 (wrbfd
, bdc
.x
, dc
->x
);
1560 windres_put_16 (wrbfd
, bdc
.y
, dc
->y
);
1561 windres_put_16 (wrbfd
, bdc
.width
, dc
->width
);
1562 windres_put_16 (wrbfd
, bdc
.height
, dc
->height
);
1563 windres_put_32 (wrbfd
, bdc
.id
, dc
->id
);
1564 set_windres_bfd_content (wrbfd
, &bdc
, off
, BIN_DIALOGEX_CONTROL_SIZE
);
1567 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_CONTROL_SIZE
: BIN_DIALOG_CONTROL_SIZE
);
1569 off
= resid_to_bin (wrbfd
, off
, dc
->class);
1570 off
= resid_to_bin (wrbfd
, off
, dc
->text
);
1572 marker
= off
; /* Save two bytes for size of optional data. */
1575 if (dc
->data
== NULL
)
1578 windres_put_16 (wrbfd
, dc_rclen
, 0);
1582 rc_uint_type saved_off
= off
;
1583 rc_uint_type old_off
;
1586 off
= res_to_bin_rcdata (wrbfd
, off
, dc
->data
);
1587 if ((off
- old_off
) == 0)
1588 old_off
= off
= saved_off
;
1590 windres_put_16 (wrbfd
, dc_rclen
, off
- old_off
);
1593 set_windres_bfd_content (wrbfd
, dc_rclen
, marker
, 2);
1598 windres_put_16 (wrbfd
, (dialogex
!= 0 ? bdx
.off
: bd
.off
), c
);
1600 set_windres_bfd_content (wrbfd
, &bd
, start
, BIN_DIALOG_SIZE
);
1602 set_windres_bfd_content (wrbfd
, &bdx
, start
, BIN_DIALOGEX_SIZE
);
1608 /* Convert a fontdir resource to binary. */
1610 res_to_bin_fontdir (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_fontdir
*fontdirs
)
1614 const rc_fontdir
*fd
;
1619 for (c
= 0, fd
= fontdirs
; fd
!= NULL
; fd
= fd
->next
, c
++)
1624 windres_put_16 (wrbfd
, d
, fd
->index
);
1625 set_windres_bfd_content (wrbfd
, d
, off
, 2);
1627 set_windres_bfd_content (wrbfd
, fd
->data
, off
+ 2, fd
->length
);
1629 off
+= (rc_uint_type
) fd
->length
+ 2;
1635 windres_put_16 (wrbfd
, d
, c
);
1636 set_windres_bfd_content (wrbfd
, d
, start
, 2);
1641 /* Convert a group icon resource to binary. */
1644 res_to_bin_group_icon (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_group_icon
*group_icons
)
1647 struct bin_group_icon bgi
;
1649 const rc_group_icon
*gi
;
1652 off
+= BIN_GROUP_ICON_SIZE
;
1654 for (c
= 0, gi
= group_icons
; gi
!= NULL
; gi
= gi
->next
, c
++)
1656 struct bin_group_icon_item bgii
;
1660 windres_put_8 (wrbfd
, bgii
.width
, gi
->width
);
1661 windres_put_8 (wrbfd
, bgii
.height
, gi
->height
);
1662 windres_put_8 (wrbfd
, bgii
.colors
, gi
->colors
);
1663 windres_put_8 (wrbfd
, bgii
.pad
, 0);
1664 windres_put_16 (wrbfd
, bgii
.planes
, gi
->planes
);
1665 windres_put_16 (wrbfd
, bgii
.bits
, gi
->bits
);
1666 windres_put_32 (wrbfd
, bgii
.bytes
, gi
->bytes
);
1667 windres_put_16 (wrbfd
, bgii
.index
, gi
->index
);
1668 set_windres_bfd_content (wrbfd
, &bgii
, off
, BIN_GROUP_ICON_ITEM_SIZE
);
1670 off
+= BIN_GROUP_ICON_ITEM_SIZE
;
1675 windres_put_16 (wrbfd
, bgi
.sig1
, 0);
1676 windres_put_16 (wrbfd
, bgi
.sig2
, 1);
1677 windres_put_16 (wrbfd
, bgi
.count
, c
);
1678 set_windres_bfd_content (wrbfd
, &bgi
, start
, BIN_GROUP_ICON_SIZE
);
1683 /* Convert a menu resource to binary. */
1686 res_to_bin_menu (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menu
*menu
)
1690 menuex
= extended_menu (menu
);
1697 windres_put_16 (wrbfd
, bm
.sig1
, 0);
1698 windres_put_16 (wrbfd
, bm
.sig2
, 0);
1699 set_windres_bfd_content (wrbfd
, &bm
, off
, BIN_MENU_SIZE
);
1703 struct bin_menuex bm
;
1704 windres_put_16 (wrbfd
, bm
.sig1
, 1);
1705 windres_put_16 (wrbfd
, bm
.sig2
, 4);
1706 windres_put_32 (wrbfd
, bm
.help
, menu
->help
);
1707 set_windres_bfd_content (wrbfd
, &bm
, off
, BIN_MENUEX_SIZE
);
1710 off
+= (menuex
!= 0 ? BIN_MENUEX_SIZE
: BIN_MENU_SIZE
);
1713 off
= res_to_bin_menuitems (wrbfd
, off
, menu
->items
);
1717 off
= res_to_bin_menuexitems (wrbfd
, off
, menu
->items
);
1722 /* Convert menu items to binary. */
1725 res_to_bin_menuitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1727 const rc_menuitem
*mi
;
1729 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1731 struct bin_menuitem bmi
;
1735 if (mi
->next
== NULL
)
1736 flags
|= MENUITEM_ENDMENU
;
1737 if (mi
->popup
!= NULL
)
1738 flags
|= MENUITEM_POPUP
;
1742 windres_put_16 (wrbfd
, bmi
.flags
, flags
);
1743 if (mi
->popup
== NULL
)
1744 windres_put_16 (wrbfd
, bmi
.id
, mi
->id
);
1745 set_windres_bfd_content (wrbfd
, &bmi
, off
,
1746 mi
->popup
== NULL
? BIN_MENUITEM_SIZE
1747 : BIN_MENUITEM_POPUP_SIZE
);
1749 off
+= (mi
->popup
== NULL
? BIN_MENUITEM_SIZE
: BIN_MENUITEM_POPUP_SIZE
);
1751 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1753 if (mi
->popup
!= NULL
)
1755 off
= res_to_bin_menuitems (wrbfd
, off
, mi
->popup
);
1761 /* Convert menuex items to binary. */
1764 res_to_bin_menuexitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1766 rc_uint_type off_delta
= off
;
1767 const rc_menuitem
*mi
;
1769 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1771 struct bin_menuitemex bmi
;
1774 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1777 if (mi
->next
== NULL
)
1779 if (mi
->popup
!= NULL
)
1784 windres_put_32 (wrbfd
, bmi
.type
, mi
->type
);
1785 windres_put_32 (wrbfd
, bmi
.state
, mi
->state
);
1786 windres_put_32 (wrbfd
, bmi
.id
, mi
->id
);
1787 windres_put_16 (wrbfd
, bmi
.flags
, flags
);
1788 set_windres_bfd_content (wrbfd
, &bmi
, off
, BIN_MENUITEMEX_SIZE
);
1790 off
+= BIN_MENUITEMEX_SIZE
;
1792 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1794 if (mi
->popup
!= NULL
)
1798 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1802 windres_put_32 (wrbfd
, help
, mi
->help
);
1803 set_windres_bfd_content (wrbfd
, help
, off
, 4);
1806 off
= res_to_bin_menuexitems (wrbfd
, off
, mi
->popup
);
1812 /* Convert an rcdata resource to binary. This is also used to convert
1813 other information which happens to be stored in rc_rcdata_item lists
1817 res_to_bin_rcdata (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_rcdata_item
*items
)
1819 const rc_rcdata_item
*ri
;
1821 for (ri
= items
; ri
!= NULL
; ri
= ri
->next
)
1835 len
= ri
->u
.string
.length
;
1837 case RCDATA_WSTRING
:
1838 len
= ri
->u
.wstring
.length
* sizeof (unichar
);
1841 len
= ri
->u
.buffer
.length
;
1847 bfd_byte
*hp
= &h
[0];
1851 windres_put_16 (wrbfd
, hp
, ri
->u
.word
);
1854 windres_put_32 (wrbfd
, hp
, ri
->u
.dword
);
1857 hp
= (bfd_byte
*) ri
->u
.string
.s
;
1859 case RCDATA_WSTRING
:
1863 hp
= (bfd_byte
*) reswr_alloc (len
);
1864 for (i
= 0; i
< ri
->u
.wstring
.length
; i
++)
1865 windres_put_16 (wrbfd
, hp
+ i
* sizeof (unichar
), ri
->u
.wstring
.w
[i
]);
1869 hp
= (bfd_byte
*) ri
->u
.buffer
.data
;
1872 set_windres_bfd_content (wrbfd
, hp
, off
, len
);
1879 /* Convert a stringtable resource to binary. */
1882 res_to_bin_stringtable (windres_bfd
*wrbfd
, rc_uint_type off
,
1883 const rc_stringtable
*st
)
1887 for (i
= 0; i
< 16; i
++)
1889 rc_uint_type slen
, length
;
1892 slen
= (rc_uint_type
) st
->strings
[i
].length
;
1893 if (slen
== 0xffffffff) slen
= 0;
1894 s
= st
->strings
[i
].string
;
1896 length
= 2 + slen
* 2;
1902 hp
= (bfd_byte
*) reswr_alloc (length
);
1903 windres_put_16 (wrbfd
, hp
, slen
);
1905 for (j
= 0; j
< slen
; j
++)
1906 windres_put_16 (wrbfd
, hp
+ 2 + j
* 2, s
[j
]);
1907 set_windres_bfd_content (wrbfd
, hp
, off
, length
);
1914 /* Convert an ASCII string to a unicode binary string. This always
1915 returns exactly one bindata structure. */
1918 string_to_unicode_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const char *s
)
1922 len
= (rc_uint_type
) strlen (s
);
1929 hp
= (bfd_byte
*) reswr_alloc ((len
+ 1) * sizeof (unichar
));
1931 for (i
= 0; i
< len
; i
++)
1932 windres_put_16 (wrbfd
, hp
+ i
* 2, s
[i
]);
1933 windres_put_16 (wrbfd
, hp
+ i
* 2, 0);
1934 set_windres_bfd_content (wrbfd
, hp
, off
, (len
+ 1) * sizeof (unichar
));
1936 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1941 res_to_bin_toolbar (windres_bfd
*wrbfd
, rc_uint_type off
, rc_toolbar
*tb
)
1945 struct bin_toolbar bt
;
1946 windres_put_32 (wrbfd
, bt
.button_width
, tb
->button_width
);
1947 windres_put_32 (wrbfd
, bt
.button_height
, tb
->button_height
);
1948 windres_put_32 (wrbfd
, bt
.nitems
, tb
->nitems
);
1949 set_windres_bfd_content (wrbfd
, &bt
, off
, BIN_TOOLBAR_SIZE
);
1952 rc_toolbar_item
*it
;
1956 ids
= (bfd_byte
*) reswr_alloc (tb
->nitems
* 4);
1960 windres_put_32 (wrbfd
, ids
+ i
, it
->id
.u
.id
);
1964 set_windres_bfd_content (wrbfd
, ids
, off
+ BIN_TOOLBAR_SIZE
, i
);
1967 off
+= BIN_TOOLBAR_SIZE
+ tb
->nitems
* 4;
1972 /* Convert a versioninfo resource to binary. */
1975 res_to_bin_versioninfo (windres_bfd
*wrbfd
, rc_uint_type off
,
1976 const rc_versioninfo
*versioninfo
)
1978 rc_uint_type off_delta
= off
;
1980 struct bin_versioninfo bvi
;
1984 off
+= BIN_VERSIONINFO_SIZE
;
1985 off
= string_to_unicode_bin (wrbfd
, off
, "VS_VERSION_INFO");
1986 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1988 if (versioninfo
->fixed
!= NULL
)
1992 struct bin_fixed_versioninfo bfv
;
1993 const rc_fixed_versioninfo
*fi
;
1995 fi
= versioninfo
->fixed
;
1996 windres_put_32 (wrbfd
, bfv
.sig1
, 0xfeef04bd);
1997 windres_put_32 (wrbfd
, bfv
.sig2
, 0x10000);
1998 windres_put_32 (wrbfd
, bfv
.file_version
, fi
->file_version_ms
);
1999 windres_put_32 (wrbfd
, bfv
.file_version_ls
, fi
->file_version_ls
);
2000 windres_put_32 (wrbfd
, bfv
.product_version_ms
, fi
->product_version_ms
);
2001 windres_put_32 (wrbfd
, bfv
.product_version_ls
, fi
->product_version_ls
);
2002 windres_put_32 (wrbfd
, bfv
.file_flags_mask
, fi
->file_flags_mask
);
2003 windres_put_32 (wrbfd
, bfv
.file_flags
, fi
->file_flags
);
2004 windres_put_32 (wrbfd
, bfv
.file_os
, fi
->file_os
);
2005 windres_put_32 (wrbfd
, bfv
.file_type
, fi
->file_type
);
2006 windres_put_32 (wrbfd
, bfv
.file_subtype
, fi
->file_subtype
);
2007 windres_put_32 (wrbfd
, bfv
.file_date_ms
, fi
->file_date_ms
);
2008 windres_put_32 (wrbfd
, bfv
.file_date_ls
, fi
->file_date_ls
);
2009 set_windres_bfd_content (wrbfd
, &bfv
, off
, BIN_FIXED_VERSIONINFO_SIZE
);
2011 off
+= BIN_FIXED_VERSIONINFO_SIZE
;
2014 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2016 struct bin_ver_info bv
;
2017 rc_uint_type bv_off
;
2019 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2023 off
+= BIN_VER_INFO_SIZE
;
2029 case VERINFO_STRING
:
2031 const rc_ver_stringtable
*vst
;
2033 off
= string_to_unicode_bin (wrbfd
, off
, "StringFileInfo");
2035 if (!vi
->u
.string
.stringtables
)
2036 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2038 for (vst
= vi
->u
.string
.stringtables
; vst
!= NULL
; vst
= vst
->next
)
2040 struct bin_ver_info bvst
;
2041 rc_uint_type vst_off
;
2042 const rc_ver_stringinfo
*vs
;
2044 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2047 off
+= BIN_VER_INFO_SIZE
;
2049 off
= unicode_to_bin (wrbfd
, off
, vst
->language
);
2051 for (vs
= vst
->strings
; vs
!= NULL
; vs
= vs
->next
)
2053 struct bin_ver_info bvs
;
2054 rc_uint_type vs_off
, str_off
;
2056 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2059 off
+= BIN_VER_INFO_SIZE
;
2061 off
= unicode_to_bin (wrbfd
, off
, vs
->key
);
2063 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2066 off
= unicode_to_bin (wrbfd
, off
, vs
->value
);
2070 windres_put_16 (wrbfd
, bvs
.size
, off
- vs_off
);
2071 windres_put_16 (wrbfd
, bvs
.sig1
, (off
- str_off
) / 2);
2072 windres_put_16 (wrbfd
, bvs
.sig2
, 1);
2073 set_windres_bfd_content (wrbfd
, &bvs
, vs_off
,
2080 windres_put_16 (wrbfd
, bvst
.size
, off
- vst_off
);
2081 windres_put_16 (wrbfd
, bvst
.sig1
, 0);
2082 windres_put_16 (wrbfd
, bvst
.sig2
, 1);
2083 set_windres_bfd_content (wrbfd
, &bvst
, vst_off
,
2092 rc_uint_type vvd_off
, vvvd_off
;
2093 struct bin_ver_info bvvd
;
2094 const rc_ver_varinfo
*vv
;
2096 off
= string_to_unicode_bin (wrbfd
, off
, "VarFileInfo");
2098 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2101 off
+= BIN_VER_INFO_SIZE
;
2103 off
= unicode_to_bin (wrbfd
, off
, vi
->u
.var
.key
);
2105 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2109 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2115 windres_put_16 (wrbfd
, &vvsd
[0], vv
->language
);
2116 windres_put_16 (wrbfd
, &vvsd
[2], vv
->charset
);
2117 set_windres_bfd_content (wrbfd
, vvsd
, off
, 4);
2123 windres_put_16 (wrbfd
, bvvd
.size
, off
- vvd_off
);
2124 windres_put_16 (wrbfd
, bvvd
.sig1
, off
- vvvd_off
);
2125 windres_put_16 (wrbfd
, bvvd
.sig2
, 0);
2126 set_windres_bfd_content (wrbfd
, &bvvd
, vvd_off
,
2136 windres_put_16 (wrbfd
, bv
.size
, off
- bv_off
);
2137 windres_put_16 (wrbfd
, bv
.sig1
, 0);
2138 windres_put_16 (wrbfd
, bv
.sig2
, 1);
2139 set_windres_bfd_content (wrbfd
, &bv
, bv_off
,
2146 windres_put_16 (wrbfd
, bvi
.size
, off
- start
);
2147 windres_put_16 (wrbfd
, bvi
.fixed_size
,
2148 versioninfo
->fixed
== NULL
? 0
2149 : BIN_FIXED_VERSIONINFO_SIZE
);
2150 windres_put_16 (wrbfd
, bvi
.sig2
, 0);
2151 set_windres_bfd_content (wrbfd
, &bvi
, start
, BIN_VER_INFO_SIZE
);
2156 /* Convert a generic resource to binary. */
2159 res_to_bin_generic (windres_bfd
*wrbfd
, rc_uint_type off
, rc_uint_type length
,
2160 const bfd_byte
*data
)
2162 if (wrbfd
&& length
!= 0)
2163 set_windres_bfd_content (wrbfd
, data
, off
, length
);
2164 return off
+ (rc_uint_type
) length
;