1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright 1997, 1998, 1999, 2002, 2003, 2005, 2006, 2007
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
5 Rewritten by Kai Tietz, Onevision.
7 This file is part of GNU Binutils.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
25 /* This file contains functions to convert between the binary resource
26 format and the internal structures that we want to use. The same
27 binary resource format is used in both res and COFF files. */
32 #include "libiberty.h"
35 /* Local functions. */
37 static void toosmall (const char *);
39 static unichar
*get_unicode (windres_bfd
*, const bfd_byte
*, rc_uint_type
, rc_uint_type
*);
40 static int get_resid (windres_bfd
*, rc_res_id
*, const bfd_byte
*, rc_uint_type
);
41 static rc_res_resource
*bin_to_res_generic (windres_bfd
*, enum rc_res_type
,
42 const bfd_byte
*, rc_uint_type
);
43 static rc_res_resource
*bin_to_res_cursor (windres_bfd
*, const bfd_byte
*, rc_uint_type
);
44 static rc_res_resource
*bin_to_res_menu (windres_bfd
*,const bfd_byte
*, rc_uint_type
);
45 static rc_menuitem
*bin_to_res_menuitems (windres_bfd
*, const bfd_byte
*, rc_uint_type
,
47 static rc_menuitem
*bin_to_res_menuexitems (windres_bfd
*, const bfd_byte
*, rc_uint_type
,
49 static rc_res_resource
*bin_to_res_dialog (windres_bfd
*, const bfd_byte
*, rc_uint_type
);
50 static rc_res_resource
*bin_to_res_string (windres_bfd
*,const bfd_byte
*, rc_uint_type
);
51 static rc_res_resource
*bin_to_res_fontdir (windres_bfd
*, const bfd_byte
*, rc_uint_type
);
52 static rc_res_resource
*bin_to_res_accelerators (windres_bfd
*, const bfd_byte
*, rc_uint_type
);
53 static rc_res_resource
*bin_to_res_rcdata (windres_bfd
*, const bfd_byte
*, rc_uint_type
, int);
54 static rc_res_resource
*bin_to_res_group_cursor (windres_bfd
*, const bfd_byte
*, rc_uint_type
);
55 static rc_res_resource
*bin_to_res_group_icon (windres_bfd
*, const bfd_byte
*, rc_uint_type
);
56 static rc_res_resource
*bin_to_res_version (windres_bfd
*, const bfd_byte
*, rc_uint_type
);
57 static rc_res_resource
*bin_to_res_userdata (windres_bfd
*, const bfd_byte
*, rc_uint_type
);
58 static rc_res_resource
*bin_to_res_toolbar (windres_bfd
*, const bfd_byte
*, rc_uint_type
);
59 static void get_version_header (windres_bfd
*, const bfd_byte
*, rc_uint_type
, const char *,
60 unichar
**, rc_uint_type
*, rc_uint_type
*, rc_uint_type
*,
63 /* Given a resource type ID, a pointer to data, a length, return a
64 rc_res_resource structure which represents that resource. The caller
65 is responsible for initializing the res_info and coff_info fields
66 of the returned structure. */
69 bin_to_res (windres_bfd
*wrbfd
, rc_res_id type
, const bfd_byte
*data
,
73 return bin_to_res_userdata (wrbfd
, data
, length
);
79 return bin_to_res_userdata (wrbfd
, data
, length
);
81 return bin_to_res_cursor (wrbfd
, data
, length
);
83 return bin_to_res_generic (wrbfd
, RES_TYPE_BITMAP
, data
, length
);
85 return bin_to_res_generic (wrbfd
, RES_TYPE_ICON
, data
, length
);
87 return bin_to_res_menu (wrbfd
, data
, length
);
89 return bin_to_res_dialog (wrbfd
, data
, length
);
91 return bin_to_res_string (wrbfd
, data
, length
);
93 return bin_to_res_fontdir (wrbfd
, data
, length
);
95 return bin_to_res_generic (wrbfd
, RES_TYPE_FONT
, data
, length
);
97 return bin_to_res_accelerators (wrbfd
, data
, length
);
99 return bin_to_res_rcdata (wrbfd
, data
, length
, RES_TYPE_RCDATA
);
100 case RT_MESSAGETABLE
:
101 return bin_to_res_generic (wrbfd
, RES_TYPE_MESSAGETABLE
, data
, length
);
102 case RT_GROUP_CURSOR
:
103 return bin_to_res_group_cursor (wrbfd
, data
, length
);
105 return bin_to_res_group_icon (wrbfd
, data
, length
);
107 return bin_to_res_version (wrbfd
, data
, length
);
109 return bin_to_res_toolbar (wrbfd
, data
, length
);
115 /* Give an error if the binary data is too small. */
118 toosmall (const char *msg
)
120 fatal (_("%s: not enough binary data"), msg
);
123 /* Swap in a NULL terminated unicode string. */
126 get_unicode (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
,
127 rc_uint_type
*retlen
)
135 if (length
< c
* 2 + 2)
136 toosmall (_("null terminated unicode string"));
137 if (windres_get_16 (wrbfd
, data
+ c
* 2, 2) == 0)
142 ret
= (unichar
*) res_alloc ((c
+ 1) * sizeof (unichar
));
144 for (i
= 0; i
< c
; i
++)
145 ret
[i
] = windres_get_16 (wrbfd
, data
+ i
* 2, 2);
154 /* Get a resource identifier. This returns the number of bytes used. */
157 get_resid (windres_bfd
*wrbfd
, rc_res_id
*id
, const bfd_byte
*data
,
163 toosmall (_("resource ID"));
165 first
= windres_get_16 (wrbfd
, data
, 2);
169 toosmall (_("resource ID"));
171 id
->u
.id
= windres_get_16 (wrbfd
, data
+ 2, 2);
177 id
->u
.n
.name
= get_unicode (wrbfd
, data
, length
, &id
->u
.n
.length
);
178 return id
->u
.n
.length
* 2 + 2;
182 /* Convert a resource which just stores uninterpreted data from
186 bin_to_res_generic (windres_bfd
*wrbfd ATTRIBUTE_UNUSED
, enum rc_res_type type
,
187 const bfd_byte
*data
, rc_uint_type length
)
191 r
= (rc_res_resource
*) res_alloc (sizeof (rc_res_resource
));
193 r
->u
.data
.data
= data
;
194 r
->u
.data
.length
= length
;
199 /* Convert a cursor resource from binary. */
202 bin_to_res_cursor (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
208 toosmall (_("cursor"));
210 c
= (rc_cursor
*) res_alloc (sizeof (rc_cursor
));
211 c
->xhotspot
= windres_get_16 (wrbfd
, data
, 2);
212 c
->yhotspot
= windres_get_16 (wrbfd
, data
+ 2, 2);
213 c
->length
= length
- 4;
216 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
217 r
->type
= RES_TYPE_CURSOR
;
223 /* Convert a menu resource from binary. */
226 bin_to_res_menu (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
230 rc_uint_type version
, read
;
232 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
233 r
->type
= RES_TYPE_MENU
;
235 m
= (rc_menu
*) res_alloc (sizeof (rc_menu
));
239 toosmall (_("menu header"));
241 version
= windres_get_16 (wrbfd
, data
, 2);
246 toosmall (_("menu header"));
248 m
->items
= bin_to_res_menuitems (wrbfd
, data
+ 4, length
- 4, &read
);
250 else if (version
== 1)
255 toosmall (_("menuex header"));
256 m
->help
= windres_get_32 (wrbfd
, data
+ 4, 4);
257 offset
= windres_get_16 (wrbfd
, data
+ 2, 2);
258 if (offset
+ 4 >= length
)
259 toosmall (_("menuex offset"));
260 m
->items
= bin_to_res_menuexitems (wrbfd
, data
+ 4 + offset
,
261 length
- (4 + offset
), &read
);
264 fatal (_("unsupported menu version %d"), (int) version
);
269 /* Convert menu items from binary. */
272 bin_to_res_menuitems (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
,
275 rc_menuitem
*first
, **pp
;
284 rc_uint_type flags
, slen
, itemlen
;
289 toosmall (_("menuitem header"));
291 mi
= (rc_menuitem
*) res_alloc (sizeof *mi
);
295 flags
= windres_get_16 (wrbfd
, data
, 2);
296 mi
->type
= flags
&~ (MENUITEM_POPUP
| MENUITEM_ENDMENU
);
298 if ((flags
& MENUITEM_POPUP
) == 0)
303 if (length
< stroff
+ 2)
304 toosmall (_("menuitem header"));
306 if (windres_get_16 (wrbfd
, data
+ stroff
, 2) == 0)
312 mi
->text
= get_unicode (wrbfd
, data
+ stroff
, length
- stroff
, &slen
);
314 itemlen
= stroff
+ slen
* 2 + 2;
316 if ((flags
& MENUITEM_POPUP
) == 0)
319 mi
->id
= windres_get_16 (wrbfd
, data
+ 2, 2);
323 rc_uint_type subread
;
326 mi
->popup
= bin_to_res_menuitems (wrbfd
, data
+ itemlen
, length
- itemlen
,
339 if ((flags
& MENUITEM_ENDMENU
) != 0)
346 /* Convert menuex items from binary. */
349 bin_to_res_menuexitems (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
,
352 rc_menuitem
*first
, **pp
;
361 rc_uint_type flags
, slen
;
362 rc_uint_type itemlen
;
366 toosmall (_("menuitem header"));
368 mi
= (rc_menuitem
*) res_alloc (sizeof (rc_menuitem
));
369 mi
->type
= windres_get_32 (wrbfd
, data
, 4);
370 mi
->state
= windres_get_32 (wrbfd
, data
+ 4, 4);
371 mi
->id
= windres_get_32 (wrbfd
, data
+ 8, 4);
373 flags
= windres_get_16 (wrbfd
, data
+ 12, 2);
375 if (windres_get_16 (wrbfd
, data
+ 14, 2) == 0)
381 mi
->text
= get_unicode (wrbfd
, data
+ 14, length
- 14, &slen
);
383 itemlen
= 14 + slen
* 2 + 2;
384 itemlen
= (itemlen
+ 3) &~ 3;
386 if ((flags
& 1) == 0)
393 rc_uint_type subread
;
395 if (length
< itemlen
+ 4)
396 toosmall (_("menuitem"));
397 mi
->help
= windres_get_32 (wrbfd
, data
+ itemlen
, 4);
400 mi
->popup
= bin_to_res_menuexitems (wrbfd
, data
+ itemlen
,
401 length
- itemlen
, &subread
);
413 if ((flags
& 0x80) != 0)
420 /* Convert a dialog resource from binary. */
422 static rc_res_resource
*
423 bin_to_res_dialog (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
425 rc_uint_type signature
;
427 rc_uint_type c
, sublen
, i
;
429 rc_dialog_control
**pp
;
433 toosmall (_("dialog header"));
435 d
= (rc_dialog
*) res_alloc (sizeof (rc_dialog
));
437 signature
= windres_get_16 (wrbfd
, data
+ 2, 2);
438 if (signature
!= 0xffff)
441 d
->style
= windres_get_32 (wrbfd
, data
, 4);
442 d
->exstyle
= windres_get_32 (wrbfd
, data
+ 4, 4);
449 version
= windres_get_16 (wrbfd
, data
, 2);
451 fatal (_("unexpected DIALOGEX version %d"), version
);
453 d
->ex
= (rc_dialog_ex
*) res_alloc (sizeof (rc_dialog_ex
));
454 d
->ex
->help
= windres_get_32 (wrbfd
, data
+ 4, 4);
455 d
->exstyle
= windres_get_32 (wrbfd
, data
+ 8, 4);
456 d
->style
= windres_get_32 (wrbfd
, data
+ 12, 4);
460 if (length
< off
+ 10)
461 toosmall (_("dialog header"));
463 c
= windres_get_16 (wrbfd
, data
+ off
, 2);
464 d
->x
= windres_get_16 (wrbfd
, data
+ off
+ 2, 2);
465 d
->y
= windres_get_16 (wrbfd
, data
+ off
+ 4, 2);
466 d
->width
= windres_get_16 (wrbfd
, data
+ off
+ 6, 2);
467 d
->height
= windres_get_16 (wrbfd
, data
+ off
+ 8, 2);
471 sublen
= get_resid (wrbfd
, &d
->menu
, data
+ off
, length
- off
);
474 sublen
= get_resid (wrbfd
, &d
->class, data
+ off
, length
- off
);
477 d
->caption
= get_unicode (wrbfd
, data
+ off
, length
- off
, &sublen
);
478 off
+= sublen
* 2 + 2;
482 if ((d
->style
& DS_SETFONT
) == 0)
490 d
->ex
->charset
= 1; /* Default charset. */
495 if (length
< off
+ 2)
496 toosmall (_("dialog font point size"));
498 d
->pointsize
= windres_get_16 (wrbfd
, data
+ off
, 2);
503 if (length
< off
+ 4)
504 toosmall (_("dialogex font information"));
505 d
->ex
->weight
= windres_get_16 (wrbfd
, data
+ off
, 2);
506 d
->ex
->italic
= windres_get_8 (wrbfd
, data
+ off
+ 2, 1);
507 d
->ex
->charset
= windres_get_8 (wrbfd
, data
+ off
+ 3, 1);
511 d
->font
= get_unicode (wrbfd
, data
+ off
, length
- off
, &sublen
);
512 off
+= sublen
* 2 + 2;
518 for (i
= 0; i
< c
; i
++)
520 rc_dialog_control
*dc
;
523 off
= (off
+ 3) &~ 3;
525 dc
= (rc_dialog_control
*) res_alloc (sizeof (rc_dialog_control
));
529 if (length
< off
+ 8)
530 toosmall (_("dialog control"));
532 dc
->style
= windres_get_32 (wrbfd
, data
+ off
, 4);
533 dc
->exstyle
= windres_get_32 (wrbfd
, data
+ off
+ 4, 4);
539 if (length
< off
+ 12)
540 toosmall (_("dialogex control"));
541 dc
->help
= windres_get_32 (wrbfd
, data
+ off
, 4);
542 dc
->exstyle
= windres_get_32 (wrbfd
, data
+ off
+ 4, 4);
543 dc
->style
= windres_get_32 (wrbfd
, data
+ off
+ 8, 4);
547 if (length
< off
+ (d
->ex
!= NULL
? 2 : 0) + 10)
548 toosmall (_("dialog control"));
550 dc
->x
= windres_get_16 (wrbfd
, data
+ off
, 2);
551 dc
->y
= windres_get_16 (wrbfd
, data
+ off
+ 2, 2);
552 dc
->width
= windres_get_16 (wrbfd
, data
+ off
+ 4, 2);
553 dc
->height
= windres_get_16 (wrbfd
, data
+ off
+ 6, 2);
556 dc
->id
= windres_get_32 (wrbfd
, data
+ off
+ 8, 4);
558 dc
->id
= windres_get_16 (wrbfd
, data
+ off
+ 8, 2);
560 off
+= 10 + (d
->ex
!= NULL
? 2 : 0);
562 sublen
= get_resid (wrbfd
, &dc
->class, data
+ off
, length
- off
);
565 sublen
= get_resid (wrbfd
, &dc
->text
, data
+ off
, length
- off
);
568 if (length
< off
+ 2)
569 toosmall (_("dialog control end"));
571 datalen
= windres_get_16 (wrbfd
, data
+ off
, 2);
578 off
= (off
+ 3) &~ 3;
580 if (length
< off
+ datalen
)
581 toosmall (_("dialog control data"));
583 dc
->data
= ((rc_rcdata_item
*)
584 res_alloc (sizeof (rc_rcdata_item
)));
585 dc
->data
->next
= NULL
;
586 dc
->data
->type
= RCDATA_BUFFER
;
587 dc
->data
->u
.buffer
.length
= datalen
;
588 dc
->data
->u
.buffer
.data
= data
+ off
;
598 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
599 r
->type
= RES_TYPE_DIALOG
;
605 /* Convert a stringtable resource from binary. */
607 static rc_res_resource
*
608 bin_to_res_string (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
614 st
= (rc_stringtable
*) res_alloc (sizeof (rc_stringtable
));
616 for (i
= 0; i
< 16; i
++)
621 toosmall (_("stringtable string length"));
622 slen
= windres_get_16 (wrbfd
, data
, 2);
623 st
->strings
[i
].length
= slen
;
630 if (length
< 2 + 2 * slen
)
631 toosmall (_("stringtable string"));
633 s
= (unichar
*) res_alloc (slen
* sizeof (unichar
));
634 st
->strings
[i
].string
= s
;
636 for (j
= 0; j
< slen
; j
++)
637 s
[j
] = windres_get_16 (wrbfd
, data
+ 2 + j
* 2, 2);
640 data
+= 2 + 2 * slen
;
641 length
-= 2 + 2 * slen
;
644 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
645 r
->type
= RES_TYPE_STRINGTABLE
;
646 r
->u
.stringtable
= st
;
651 /* Convert a fontdir resource from binary. */
653 static rc_res_resource
*
654 bin_to_res_fontdir (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
657 rc_fontdir
*first
, **pp
;
661 toosmall (_("fontdir header"));
663 c
= windres_get_16 (wrbfd
, data
, 2);
668 for (i
= 0; i
< c
; i
++)
670 const struct bin_fontdir_item
*bfi
;
675 toosmall (_("fontdir"));
677 bfi
= (const struct bin_fontdir_item
*) data
;
678 fd
= (rc_fontdir
*) res_alloc (sizeof *fd
);
679 fd
->index
= windres_get_16 (wrbfd
, bfi
->index
, 2);
681 /* To work out the length of the fontdir data, we must get the
682 length of the device name and face name strings, even though
683 we don't store them in the rc_fontdir. The
684 documentation says that these are NULL terminated char
685 strings, not Unicode strings. */
689 while (off
< length
&& data
[off
] != '\0')
692 toosmall (_("fontdir device name"));
695 while (off
< length
&& data
[off
] != '\0')
698 toosmall (_("fontdir face name"));
708 /* The documentation does not indicate that any rounding is
715 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
716 r
->type
= RES_TYPE_FONTDIR
;
717 r
->u
.fontdir
= first
;
722 /* Convert an accelerators resource from binary. */
724 static rc_res_resource
*
725 bin_to_res_accelerators (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
727 rc_accelerator
*first
, **pp
;
738 toosmall (_("accelerator"));
740 a
= (rc_accelerator
*) res_alloc (sizeof (rc_accelerator
));
742 a
->flags
= windres_get_16 (wrbfd
, data
, 2);
743 a
->key
= windres_get_16 (wrbfd
, data
+ 2, 2);
744 a
->id
= windres_get_16 (wrbfd
, data
+ 4, 2);
750 if ((a
->flags
& ACC_LAST
) != 0)
757 r
= (rc_res_resource
*) res_alloc (sizeof (rc_res_resource
));
758 r
->type
= RES_TYPE_ACCELERATOR
;
764 /* Convert an rcdata resource from binary. */
766 static rc_res_resource
*
767 bin_to_res_rcdata (windres_bfd
*wrbfd ATTRIBUTE_UNUSED
, const bfd_byte
*data
,
768 rc_uint_type length
, int rctyp
)
773 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
776 ri
->type
= RCDATA_BUFFER
;
777 ri
->u
.buffer
.length
= length
;
778 ri
->u
.buffer
.data
= data
;
780 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
787 /* Convert a group cursor resource from binary. */
789 static rc_res_resource
*
790 bin_to_res_group_cursor (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
793 rc_group_cursor
*first
, **pp
;
797 toosmall (_("group cursor header"));
799 type
= windres_get_16 (wrbfd
, data
+ 2, 2);
801 fatal (_("unexpected group cursor type %d"), type
);
803 c
= windres_get_16 (wrbfd
, data
+ 4, 2);
811 for (i
= 0; i
< c
; i
++)
816 toosmall (_("group cursor"));
818 gc
= (rc_group_cursor
*) res_alloc (sizeof *gc
);
820 gc
->width
= windres_get_16 (wrbfd
, data
, 2);
821 gc
->height
= windres_get_16 (wrbfd
, data
+ 2, 2);
822 gc
->planes
= windres_get_16 (wrbfd
, data
+ 4, 2);
823 gc
->bits
= windres_get_16 (wrbfd
, data
+ 6, 2);
824 gc
->bytes
= windres_get_32 (wrbfd
, data
+ 8, 4);
825 gc
->index
= windres_get_16 (wrbfd
, data
+ 12, 2);
835 r
= (rc_res_resource
*) res_alloc (sizeof (rc_res_resource
));
836 r
->type
= RES_TYPE_GROUP_CURSOR
;
837 r
->u
.group_cursor
= first
;
842 /* Convert a group icon resource from binary. */
844 static rc_res_resource
*
845 bin_to_res_group_icon (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
848 rc_group_icon
*first
, **pp
;
852 toosmall (_("group icon header"));
854 type
= windres_get_16 (wrbfd
, data
+ 2, 2);
856 fatal (_("unexpected group icon type %d"), type
);
858 c
= windres_get_16 (wrbfd
, data
+ 4, 2);
866 for (i
= 0; i
< c
; i
++)
871 toosmall (_("group icon"));
873 gi
= (rc_group_icon
*) res_alloc (sizeof (rc_group_icon
));
875 gi
->width
= windres_get_8 (wrbfd
, data
, 1);
876 gi
->height
= windres_get_8 (wrbfd
, data
+ 1, 1);
877 gi
->colors
= windres_get_8 (wrbfd
, data
+ 2, 1);
878 gi
->planes
= windres_get_16 (wrbfd
, data
+ 4, 2);
879 gi
->bits
= windres_get_16 (wrbfd
, data
+ 6, 2);
880 gi
->bytes
= windres_get_32 (wrbfd
, data
+ 8, 4);
881 gi
->index
= windres_get_16 (wrbfd
, data
+ 12, 2);
891 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
892 r
->type
= RES_TYPE_GROUP_ICON
;
893 r
->u
.group_icon
= first
;
898 /* Extract data from a version header. If KEY is not NULL, then the
899 key must be KEY; otherwise, the key is returned in *PKEY. This
900 sets *LEN to the total length, *VALLEN to the value length, *TYPE
901 to the type, and *OFF to the offset to the children. */
904 get_version_header (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
,
905 const char *key
, unichar
**pkey
,
906 rc_uint_type
*len
, rc_uint_type
*vallen
, rc_uint_type
*type
,
912 *len
= windres_get_16 (wrbfd
, data
, 2);
913 *vallen
= windres_get_16 (wrbfd
, data
+ 2, 2);
914 *type
= windres_get_16 (wrbfd
, data
+ 4, 2);
925 *pkey
= get_unicode (wrbfd
, data
, length
, &sublen
);
926 *off
+= (sublen
+ 1) * sizeof (unichar
);
934 if (windres_get_16 (wrbfd
, data
, 2) != (bfd_byte
) *key
)
935 fatal (_("unexpected version string"));
948 *off
= (*off
+ 3) &~ 3;
951 /* Convert a version resource from binary. */
953 static rc_res_resource
*
954 bin_to_res_version (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
956 rc_uint_type verlen
, vallen
, type
, off
;
957 rc_fixed_versioninfo
*fi
;
958 rc_ver_info
*first
, **pp
;
962 get_version_header (wrbfd
, data
, length
, "VS_VERSION_INFO",
963 (unichar
**) NULL
, &verlen
, &vallen
, &type
, &off
);
965 if ((unsigned int) verlen
!= length
)
966 fatal (_("version length %d does not match resource length %lu"),
967 (int) 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_stringinfo
**ppvs
;
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
);
1044 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1045 &vi
->u
.string
.language
, &verlen
, &vallen
,
1049 fatal (_("unexpected version stringtable value length %ld"), (long) vallen
);
1055 vi
->u
.string
.strings
= NULL
;
1056 ppvs
= &vi
->u
.string
.strings
;
1058 /* It's convenient to round verlen to a 4 byte alignment,
1059 since we round the subvariables in the loop. */
1060 verlen
= (verlen
+ 3) &~ 3;
1064 rc_ver_stringinfo
*vs
;
1065 rc_uint_type subverlen
, vslen
, valoff
;
1067 vs
= (rc_ver_stringinfo
*) res_alloc (sizeof *vs
);
1069 get_version_header (wrbfd
, data
, length
,
1070 (const char *) NULL
, &vs
->key
, &subverlen
,
1071 &vallen
, &type
, &off
);
1073 subverlen
= (subverlen
+ 3) &~ 3;
1078 vs
->value
= get_unicode (wrbfd
, data
, length
, &vslen
);
1079 valoff
= vslen
* 2 + 2;
1080 valoff
= (valoff
+ 3) &~ 3;
1082 if (off
+ valoff
!= subverlen
)
1083 fatal (_("unexpected version string length %ld != %ld + %ld"),
1084 (long) subverlen
, (long) off
, (long) valoff
);
1093 if (verlen
< subverlen
)
1094 fatal (_("unexpected version string length %ld < %ld"),
1095 (long) verlen
, (long) subverlen
);
1097 verlen
-= subverlen
;
1102 rc_ver_varinfo
**ppvv
;
1104 vi
->type
= VERINFO_VAR
;
1106 get_version_header (wrbfd
, data
, length
, "VarFileInfo",
1107 (unichar
**) NULL
, &verlen
, &vallen
, &type
,
1111 fatal (_("unexpected varfileinfo value length %ld"), (long) vallen
);
1116 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1117 &vi
->u
.var
.key
, &verlen
, &vallen
, &type
, &off
);
1122 vi
->u
.var
.var
= NULL
;
1123 ppvv
= &vi
->u
.var
.var
;
1130 toosmall (_("version varfileinfo"));
1132 vv
= (rc_ver_varinfo
*) res_alloc (sizeof (rc_ver_varinfo
));
1134 vv
->language
= windres_get_16 (wrbfd
, data
, 2);
1135 vv
->charset
= windres_get_16 (wrbfd
, data
+ 2, 2);
1145 fatal (_("unexpected version value length %ld"), (long) vallen
);
1151 fatal (_("unexpected version string"));
1158 v
= (rc_versioninfo
*) res_alloc (sizeof (rc_versioninfo
));
1162 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1163 r
->type
= RES_TYPE_VERSIONINFO
;
1164 r
->u
.versioninfo
= v
;
1169 /* Convert an arbitrary user defined resource from binary. */
1171 static rc_res_resource
*
1172 bin_to_res_userdata (windres_bfd
*wrbfd ATTRIBUTE_UNUSED
, const bfd_byte
*data
,
1173 rc_uint_type length
)
1178 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1181 ri
->type
= RCDATA_BUFFER
;
1182 ri
->u
.buffer
.length
= length
;
1183 ri
->u
.buffer
.data
= data
;
1185 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1186 r
->type
= RES_TYPE_USERDATA
;
1192 static rc_res_resource
*
1193 bin_to_res_toolbar (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
1199 ri
= (rc_toolbar
*) res_alloc (sizeof (rc_toolbar
));
1200 ri
->button_width
= windres_get_32 (wrbfd
, data
, 4);
1201 ri
->button_height
= windres_get_32 (wrbfd
, data
+ 4, 4);
1202 ri
->nitems
= windres_get_32 (wrbfd
, data
+ 8, 4);
1207 for (i
=0 ; i
< ri
->nitems
; i
++)
1209 rc_toolbar_item
*it
;
1210 it
= (rc_toolbar_item
*) res_alloc (sizeof (rc_toolbar_item
));
1212 it
->id
.u
.id
= (int) windres_get_32 (wrbfd
, data
, 4);
1213 it
->prev
= it
->next
= NULL
;
1217 rc_toolbar_item
*ii
= ri
->items
;
1218 while (ii
->next
!= NULL
)
1226 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1227 r
->type
= RES_TYPE_TOOLBAR
;
1233 /* Local functions used to convert resources to binary format. */
1235 static rc_uint_type
resid_to_bin (windres_bfd
*, rc_uint_type
, rc_res_id
);
1236 static rc_uint_type
unicode_to_bin (windres_bfd
*, rc_uint_type
, const unichar
*);
1237 static rc_uint_type
res_to_bin_accelerator (windres_bfd
*, rc_uint_type
, const rc_accelerator
*);
1238 static rc_uint_type
res_to_bin_cursor (windres_bfd
*, rc_uint_type
, const rc_cursor
*);
1239 static rc_uint_type
res_to_bin_group_cursor (windres_bfd
*, rc_uint_type
, const rc_group_cursor
*);
1240 static rc_uint_type
res_to_bin_dialog (windres_bfd
*, rc_uint_type
, const rc_dialog
*);
1241 static rc_uint_type
res_to_bin_fontdir (windres_bfd
*, rc_uint_type
, const rc_fontdir
*);
1242 static rc_uint_type
res_to_bin_group_icon (windres_bfd
*, rc_uint_type
, const rc_group_icon
*);
1243 static rc_uint_type
res_to_bin_menu (windres_bfd
*, rc_uint_type
, const rc_menu
*);
1244 static rc_uint_type
res_to_bin_menuitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1245 static rc_uint_type
res_to_bin_menuexitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1246 static rc_uint_type
res_to_bin_rcdata (windres_bfd
*, rc_uint_type
, const rc_rcdata_item
*);
1247 static rc_uint_type
res_to_bin_stringtable (windres_bfd
*, rc_uint_type
, const rc_stringtable
*);
1248 static rc_uint_type
string_to_unicode_bin (windres_bfd
*, rc_uint_type
, const char *);
1249 static rc_uint_type
res_to_bin_toolbar (windres_bfd
*, rc_uint_type
, rc_toolbar
*tb
);
1250 static rc_uint_type
res_to_bin_versioninfo (windres_bfd
*, rc_uint_type
, const rc_versioninfo
*);
1251 static rc_uint_type
res_to_bin_generic (windres_bfd
*, rc_uint_type
, rc_uint_type
,
1254 /* Convert a resource to binary. */
1257 res_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_res_resource
*res
)
1261 case RES_TYPE_BITMAP
:
1264 case RES_TYPE_MESSAGETABLE
:
1265 return res_to_bin_generic (wrbfd
, off
, res
->u
.data
.length
, res
->u
.data
.data
);
1266 case RES_TYPE_ACCELERATOR
:
1267 return res_to_bin_accelerator (wrbfd
, off
, res
->u
.acc
);
1268 case RES_TYPE_CURSOR
:
1269 return res_to_bin_cursor (wrbfd
, off
, res
->u
.cursor
);
1270 case RES_TYPE_GROUP_CURSOR
:
1271 return res_to_bin_group_cursor (wrbfd
, off
, res
->u
.group_cursor
);
1272 case RES_TYPE_DIALOG
:
1273 return res_to_bin_dialog (wrbfd
, off
, res
->u
.dialog
);
1274 case RES_TYPE_FONTDIR
:
1275 return res_to_bin_fontdir (wrbfd
, off
, res
->u
.fontdir
);
1276 case RES_TYPE_GROUP_ICON
:
1277 return res_to_bin_group_icon (wrbfd
, off
, res
->u
.group_icon
);
1279 return res_to_bin_menu (wrbfd
, off
, res
->u
.menu
);
1280 case RES_TYPE_STRINGTABLE
:
1281 return res_to_bin_stringtable (wrbfd
, off
, res
->u
.stringtable
);
1282 case RES_TYPE_VERSIONINFO
:
1283 return res_to_bin_versioninfo (wrbfd
, off
, res
->u
.versioninfo
);
1284 case RES_TYPE_TOOLBAR
:
1285 return res_to_bin_toolbar (wrbfd
, off
, res
->u
.toolbar
);
1286 case RES_TYPE_USERDATA
:
1287 case RES_TYPE_RCDATA
:
1289 return res_to_bin_rcdata (wrbfd
, off
, res
->u
.rcdata
);
1293 /* Convert a resource ID to binary. This always returns exactly one
1294 bindata structure. */
1297 resid_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, rc_res_id id
)
1303 struct bin_res_id bri
;
1305 windres_put_16 (wrbfd
, bri
.sig
, 0xffff);
1306 windres_put_16 (wrbfd
, bri
.id
, id
.u
.id
);
1307 set_windres_bfd_content (wrbfd
, &bri
, off
, BIN_RES_ID
);
1313 rc_uint_type len
= (id
.u
.n
.name
? unichar_len (id
.u
.n
.name
) : 0);
1316 bfd_byte
*d
= (bfd_byte
*) reswr_alloc ((len
+ 1) * sizeof (unichar
));
1318 for (i
= 0; i
< len
; i
++)
1319 windres_put_16 (wrbfd
, d
+ (i
* sizeof (unichar
)), id
.u
.n
.name
[i
]);
1320 windres_put_16 (wrbfd
, d
+ (len
* sizeof (unichar
)), 0);
1321 set_windres_bfd_content (wrbfd
, d
, off
, (len
+ 1) * sizeof (unichar
));
1323 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1328 /* Convert a null terminated unicode string to binary. This always
1329 returns exactly one bindata structure. */
1332 unicode_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const unichar
*str
)
1334 rc_uint_type len
= 0;
1337 len
= unichar_len (str
);
1343 d
= (bfd_byte
*) reswr_alloc ( (len
+ 1) * sizeof (unichar
));
1344 for (i
= 0; i
< len
; i
++)
1345 windres_put_16 (wrbfd
, d
+ (i
* sizeof (unichar
)), str
[i
]);
1346 windres_put_16 (wrbfd
, d
+ (len
* sizeof (unichar
)), 0);
1347 set_windres_bfd_content (wrbfd
, d
, off
, (len
+ 1) * sizeof (unichar
));
1349 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1354 /* Convert an accelerator resource to binary. */
1357 res_to_bin_accelerator (windres_bfd
*wrbfd
, rc_uint_type off
,
1358 const rc_accelerator
*accelerators
)
1360 bindata
*first
, **pp
;
1361 const rc_accelerator
*a
;
1366 for (a
= accelerators
; a
!= NULL
; a
= a
->next
)
1370 struct bin_accelerator ba
;
1372 windres_put_16 (wrbfd
, ba
.flags
, a
->flags
| (a
->next
!= NULL
? 0 : ACC_LAST
));
1373 windres_put_16 (wrbfd
, ba
.key
, a
->key
);
1374 windres_put_16 (wrbfd
, ba
.id
, a
->id
);
1375 windres_put_16 (wrbfd
, ba
.pad
, 0);
1376 set_windres_bfd_content (wrbfd
, &ba
, off
, BIN_ACCELERATOR_SIZE
);
1378 off
+= BIN_ACCELERATOR_SIZE
;
1383 /* Convert a cursor resource to binary. */
1386 res_to_bin_cursor (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_cursor
*c
)
1390 struct bin_cursor bc
;
1392 windres_put_16 (wrbfd
, bc
.xhotspot
, c
->xhotspot
);
1393 windres_put_16 (wrbfd
, bc
.yhotspot
, c
->yhotspot
);
1394 set_windres_bfd_content (wrbfd
, &bc
, off
, BIN_CURSOR_SIZE
);
1396 set_windres_bfd_content (wrbfd
, c
->data
, off
+ BIN_CURSOR_SIZE
, c
->length
);
1398 off
= (off
+ BIN_CURSOR_SIZE
+ (rc_uint_type
) c
->length
);
1402 /* Convert a group cursor resource to binary. */
1405 res_to_bin_group_cursor (windres_bfd
*wrbfd
, rc_uint_type off
,
1406 const rc_group_cursor
*group_cursors
)
1409 const rc_group_cursor
*gc
;
1410 struct bin_group_cursor bgc
;
1411 struct bin_group_cursor_item bgci
;
1412 rc_uint_type start
= off
;
1414 off
+= BIN_GROUP_CURSOR_SIZE
;
1416 for (c
= 0, gc
= group_cursors
; gc
!= NULL
; gc
= gc
->next
, c
++)
1420 windres_put_16 (wrbfd
, bgci
.width
, gc
->width
);
1421 windres_put_16 (wrbfd
, bgci
.height
, gc
->height
);
1422 windres_put_16 (wrbfd
, bgci
.planes
, gc
->planes
);
1423 windres_put_16 (wrbfd
, bgci
.bits
, gc
->bits
);
1424 windres_put_32 (wrbfd
, bgci
.bytes
, gc
->bytes
);
1425 windres_put_16 (wrbfd
, bgci
.index
, gc
->index
);
1426 set_windres_bfd_content (wrbfd
, &bgci
, off
, BIN_GROUP_CURSOR_ITEM_SIZE
);
1429 off
+= BIN_GROUP_CURSOR_ITEM_SIZE
;
1433 windres_put_16 (wrbfd
, bgc
.sig1
, 0);
1434 windres_put_16 (wrbfd
, bgc
.sig2
, 2);
1435 windres_put_16 (wrbfd
, bgc
.nitems
, c
);
1436 set_windres_bfd_content (wrbfd
, &bgc
, start
, BIN_GROUP_CURSOR_SIZE
);
1441 /* Convert a dialog resource to binary. */
1444 res_to_bin_dialog (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_dialog
*dialog
)
1446 rc_uint_type off_delta
;
1447 rc_uint_type start
, marker
;
1450 rc_dialog_control
*dc
;
1451 struct bin_dialogex bdx
;
1452 struct bin_dialog bd
;
1456 dialogex
= extended_dialog (dialog
);
1462 windres_put_32 (wrbfd
, bd
.style
, dialog
->style
);
1463 windres_put_32 (wrbfd
, bd
.exstyle
, dialog
->exstyle
);
1464 windres_put_16 (wrbfd
, bd
.x
, dialog
->x
);
1465 windres_put_16 (wrbfd
, bd
.y
, dialog
->y
);
1466 windres_put_16 (wrbfd
, bd
.width
, dialog
->width
);
1467 windres_put_16 (wrbfd
, bd
.height
, dialog
->height
);
1471 windres_put_16 (wrbfd
, bdx
.sig1
, 1);
1472 windres_put_16 (wrbfd
, bdx
.sig2
, 0xffff);
1473 windres_put_32 (wrbfd
, bdx
.help
, (dialog
->ex
? dialog
->ex
->help
: 0));
1474 windres_put_32 (wrbfd
, bdx
.exstyle
, dialog
->exstyle
);
1475 windres_put_32 (wrbfd
, bdx
.style
, dialog
->style
);
1476 windres_put_16 (wrbfd
, bdx
.x
, dialog
->x
);
1477 windres_put_16 (wrbfd
, bdx
.y
, dialog
->y
);
1478 windres_put_16 (wrbfd
, bdx
.width
, dialog
->width
);
1479 windres_put_16 (wrbfd
, bdx
.height
, dialog
->height
);
1483 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_SIZE
: BIN_DIALOG_SIZE
);
1485 off
= resid_to_bin (wrbfd
, off
, dialog
->menu
);
1486 off
= resid_to_bin (wrbfd
, off
, dialog
->class);
1487 off
= unicode_to_bin (wrbfd
, off
, dialog
->caption
);
1489 if ((dialog
->style
& DS_SETFONT
) != 0)
1495 struct bin_dialogfont bdf
;
1496 windres_put_16 (wrbfd
, bdf
.pointsize
, dialog
->pointsize
);
1497 set_windres_bfd_content (wrbfd
, &bdf
, off
, BIN_DIALOGFONT_SIZE
);
1501 struct bin_dialogexfont bdxf
;
1502 windres_put_16 (wrbfd
, bdxf
.pointsize
, dialog
->pointsize
);
1503 windres_put_16 (wrbfd
, bdxf
.weight
, (dialog
->ex
== NULL
? 0 : dialog
->ex
->weight
));
1504 windres_put_8 (wrbfd
, bdxf
.italic
, (dialog
->ex
== NULL
? 0 : dialog
->ex
->italic
));
1505 windres_put_8 (wrbfd
, bdxf
.charset
, (dialog
->ex
== NULL
? 1 : dialog
->ex
->charset
));
1506 set_windres_bfd_content (wrbfd
, &bdxf
, off
, BIN_DIALOGEXFONT_SIZE
);
1509 off
+= (dialogex
? BIN_DIALOGEXFONT_SIZE
: BIN_DIALOGFONT_SIZE
);
1510 off
= unicode_to_bin (wrbfd
, off
, dialog
->font
);
1512 for (c
= 0, dc
= dialog
->controls
; dc
!= NULL
; dc
= dc
->next
, c
++)
1514 bfd_byte dc_rclen
[2];
1516 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1521 struct bin_dialog_control bdc
;
1523 windres_put_32 (wrbfd
, bdc
.style
, dc
->style
);
1524 windres_put_32 (wrbfd
, bdc
.exstyle
, dc
->exstyle
);
1525 windres_put_16 (wrbfd
, bdc
.x
, dc
->x
);
1526 windres_put_16 (wrbfd
, bdc
.y
, dc
->y
);
1527 windres_put_16 (wrbfd
, bdc
.width
, dc
->width
);
1528 windres_put_16 (wrbfd
, bdc
.height
, dc
->height
);
1529 windres_put_16 (wrbfd
, bdc
.id
, dc
->id
);
1530 set_windres_bfd_content (wrbfd
, &bdc
, off
, BIN_DIALOG_CONTROL_SIZE
);
1534 struct bin_dialogex_control bdc
;
1536 windres_put_32 (wrbfd
, bdc
.help
, dc
->help
);
1537 windres_put_32 (wrbfd
, bdc
.exstyle
, dc
->exstyle
);
1538 windres_put_32 (wrbfd
, bdc
.style
, dc
->style
);
1539 windres_put_16 (wrbfd
, bdc
.x
, dc
->x
);
1540 windres_put_16 (wrbfd
, bdc
.y
, dc
->y
);
1541 windres_put_16 (wrbfd
, bdc
.width
, dc
->width
);
1542 windres_put_16 (wrbfd
, bdc
.height
, dc
->height
);
1543 windres_put_32 (wrbfd
, bdc
.id
, dc
->id
);
1544 set_windres_bfd_content (wrbfd
, &bdc
, off
, BIN_DIALOGEX_CONTROL_SIZE
);
1547 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_CONTROL_SIZE
: BIN_DIALOG_CONTROL_SIZE
);
1549 off
= resid_to_bin (wrbfd
, off
, dc
->class);
1550 off
= resid_to_bin (wrbfd
, off
, dc
->text
);
1552 marker
= off
; /* Save two bytes for size of optional data. */
1555 if (dc
->data
== NULL
)
1558 windres_put_16 (wrbfd
, dc_rclen
, 0);
1562 rc_uint_type saved_off
= off
;
1563 rc_uint_type old_off
;
1564 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1567 off
= res_to_bin_rcdata (wrbfd
, off
, dc
->data
);
1568 if ((off
- old_off
) == 0)
1569 old_off
= off
= saved_off
;
1571 windres_put_16 (wrbfd
, dc_rclen
, off
- old_off
);
1574 set_windres_bfd_content (wrbfd
, dc_rclen
, marker
, 2);
1579 windres_put_16 (wrbfd
, (dialogex
!= 0 ? bdx
.off
: bd
.off
), c
);
1581 set_windres_bfd_content (wrbfd
, &bd
, start
, BIN_DIALOG_SIZE
);
1583 set_windres_bfd_content (wrbfd
, &bdx
, start
, BIN_DIALOGEX_SIZE
);
1589 /* Convert a fontdir resource to binary. */
1591 res_to_bin_fontdir (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_fontdir
*fontdirs
)
1595 const rc_fontdir
*fd
;
1600 for (c
= 0, fd
= fontdirs
; fd
!= NULL
; fd
= fd
->next
, c
++)
1605 windres_put_16 (wrbfd
, d
, fd
->index
);
1606 set_windres_bfd_content (wrbfd
, d
, off
, 2);
1608 set_windres_bfd_content (wrbfd
, fd
->data
, off
+ 2, fd
->length
);
1610 off
+= (rc_uint_type
) fd
->length
+ 2;
1616 windres_put_16 (wrbfd
, d
, c
);
1617 set_windres_bfd_content (wrbfd
, d
, start
, 2);
1622 /* Convert a group icon resource to binary. */
1625 res_to_bin_group_icon (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_group_icon
*group_icons
)
1628 struct bin_group_icon bgi
;
1630 const rc_group_icon
*gi
;
1633 off
+= BIN_GROUP_ICON_SIZE
;
1635 for (c
= 0, gi
= group_icons
; gi
!= NULL
; gi
= gi
->next
, c
++)
1637 struct bin_group_icon_item bgii
;
1641 windres_put_8 (wrbfd
, bgii
.width
, gi
->width
);
1642 windres_put_8 (wrbfd
, bgii
.height
, gi
->height
);
1643 windres_put_8 (wrbfd
, bgii
.colors
, gi
->colors
);
1644 windres_put_8 (wrbfd
, bgii
.pad
, 0);
1645 windres_put_16 (wrbfd
, bgii
.planes
, gi
->planes
);
1646 windres_put_16 (wrbfd
, bgii
.bits
, gi
->bits
);
1647 windres_put_32 (wrbfd
, bgii
.bytes
, gi
->bytes
);
1648 windres_put_16 (wrbfd
, bgii
.index
, gi
->index
);
1649 set_windres_bfd_content (wrbfd
, &bgii
, off
, BIN_GROUP_ICON_ITEM_SIZE
);
1651 off
+= BIN_GROUP_ICON_ITEM_SIZE
;
1656 windres_put_16 (wrbfd
, bgi
.sig1
, 0);
1657 windres_put_16 (wrbfd
, bgi
.sig2
, 1);
1658 windres_put_16 (wrbfd
, bgi
.count
, c
);
1659 set_windres_bfd_content (wrbfd
, &bgi
, start
, BIN_GROUP_ICON_SIZE
);
1664 /* Convert a menu resource to binary. */
1667 res_to_bin_menu (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menu
*menu
)
1671 menuex
= extended_menu (menu
);
1678 windres_put_16 (wrbfd
, bm
.sig1
, 0);
1679 windres_put_16 (wrbfd
, bm
.sig2
, 0);
1680 set_windres_bfd_content (wrbfd
, &bm
, off
, BIN_MENU_SIZE
);
1684 struct bin_menuex bm
;
1685 windres_put_16 (wrbfd
, bm
.sig1
, 1);
1686 windres_put_16 (wrbfd
, bm
.sig2
, 4);
1687 windres_put_32 (wrbfd
, bm
.help
, menu
->help
);
1688 set_windres_bfd_content (wrbfd
, &bm
, off
, BIN_MENUEX_SIZE
);
1691 off
+= (menuex
!= 0 ? BIN_MENUEX_SIZE
: BIN_MENU_SIZE
);
1694 off
= res_to_bin_menuitems (wrbfd
, off
, menu
->items
);
1698 off
= res_to_bin_menuexitems (wrbfd
, off
, menu
->items
);
1703 /* Convert menu items to binary. */
1706 res_to_bin_menuitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1708 const rc_menuitem
*mi
;
1710 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1712 struct bin_menuitem bmi
;
1716 if (mi
->next
== NULL
)
1717 flags
|= MENUITEM_ENDMENU
;
1718 if (mi
->popup
!= NULL
)
1719 flags
|= MENUITEM_POPUP
;
1723 windres_put_16 (wrbfd
, bmi
.flags
, flags
);
1724 if (mi
->popup
== NULL
)
1725 windres_put_16 (wrbfd
, bmi
.id
, mi
->id
);
1726 set_windres_bfd_content (wrbfd
, &bmi
, off
,
1727 mi
->popup
== NULL
? BIN_MENUITEM_SIZE
1728 : BIN_MENUITEM_POPUP_SIZE
);
1730 off
+= (mi
->popup
== NULL
? BIN_MENUITEM_SIZE
: BIN_MENUITEM_POPUP_SIZE
);
1732 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1734 if (mi
->popup
!= NULL
)
1736 off
= res_to_bin_menuitems (wrbfd
, off
, mi
->popup
);
1742 /* Convert menuex items to binary. */
1745 res_to_bin_menuexitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1747 rc_uint_type off_delta
= off
;
1748 const rc_menuitem
*mi
;
1750 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1752 struct bin_menuitemex bmi
;
1755 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1758 if (mi
->next
== NULL
)
1760 if (mi
->popup
!= NULL
)
1765 windres_put_32 (wrbfd
, bmi
.type
, mi
->type
);
1766 windres_put_32 (wrbfd
, bmi
.state
, mi
->state
);
1767 windres_put_32 (wrbfd
, bmi
.id
, mi
->id
);
1768 windres_put_16 (wrbfd
, bmi
.flags
, flags
);
1769 set_windres_bfd_content (wrbfd
, &bmi
, off
, BIN_MENUITEMEX_SIZE
);
1771 off
+= BIN_MENUITEMEX_SIZE
;
1773 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1775 if (mi
->popup
!= NULL
)
1779 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1783 windres_put_32 (wrbfd
, help
, mi
->help
);
1784 set_windres_bfd_content (wrbfd
, help
, off
, 4);
1787 off
= res_to_bin_menuexitems (wrbfd
, off
, mi
->popup
);
1793 /* Convert an rcdata resource to binary. This is also used to convert
1794 other information which happens to be stored in rc_rcdata_item lists
1798 res_to_bin_rcdata (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_rcdata_item
*items
)
1800 const rc_rcdata_item
*ri
;
1802 for (ri
= items
; ri
!= NULL
; ri
= ri
->next
)
1816 len
= ri
->u
.string
.length
;
1818 case RCDATA_WSTRING
:
1819 len
= ri
->u
.wstring
.length
* sizeof (unichar
);
1822 len
= ri
->u
.buffer
.length
;
1828 bfd_byte
*hp
= &h
[0];
1832 windres_put_16 (wrbfd
, hp
, ri
->u
.word
);
1835 windres_put_32 (wrbfd
, hp
, ri
->u
.dword
);
1838 hp
= (bfd_byte
*) ri
->u
.string
.s
;
1840 case RCDATA_WSTRING
:
1844 hp
= (bfd_byte
*) reswr_alloc (len
);
1845 for (i
= 0; i
< ri
->u
.wstring
.length
; i
++)
1846 windres_put_16 (wrbfd
, hp
+ i
* sizeof (unichar
), ri
->u
.wstring
.w
[i
]);
1850 hp
= (bfd_byte
*) ri
->u
.buffer
.data
;
1853 set_windres_bfd_content (wrbfd
, hp
, off
, len
);
1860 /* Convert a stringtable resource to binary. */
1863 res_to_bin_stringtable (windres_bfd
*wrbfd
, rc_uint_type off
,
1864 const rc_stringtable
*st
)
1868 for (i
= 0; i
< 16; i
++)
1870 rc_uint_type slen
, length
;
1873 slen
= (rc_uint_type
) st
->strings
[i
].length
;
1874 s
= st
->strings
[i
].string
;
1876 length
= 2 + slen
* 2;
1882 hp
= (bfd_byte
*) reswr_alloc (length
);
1883 windres_put_16 (wrbfd
, hp
, slen
);
1885 for (j
= 0; j
< slen
; j
++)
1886 windres_put_16 (wrbfd
, hp
+ 2 + j
* 2, s
[j
]);
1887 set_windres_bfd_content (wrbfd
, hp
, off
, length
);
1894 /* Convert an ASCII string to a unicode binary string. This always
1895 returns exactly one bindata structure. */
1898 string_to_unicode_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const char *s
)
1902 len
= (rc_uint_type
) strlen (s
);
1909 hp
= (bfd_byte
*) reswr_alloc ((len
+ 1) * sizeof (unichar
));
1911 for (i
= 0; i
< len
; i
++)
1912 windres_put_16 (wrbfd
, hp
+ i
* 2, s
[i
]);
1913 windres_put_16 (wrbfd
, hp
+ i
* 2, 0);
1914 set_windres_bfd_content (wrbfd
, hp
, off
, (len
+ 1) * sizeof (unichar
));
1916 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1921 res_to_bin_toolbar (windres_bfd
*wrbfd
, rc_uint_type off
, rc_toolbar
*tb
)
1925 struct bin_toolbar bt
;
1926 windres_put_32 (wrbfd
, bt
.button_width
, tb
->button_width
);
1927 windres_put_32 (wrbfd
, bt
.button_height
, tb
->button_height
);
1928 windres_put_32 (wrbfd
, bt
.nitems
, tb
->nitems
);
1929 set_windres_bfd_content (wrbfd
, &bt
, off
, BIN_TOOLBAR_SIZE
);
1932 rc_toolbar_item
*it
;
1936 ids
= (bfd_byte
*) reswr_alloc (tb
->nitems
* 4);
1940 windres_put_32 (wrbfd
, ids
+ i
, it
->id
.u
.id
);
1944 set_windres_bfd_content (wrbfd
, ids
, off
+ BIN_TOOLBAR_SIZE
, i
);
1947 off
+= BIN_TOOLBAR_SIZE
+ tb
->nitems
* 4;
1952 /* Convert a versioninfo resource to binary. */
1955 res_to_bin_versioninfo (windres_bfd
*wrbfd
, rc_uint_type off
,
1956 const rc_versioninfo
*versioninfo
)
1958 rc_uint_type off_delta
= off
;
1960 struct bin_versioninfo bvi
;
1964 off
+= BIN_VERSIONINFO_SIZE
;
1965 off
= string_to_unicode_bin (wrbfd
, off
, "VS_VERSION_INFO");
1966 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1968 if (versioninfo
->fixed
!= NULL
)
1972 struct bin_fixed_versioninfo bfv
;
1973 const rc_fixed_versioninfo
*fi
;
1975 fi
= versioninfo
->fixed
;
1976 windres_put_32 (wrbfd
, bfv
.sig1
, 0xfeef04bd);
1977 windres_put_32 (wrbfd
, bfv
.sig2
, 0x10000);
1978 windres_put_32 (wrbfd
, bfv
.file_version
, fi
->file_version_ms
);
1979 windres_put_32 (wrbfd
, bfv
.file_version_ls
, fi
->file_version_ls
);
1980 windres_put_32 (wrbfd
, bfv
.product_version_ms
, fi
->product_version_ms
);
1981 windres_put_32 (wrbfd
, bfv
.product_version_ls
, fi
->product_version_ls
);
1982 windres_put_32 (wrbfd
, bfv
.file_flags_mask
, fi
->file_flags_mask
);
1983 windres_put_32 (wrbfd
, bfv
.file_flags
, fi
->file_flags
);
1984 windres_put_32 (wrbfd
, bfv
.file_os
, fi
->file_os
);
1985 windres_put_32 (wrbfd
, bfv
.file_type
, fi
->file_type
);
1986 windres_put_32 (wrbfd
, bfv
.file_subtype
, fi
->file_subtype
);
1987 windres_put_32 (wrbfd
, bfv
.file_date_ms
, fi
->file_date_ms
);
1988 windres_put_32 (wrbfd
, bfv
.file_date_ls
, fi
->file_date_ls
);
1989 set_windres_bfd_content (wrbfd
, &bfv
, off
, BIN_FIXED_VERSIONINFO_SIZE
);
1991 off
+= BIN_FIXED_VERSIONINFO_SIZE
;
1994 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
1996 struct bin_ver_info bv
;
1997 rc_uint_type bv_off
;
1999 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2003 off
+= BIN_VER_INFO_SIZE
;
2009 case VERINFO_STRING
:
2011 struct bin_ver_info bvsd
;
2012 rc_uint_type vs_off
;
2013 const rc_ver_stringinfo
*vs
;
2015 off
= string_to_unicode_bin (wrbfd
, off
, "StringFileInfo");
2016 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2020 off
+= BIN_VER_INFO_SIZE
;
2022 off
= unicode_to_bin (wrbfd
, off
, vi
->u
.string
.language
);
2024 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
2026 struct bin_ver_info bvss
;
2027 rc_uint_type vss_off
,str_off
;
2029 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2032 off
+= BIN_VER_INFO_SIZE
;
2034 off
= unicode_to_bin (wrbfd
, off
, vs
->key
);
2036 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2039 off
= unicode_to_bin (wrbfd
, off
, vs
->value
);
2042 windres_put_16 (wrbfd
, bvss
.size
, off
- vss_off
);
2043 windres_put_16 (wrbfd
, bvss
.sig1
, (off
- str_off
) / 2);
2044 windres_put_16 (wrbfd
, bvss
.sig2
, 1);
2045 set_windres_bfd_content (wrbfd
, &bvss
, vss_off
,
2051 windres_put_16 (wrbfd
, bvsd
.size
, off
- vs_off
);
2052 windres_put_16 (wrbfd
, bvsd
.sig1
, 0);
2053 windres_put_16 (wrbfd
, bvsd
.sig2
, 0);
2054 set_windres_bfd_content (wrbfd
, &bvsd
, vs_off
,
2062 rc_uint_type vvd_off
, vvvd_off
;
2063 struct bin_ver_info bvvd
;
2064 const rc_ver_varinfo
*vv
;
2066 off
= string_to_unicode_bin (wrbfd
, off
, "VarFileInfo");
2068 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2071 off
+= BIN_VER_INFO_SIZE
;
2073 off
= unicode_to_bin (wrbfd
, off
, vi
->u
.var
.key
);
2075 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2079 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2085 windres_put_16 (wrbfd
, &vvsd
[0], vv
->language
);
2086 windres_put_16 (wrbfd
, &vvsd
[2], vv
->charset
);
2087 set_windres_bfd_content (wrbfd
, vvsd
, off
, 4);
2093 windres_put_16 (wrbfd
, bvvd
.size
, off
- vvd_off
);
2094 windres_put_16 (wrbfd
, bvvd
.sig1
, off
- vvvd_off
);
2095 windres_put_16 (wrbfd
, bvvd
.sig2
, 0);
2096 set_windres_bfd_content (wrbfd
, &bvvd
, vvd_off
,
2106 windres_put_16 (wrbfd
, bv
.size
, off
-bv_off
);
2107 windres_put_16 (wrbfd
, bv
.sig1
, 0);
2108 windres_put_16 (wrbfd
, bv
.sig2
, 0);
2109 set_windres_bfd_content (wrbfd
, &bv
, bv_off
,
2116 windres_put_16 (wrbfd
, bvi
.size
, off
- start
);
2117 windres_put_16 (wrbfd
, bvi
.fixed_size
,
2118 versioninfo
->fixed
== NULL
? 0
2119 : BIN_FIXED_VERSIONINFO_SIZE
);
2120 windres_put_16 (wrbfd
, bvi
.sig2
, 0);
2121 set_windres_bfd_content (wrbfd
, &bvi
, start
, BIN_VER_INFO_SIZE
);
2126 /* Convert a generic resource to binary. */
2129 res_to_bin_generic (windres_bfd
*wrbfd
, rc_uint_type off
, rc_uint_type length
,
2130 const bfd_byte
*data
)
2132 if (wrbfd
&& length
!= 0)
2133 set_windres_bfd_content (wrbfd
, data
, off
, length
);
2134 return off
+ (rc_uint_type
) length
;