1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright 1997, 1998, 1999, 2002, 2003, 2005, 2006, 2007, 2009, 2010, 2011
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
, got
;
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, &got
);
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
), &got
);
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) + 3) & ~3;
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_stringtable
**ppvst
;
1032 vi
->type
= VERINFO_STRING
;
1034 get_version_header (wrbfd
, data
, length
, "StringFileInfo",
1035 (unichar
**) NULL
, &verlen
, &vallen
, &type
,
1039 fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen
);
1046 vi
->u
.string
.stringtables
= NULL
;
1047 ppvst
= &vi
->u
.string
.stringtables
;
1051 rc_ver_stringtable
*vst
;
1052 rc_uint_type stverlen
;
1053 rc_ver_stringinfo
**ppvs
;
1056 toosmall (_("version stringtable"));
1058 vst
= (rc_ver_stringtable
*) res_alloc (sizeof (rc_ver_stringtable
));
1060 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1061 &vst
->language
, &stverlen
, &vallen
, &type
, &off
);
1064 fatal (_("unexpected version stringtable value length %ld"), (long) vallen
);
1072 vst
->strings
= NULL
;
1073 ppvs
= &vst
->strings
;
1075 while (stverlen
> 0)
1077 rc_ver_stringinfo
*vs
;
1078 rc_uint_type sverlen
, vslen
, valoff
;
1081 toosmall (_("version string"));
1083 vs
= (rc_ver_stringinfo
*) res_alloc (sizeof (rc_ver_stringinfo
));
1085 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1086 &vs
->key
, &sverlen
, &vallen
, &type
, &off
);
1091 vs
->value
= get_unicode (wrbfd
, data
, length
, &vslen
);
1092 valoff
= vslen
* 2 + 2;
1093 valoff
= (valoff
+ 3) & ~3;
1095 if (off
+ valoff
!= sverlen
)
1096 fatal (_("unexpected version string length %ld != %ld + %ld"),
1097 (long) sverlen
, (long) off
, (long) valoff
);
1102 if (stverlen
< sverlen
)
1103 fatal (_("unexpected version string length %ld < %ld"),
1104 (long) verlen
, (long) sverlen
);
1105 stverlen
-= sverlen
;
1120 rc_ver_varinfo
**ppvv
;
1122 vi
->type
= VERINFO_VAR
;
1124 get_version_header (wrbfd
, data
, length
, "VarFileInfo",
1125 (unichar
**) NULL
, &verlen
, &vallen
, &type
,
1129 fatal (_("unexpected varfileinfo value length %ld"), (long) vallen
);
1134 get_version_header (wrbfd
, data
, length
, (const char *) NULL
,
1135 &vi
->u
.var
.key
, &verlen
, &vallen
, &type
, &off
);
1140 vi
->u
.var
.var
= NULL
;
1141 ppvv
= &vi
->u
.var
.var
;
1148 toosmall (_("version varfileinfo"));
1150 vv
= (rc_ver_varinfo
*) res_alloc (sizeof (rc_ver_varinfo
));
1152 vv
->language
= windres_get_16 (wrbfd
, data
, 2);
1153 vv
->charset
= windres_get_16 (wrbfd
, data
+ 2, 2);
1163 fatal (_("unexpected version value length %ld"), (long) vallen
);
1169 fatal (_("unexpected version string"));
1176 v
= (rc_versioninfo
*) res_alloc (sizeof (rc_versioninfo
));
1180 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1181 r
->type
= RES_TYPE_VERSIONINFO
;
1182 r
->u
.versioninfo
= v
;
1187 /* Convert an arbitrary user defined resource from binary. */
1189 static rc_res_resource
*
1190 bin_to_res_userdata (windres_bfd
*wrbfd ATTRIBUTE_UNUSED
, const bfd_byte
*data
,
1191 rc_uint_type length
)
1196 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1199 ri
->type
= RCDATA_BUFFER
;
1200 ri
->u
.buffer
.length
= length
;
1201 ri
->u
.buffer
.data
= data
;
1203 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1204 r
->type
= RES_TYPE_USERDATA
;
1210 static rc_res_resource
*
1211 bin_to_res_toolbar (windres_bfd
*wrbfd
, const bfd_byte
*data
, rc_uint_type length
)
1217 ri
= (rc_toolbar
*) res_alloc (sizeof (rc_toolbar
));
1218 ri
->button_width
= windres_get_32 (wrbfd
, data
, 4);
1219 ri
->button_height
= windres_get_32 (wrbfd
, data
+ 4, 4);
1220 ri
->nitems
= windres_get_32 (wrbfd
, data
+ 8, 4);
1225 for (i
=0 ; i
< ri
->nitems
; i
++)
1227 rc_toolbar_item
*it
;
1228 it
= (rc_toolbar_item
*) res_alloc (sizeof (rc_toolbar_item
));
1230 it
->id
.u
.id
= (int) windres_get_32 (wrbfd
, data
, 4);
1231 it
->prev
= it
->next
= NULL
;
1235 rc_toolbar_item
*ii
= ri
->items
;
1236 while (ii
->next
!= NULL
)
1244 r
= (rc_res_resource
*) res_alloc (sizeof *r
);
1245 r
->type
= RES_TYPE_TOOLBAR
;
1251 /* Local functions used to convert resources to binary format. */
1253 static rc_uint_type
resid_to_bin (windres_bfd
*, rc_uint_type
, rc_res_id
);
1254 static rc_uint_type
unicode_to_bin (windres_bfd
*, rc_uint_type
, const unichar
*);
1255 static rc_uint_type
res_to_bin_accelerator (windres_bfd
*, rc_uint_type
, const rc_accelerator
*);
1256 static rc_uint_type
res_to_bin_cursor (windres_bfd
*, rc_uint_type
, const rc_cursor
*);
1257 static rc_uint_type
res_to_bin_group_cursor (windres_bfd
*, rc_uint_type
, const rc_group_cursor
*);
1258 static rc_uint_type
res_to_bin_dialog (windres_bfd
*, rc_uint_type
, const rc_dialog
*);
1259 static rc_uint_type
res_to_bin_fontdir (windres_bfd
*, rc_uint_type
, const rc_fontdir
*);
1260 static rc_uint_type
res_to_bin_group_icon (windres_bfd
*, rc_uint_type
, const rc_group_icon
*);
1261 static rc_uint_type
res_to_bin_menu (windres_bfd
*, rc_uint_type
, const rc_menu
*);
1262 static rc_uint_type
res_to_bin_menuitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1263 static rc_uint_type
res_to_bin_menuexitems (windres_bfd
*, rc_uint_type
, const rc_menuitem
*);
1264 static rc_uint_type
res_to_bin_rcdata (windres_bfd
*, rc_uint_type
, const rc_rcdata_item
*);
1265 static rc_uint_type
res_to_bin_stringtable (windres_bfd
*, rc_uint_type
, const rc_stringtable
*);
1266 static rc_uint_type
string_to_unicode_bin (windres_bfd
*, rc_uint_type
, const char *);
1267 static rc_uint_type
res_to_bin_toolbar (windres_bfd
*, rc_uint_type
, rc_toolbar
*tb
);
1268 static rc_uint_type
res_to_bin_versioninfo (windres_bfd
*, rc_uint_type
, const rc_versioninfo
*);
1269 static rc_uint_type
res_to_bin_generic (windres_bfd
*, rc_uint_type
, rc_uint_type
,
1272 /* Convert a resource to binary. */
1275 res_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_res_resource
*res
)
1279 case RES_TYPE_BITMAP
:
1282 case RES_TYPE_MESSAGETABLE
:
1283 return res_to_bin_generic (wrbfd
, off
, res
->u
.data
.length
, res
->u
.data
.data
);
1284 case RES_TYPE_ACCELERATOR
:
1285 return res_to_bin_accelerator (wrbfd
, off
, res
->u
.acc
);
1286 case RES_TYPE_CURSOR
:
1287 return res_to_bin_cursor (wrbfd
, off
, res
->u
.cursor
);
1288 case RES_TYPE_GROUP_CURSOR
:
1289 return res_to_bin_group_cursor (wrbfd
, off
, res
->u
.group_cursor
);
1290 case RES_TYPE_DIALOG
:
1291 return res_to_bin_dialog (wrbfd
, off
, res
->u
.dialog
);
1292 case RES_TYPE_FONTDIR
:
1293 return res_to_bin_fontdir (wrbfd
, off
, res
->u
.fontdir
);
1294 case RES_TYPE_GROUP_ICON
:
1295 return res_to_bin_group_icon (wrbfd
, off
, res
->u
.group_icon
);
1297 return res_to_bin_menu (wrbfd
, off
, res
->u
.menu
);
1298 case RES_TYPE_STRINGTABLE
:
1299 return res_to_bin_stringtable (wrbfd
, off
, res
->u
.stringtable
);
1300 case RES_TYPE_VERSIONINFO
:
1301 return res_to_bin_versioninfo (wrbfd
, off
, res
->u
.versioninfo
);
1302 case RES_TYPE_TOOLBAR
:
1303 return res_to_bin_toolbar (wrbfd
, off
, res
->u
.toolbar
);
1304 case RES_TYPE_USERDATA
:
1305 case RES_TYPE_RCDATA
:
1307 return res_to_bin_rcdata (wrbfd
, off
, res
->u
.rcdata
);
1311 /* Convert a resource ID to binary. This always returns exactly one
1312 bindata structure. */
1315 resid_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, rc_res_id id
)
1321 struct bin_res_id bri
;
1323 windres_put_16 (wrbfd
, bri
.sig
, 0xffff);
1324 windres_put_16 (wrbfd
, bri
.id
, id
.u
.id
);
1325 set_windres_bfd_content (wrbfd
, &bri
, off
, BIN_RES_ID
);
1331 rc_uint_type len
= (id
.u
.n
.name
? unichar_len (id
.u
.n
.name
) : 0);
1334 bfd_byte
*d
= (bfd_byte
*) reswr_alloc ((len
+ 1) * sizeof (unichar
));
1336 for (i
= 0; i
< len
; i
++)
1337 windres_put_16 (wrbfd
, d
+ (i
* sizeof (unichar
)), id
.u
.n
.name
[i
]);
1338 windres_put_16 (wrbfd
, d
+ (len
* sizeof (unichar
)), 0);
1339 set_windres_bfd_content (wrbfd
, d
, off
, (len
+ 1) * sizeof (unichar
));
1341 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1346 /* Convert a null terminated unicode string to binary. This always
1347 returns exactly one bindata structure. */
1350 unicode_to_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const unichar
*str
)
1352 rc_uint_type len
= 0;
1355 len
= unichar_len (str
);
1361 d
= (bfd_byte
*) reswr_alloc ( (len
+ 1) * sizeof (unichar
));
1362 for (i
= 0; i
< len
; i
++)
1363 windres_put_16 (wrbfd
, d
+ (i
* sizeof (unichar
)), str
[i
]);
1364 windres_put_16 (wrbfd
, d
+ (len
* sizeof (unichar
)), 0);
1365 set_windres_bfd_content (wrbfd
, d
, off
, (len
+ 1) * sizeof (unichar
));
1367 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1372 /* Convert an accelerator resource to binary. */
1375 res_to_bin_accelerator (windres_bfd
*wrbfd
, rc_uint_type off
,
1376 const rc_accelerator
*accelerators
)
1378 const rc_accelerator
*a
;
1380 for (a
= accelerators
; a
!= NULL
; a
= a
->next
)
1384 struct bin_accelerator ba
;
1386 windres_put_16 (wrbfd
, ba
.flags
, a
->flags
| (a
->next
!= NULL
? 0 : ACC_LAST
));
1387 windres_put_16 (wrbfd
, ba
.key
, a
->key
);
1388 windres_put_16 (wrbfd
, ba
.id
, a
->id
);
1389 windres_put_16 (wrbfd
, ba
.pad
, 0);
1390 set_windres_bfd_content (wrbfd
, &ba
, off
, BIN_ACCELERATOR_SIZE
);
1392 off
+= BIN_ACCELERATOR_SIZE
;
1397 /* Convert a cursor resource to binary. */
1400 res_to_bin_cursor (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_cursor
*c
)
1404 struct bin_cursor bc
;
1406 windres_put_16 (wrbfd
, bc
.xhotspot
, c
->xhotspot
);
1407 windres_put_16 (wrbfd
, bc
.yhotspot
, c
->yhotspot
);
1408 set_windres_bfd_content (wrbfd
, &bc
, off
, BIN_CURSOR_SIZE
);
1410 set_windres_bfd_content (wrbfd
, c
->data
, off
+ BIN_CURSOR_SIZE
, c
->length
);
1412 off
= (off
+ BIN_CURSOR_SIZE
+ (rc_uint_type
) c
->length
);
1416 /* Convert a group cursor resource to binary. */
1419 res_to_bin_group_cursor (windres_bfd
*wrbfd
, rc_uint_type off
,
1420 const rc_group_cursor
*group_cursors
)
1423 const rc_group_cursor
*gc
;
1424 struct bin_group_cursor bgc
;
1425 struct bin_group_cursor_item bgci
;
1426 rc_uint_type start
= off
;
1428 off
+= BIN_GROUP_CURSOR_SIZE
;
1430 for (c
= 0, gc
= group_cursors
; gc
!= NULL
; gc
= gc
->next
, c
++)
1434 windres_put_16 (wrbfd
, bgci
.width
, gc
->width
);
1435 windres_put_16 (wrbfd
, bgci
.height
, gc
->height
);
1436 windres_put_16 (wrbfd
, bgci
.planes
, gc
->planes
);
1437 windres_put_16 (wrbfd
, bgci
.bits
, gc
->bits
);
1438 windres_put_32 (wrbfd
, bgci
.bytes
, gc
->bytes
);
1439 windres_put_16 (wrbfd
, bgci
.index
, gc
->index
);
1440 set_windres_bfd_content (wrbfd
, &bgci
, off
, BIN_GROUP_CURSOR_ITEM_SIZE
);
1443 off
+= BIN_GROUP_CURSOR_ITEM_SIZE
;
1447 windres_put_16 (wrbfd
, bgc
.sig1
, 0);
1448 windres_put_16 (wrbfd
, bgc
.sig2
, 2);
1449 windres_put_16 (wrbfd
, bgc
.nitems
, c
);
1450 set_windres_bfd_content (wrbfd
, &bgc
, start
, BIN_GROUP_CURSOR_SIZE
);
1455 /* Convert a dialog resource to binary. */
1458 res_to_bin_dialog (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_dialog
*dialog
)
1460 rc_uint_type off_delta
;
1461 rc_uint_type start
, marker
;
1464 rc_dialog_control
*dc
;
1465 struct bin_dialogex bdx
;
1466 struct bin_dialog bd
;
1470 dialogex
= extended_dialog (dialog
);
1476 windres_put_32 (wrbfd
, bd
.style
, dialog
->style
);
1477 windres_put_32 (wrbfd
, bd
.exstyle
, dialog
->exstyle
);
1478 windres_put_16 (wrbfd
, bd
.x
, dialog
->x
);
1479 windres_put_16 (wrbfd
, bd
.y
, dialog
->y
);
1480 windres_put_16 (wrbfd
, bd
.width
, dialog
->width
);
1481 windres_put_16 (wrbfd
, bd
.height
, dialog
->height
);
1485 windres_put_16 (wrbfd
, bdx
.sig1
, 1);
1486 windres_put_16 (wrbfd
, bdx
.sig2
, 0xffff);
1487 windres_put_32 (wrbfd
, bdx
.help
, (dialog
->ex
? dialog
->ex
->help
: 0));
1488 windres_put_32 (wrbfd
, bdx
.exstyle
, dialog
->exstyle
);
1489 windres_put_32 (wrbfd
, bdx
.style
, dialog
->style
);
1490 windres_put_16 (wrbfd
, bdx
.x
, dialog
->x
);
1491 windres_put_16 (wrbfd
, bdx
.y
, dialog
->y
);
1492 windres_put_16 (wrbfd
, bdx
.width
, dialog
->width
);
1493 windres_put_16 (wrbfd
, bdx
.height
, dialog
->height
);
1497 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_SIZE
: BIN_DIALOG_SIZE
);
1499 off
= resid_to_bin (wrbfd
, off
, dialog
->menu
);
1500 off
= resid_to_bin (wrbfd
, off
, dialog
->class);
1501 off
= unicode_to_bin (wrbfd
, off
, dialog
->caption
);
1503 if ((dialog
->style
& DS_SETFONT
) != 0)
1509 struct bin_dialogfont bdf
;
1510 windres_put_16 (wrbfd
, bdf
.pointsize
, dialog
->pointsize
);
1511 set_windres_bfd_content (wrbfd
, &bdf
, off
, BIN_DIALOGFONT_SIZE
);
1515 struct bin_dialogexfont bdxf
;
1516 windres_put_16 (wrbfd
, bdxf
.pointsize
, dialog
->pointsize
);
1517 windres_put_16 (wrbfd
, bdxf
.weight
, (dialog
->ex
== NULL
? 0 : dialog
->ex
->weight
));
1518 windres_put_8 (wrbfd
, bdxf
.italic
, (dialog
->ex
== NULL
? 0 : dialog
->ex
->italic
));
1519 windres_put_8 (wrbfd
, bdxf
.charset
, (dialog
->ex
== NULL
? 1 : dialog
->ex
->charset
));
1520 set_windres_bfd_content (wrbfd
, &bdxf
, off
, BIN_DIALOGEXFONT_SIZE
);
1523 off
+= (dialogex
? BIN_DIALOGEXFONT_SIZE
: BIN_DIALOGFONT_SIZE
);
1524 off
= unicode_to_bin (wrbfd
, off
, dialog
->font
);
1526 for (c
= 0, dc
= dialog
->controls
; dc
!= NULL
; dc
= dc
->next
, c
++)
1528 bfd_byte dc_rclen
[2];
1530 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1535 struct bin_dialog_control bdc
;
1537 windres_put_32 (wrbfd
, bdc
.style
, dc
->style
);
1538 windres_put_32 (wrbfd
, bdc
.exstyle
, dc
->exstyle
);
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_16 (wrbfd
, bdc
.id
, dc
->id
);
1544 set_windres_bfd_content (wrbfd
, &bdc
, off
, BIN_DIALOG_CONTROL_SIZE
);
1548 struct bin_dialogex_control bdc
;
1550 windres_put_32 (wrbfd
, bdc
.help
, dc
->help
);
1551 windres_put_32 (wrbfd
, bdc
.exstyle
, dc
->exstyle
);
1552 windres_put_32 (wrbfd
, bdc
.style
, dc
->style
);
1553 windres_put_16 (wrbfd
, bdc
.x
, dc
->x
);
1554 windres_put_16 (wrbfd
, bdc
.y
, dc
->y
);
1555 windres_put_16 (wrbfd
, bdc
.width
, dc
->width
);
1556 windres_put_16 (wrbfd
, bdc
.height
, dc
->height
);
1557 windres_put_32 (wrbfd
, bdc
.id
, dc
->id
);
1558 set_windres_bfd_content (wrbfd
, &bdc
, off
, BIN_DIALOGEX_CONTROL_SIZE
);
1561 off
+= (dialogex
!= 0 ? BIN_DIALOGEX_CONTROL_SIZE
: BIN_DIALOG_CONTROL_SIZE
);
1563 off
= resid_to_bin (wrbfd
, off
, dc
->class);
1564 off
= resid_to_bin (wrbfd
, off
, dc
->text
);
1566 marker
= off
; /* Save two bytes for size of optional data. */
1569 if (dc
->data
== NULL
)
1572 windres_put_16 (wrbfd
, dc_rclen
, 0);
1576 rc_uint_type saved_off
= off
;
1577 rc_uint_type old_off
;
1578 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1581 off
= res_to_bin_rcdata (wrbfd
, off
, dc
->data
);
1582 if ((off
- old_off
) == 0)
1583 old_off
= off
= saved_off
;
1585 windres_put_16 (wrbfd
, dc_rclen
, off
- old_off
);
1588 set_windres_bfd_content (wrbfd
, dc_rclen
, marker
, 2);
1593 windres_put_16 (wrbfd
, (dialogex
!= 0 ? bdx
.off
: bd
.off
), c
);
1595 set_windres_bfd_content (wrbfd
, &bd
, start
, BIN_DIALOG_SIZE
);
1597 set_windres_bfd_content (wrbfd
, &bdx
, start
, BIN_DIALOGEX_SIZE
);
1603 /* Convert a fontdir resource to binary. */
1605 res_to_bin_fontdir (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_fontdir
*fontdirs
)
1609 const rc_fontdir
*fd
;
1614 for (c
= 0, fd
= fontdirs
; fd
!= NULL
; fd
= fd
->next
, c
++)
1619 windres_put_16 (wrbfd
, d
, fd
->index
);
1620 set_windres_bfd_content (wrbfd
, d
, off
, 2);
1622 set_windres_bfd_content (wrbfd
, fd
->data
, off
+ 2, fd
->length
);
1624 off
+= (rc_uint_type
) fd
->length
+ 2;
1630 windres_put_16 (wrbfd
, d
, c
);
1631 set_windres_bfd_content (wrbfd
, d
, start
, 2);
1636 /* Convert a group icon resource to binary. */
1639 res_to_bin_group_icon (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_group_icon
*group_icons
)
1642 struct bin_group_icon bgi
;
1644 const rc_group_icon
*gi
;
1647 off
+= BIN_GROUP_ICON_SIZE
;
1649 for (c
= 0, gi
= group_icons
; gi
!= NULL
; gi
= gi
->next
, c
++)
1651 struct bin_group_icon_item bgii
;
1655 windres_put_8 (wrbfd
, bgii
.width
, gi
->width
);
1656 windres_put_8 (wrbfd
, bgii
.height
, gi
->height
);
1657 windres_put_8 (wrbfd
, bgii
.colors
, gi
->colors
);
1658 windres_put_8 (wrbfd
, bgii
.pad
, 0);
1659 windres_put_16 (wrbfd
, bgii
.planes
, gi
->planes
);
1660 windres_put_16 (wrbfd
, bgii
.bits
, gi
->bits
);
1661 windres_put_32 (wrbfd
, bgii
.bytes
, gi
->bytes
);
1662 windres_put_16 (wrbfd
, bgii
.index
, gi
->index
);
1663 set_windres_bfd_content (wrbfd
, &bgii
, off
, BIN_GROUP_ICON_ITEM_SIZE
);
1665 off
+= BIN_GROUP_ICON_ITEM_SIZE
;
1670 windres_put_16 (wrbfd
, bgi
.sig1
, 0);
1671 windres_put_16 (wrbfd
, bgi
.sig2
, 1);
1672 windres_put_16 (wrbfd
, bgi
.count
, c
);
1673 set_windres_bfd_content (wrbfd
, &bgi
, start
, BIN_GROUP_ICON_SIZE
);
1678 /* Convert a menu resource to binary. */
1681 res_to_bin_menu (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menu
*menu
)
1685 menuex
= extended_menu (menu
);
1692 windres_put_16 (wrbfd
, bm
.sig1
, 0);
1693 windres_put_16 (wrbfd
, bm
.sig2
, 0);
1694 set_windres_bfd_content (wrbfd
, &bm
, off
, BIN_MENU_SIZE
);
1698 struct bin_menuex bm
;
1699 windres_put_16 (wrbfd
, bm
.sig1
, 1);
1700 windres_put_16 (wrbfd
, bm
.sig2
, 4);
1701 windres_put_32 (wrbfd
, bm
.help
, menu
->help
);
1702 set_windres_bfd_content (wrbfd
, &bm
, off
, BIN_MENUEX_SIZE
);
1705 off
+= (menuex
!= 0 ? BIN_MENUEX_SIZE
: BIN_MENU_SIZE
);
1708 off
= res_to_bin_menuitems (wrbfd
, off
, menu
->items
);
1712 off
= res_to_bin_menuexitems (wrbfd
, off
, menu
->items
);
1717 /* Convert menu items to binary. */
1720 res_to_bin_menuitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1722 const rc_menuitem
*mi
;
1724 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1726 struct bin_menuitem bmi
;
1730 if (mi
->next
== NULL
)
1731 flags
|= MENUITEM_ENDMENU
;
1732 if (mi
->popup
!= NULL
)
1733 flags
|= MENUITEM_POPUP
;
1737 windres_put_16 (wrbfd
, bmi
.flags
, flags
);
1738 if (mi
->popup
== NULL
)
1739 windres_put_16 (wrbfd
, bmi
.id
, mi
->id
);
1740 set_windres_bfd_content (wrbfd
, &bmi
, off
,
1741 mi
->popup
== NULL
? BIN_MENUITEM_SIZE
1742 : BIN_MENUITEM_POPUP_SIZE
);
1744 off
+= (mi
->popup
== NULL
? BIN_MENUITEM_SIZE
: BIN_MENUITEM_POPUP_SIZE
);
1746 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1748 if (mi
->popup
!= NULL
)
1750 off
= res_to_bin_menuitems (wrbfd
, off
, mi
->popup
);
1756 /* Convert menuex items to binary. */
1759 res_to_bin_menuexitems (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_menuitem
*items
)
1761 rc_uint_type off_delta
= off
;
1762 const rc_menuitem
*mi
;
1764 for (mi
= items
; mi
!= NULL
; mi
= mi
->next
)
1766 struct bin_menuitemex bmi
;
1769 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1772 if (mi
->next
== NULL
)
1774 if (mi
->popup
!= NULL
)
1779 windres_put_32 (wrbfd
, bmi
.type
, mi
->type
);
1780 windres_put_32 (wrbfd
, bmi
.state
, mi
->state
);
1781 windres_put_32 (wrbfd
, bmi
.id
, mi
->id
);
1782 windres_put_16 (wrbfd
, bmi
.flags
, flags
);
1783 set_windres_bfd_content (wrbfd
, &bmi
, off
, BIN_MENUITEMEX_SIZE
);
1785 off
+= BIN_MENUITEMEX_SIZE
;
1787 off
= unicode_to_bin (wrbfd
, off
, mi
->text
);
1789 if (mi
->popup
!= NULL
)
1793 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1797 windres_put_32 (wrbfd
, help
, mi
->help
);
1798 set_windres_bfd_content (wrbfd
, help
, off
, 4);
1801 off
= res_to_bin_menuexitems (wrbfd
, off
, mi
->popup
);
1807 /* Convert an rcdata resource to binary. This is also used to convert
1808 other information which happens to be stored in rc_rcdata_item lists
1812 res_to_bin_rcdata (windres_bfd
*wrbfd
, rc_uint_type off
, const rc_rcdata_item
*items
)
1814 const rc_rcdata_item
*ri
;
1816 for (ri
= items
; ri
!= NULL
; ri
= ri
->next
)
1830 len
= ri
->u
.string
.length
;
1832 case RCDATA_WSTRING
:
1833 len
= ri
->u
.wstring
.length
* sizeof (unichar
);
1836 len
= ri
->u
.buffer
.length
;
1842 bfd_byte
*hp
= &h
[0];
1846 windres_put_16 (wrbfd
, hp
, ri
->u
.word
);
1849 windres_put_32 (wrbfd
, hp
, ri
->u
.dword
);
1852 hp
= (bfd_byte
*) ri
->u
.string
.s
;
1854 case RCDATA_WSTRING
:
1858 hp
= (bfd_byte
*) reswr_alloc (len
);
1859 for (i
= 0; i
< ri
->u
.wstring
.length
; i
++)
1860 windres_put_16 (wrbfd
, hp
+ i
* sizeof (unichar
), ri
->u
.wstring
.w
[i
]);
1864 hp
= (bfd_byte
*) ri
->u
.buffer
.data
;
1867 set_windres_bfd_content (wrbfd
, hp
, off
, len
);
1874 /* Convert a stringtable resource to binary. */
1877 res_to_bin_stringtable (windres_bfd
*wrbfd
, rc_uint_type off
,
1878 const rc_stringtable
*st
)
1882 for (i
= 0; i
< 16; i
++)
1884 rc_uint_type slen
, length
;
1887 slen
= (rc_uint_type
) st
->strings
[i
].length
;
1888 if (slen
== 0xffffffff) slen
= 0;
1889 s
= st
->strings
[i
].string
;
1891 length
= 2 + slen
* 2;
1897 hp
= (bfd_byte
*) reswr_alloc (length
);
1898 windres_put_16 (wrbfd
, hp
, slen
);
1900 for (j
= 0; j
< slen
; j
++)
1901 windres_put_16 (wrbfd
, hp
+ 2 + j
* 2, s
[j
]);
1902 set_windres_bfd_content (wrbfd
, hp
, off
, length
);
1909 /* Convert an ASCII string to a unicode binary string. This always
1910 returns exactly one bindata structure. */
1913 string_to_unicode_bin (windres_bfd
*wrbfd
, rc_uint_type off
, const char *s
)
1917 len
= (rc_uint_type
) strlen (s
);
1924 hp
= (bfd_byte
*) reswr_alloc ((len
+ 1) * sizeof (unichar
));
1926 for (i
= 0; i
< len
; i
++)
1927 windres_put_16 (wrbfd
, hp
+ i
* 2, s
[i
]);
1928 windres_put_16 (wrbfd
, hp
+ i
* 2, 0);
1929 set_windres_bfd_content (wrbfd
, hp
, off
, (len
+ 1) * sizeof (unichar
));
1931 off
+= (rc_uint_type
) ((len
+ 1) * sizeof (unichar
));
1936 res_to_bin_toolbar (windres_bfd
*wrbfd
, rc_uint_type off
, rc_toolbar
*tb
)
1940 struct bin_toolbar bt
;
1941 windres_put_32 (wrbfd
, bt
.button_width
, tb
->button_width
);
1942 windres_put_32 (wrbfd
, bt
.button_height
, tb
->button_height
);
1943 windres_put_32 (wrbfd
, bt
.nitems
, tb
->nitems
);
1944 set_windres_bfd_content (wrbfd
, &bt
, off
, BIN_TOOLBAR_SIZE
);
1947 rc_toolbar_item
*it
;
1951 ids
= (bfd_byte
*) reswr_alloc (tb
->nitems
* 4);
1955 windres_put_32 (wrbfd
, ids
+ i
, it
->id
.u
.id
);
1959 set_windres_bfd_content (wrbfd
, ids
, off
+ BIN_TOOLBAR_SIZE
, i
);
1962 off
+= BIN_TOOLBAR_SIZE
+ tb
->nitems
* 4;
1967 /* Convert a versioninfo resource to binary. */
1970 res_to_bin_versioninfo (windres_bfd
*wrbfd
, rc_uint_type off
,
1971 const rc_versioninfo
*versioninfo
)
1973 rc_uint_type off_delta
= off
;
1975 struct bin_versioninfo bvi
;
1979 off
+= BIN_VERSIONINFO_SIZE
;
1980 off
= string_to_unicode_bin (wrbfd
, off
, "VS_VERSION_INFO");
1981 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
1983 if (versioninfo
->fixed
!= NULL
)
1987 struct bin_fixed_versioninfo bfv
;
1988 const rc_fixed_versioninfo
*fi
;
1990 fi
= versioninfo
->fixed
;
1991 windres_put_32 (wrbfd
, bfv
.sig1
, 0xfeef04bd);
1992 windres_put_32 (wrbfd
, bfv
.sig2
, 0x10000);
1993 windres_put_32 (wrbfd
, bfv
.file_version
, fi
->file_version_ms
);
1994 windres_put_32 (wrbfd
, bfv
.file_version_ls
, fi
->file_version_ls
);
1995 windres_put_32 (wrbfd
, bfv
.product_version_ms
, fi
->product_version_ms
);
1996 windres_put_32 (wrbfd
, bfv
.product_version_ls
, fi
->product_version_ls
);
1997 windres_put_32 (wrbfd
, bfv
.file_flags_mask
, fi
->file_flags_mask
);
1998 windres_put_32 (wrbfd
, bfv
.file_flags
, fi
->file_flags
);
1999 windres_put_32 (wrbfd
, bfv
.file_os
, fi
->file_os
);
2000 windres_put_32 (wrbfd
, bfv
.file_type
, fi
->file_type
);
2001 windres_put_32 (wrbfd
, bfv
.file_subtype
, fi
->file_subtype
);
2002 windres_put_32 (wrbfd
, bfv
.file_date_ms
, fi
->file_date_ms
);
2003 windres_put_32 (wrbfd
, bfv
.file_date_ls
, fi
->file_date_ls
);
2004 set_windres_bfd_content (wrbfd
, &bfv
, off
, BIN_FIXED_VERSIONINFO_SIZE
);
2006 off
+= BIN_FIXED_VERSIONINFO_SIZE
;
2009 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
2011 struct bin_ver_info bv
;
2012 rc_uint_type bv_off
;
2014 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2018 off
+= BIN_VER_INFO_SIZE
;
2024 case VERINFO_STRING
:
2026 const rc_ver_stringtable
*vst
;
2028 off
= string_to_unicode_bin (wrbfd
, off
, "StringFileInfo");
2030 if (!vi
->u
.string
.stringtables
)
2031 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2033 for (vst
= vi
->u
.string
.stringtables
; vst
!= NULL
; vst
= vst
->next
)
2035 struct bin_ver_info bvst
;
2036 rc_uint_type vst_off
;
2037 const rc_ver_stringinfo
*vs
;
2039 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2042 off
+= BIN_VER_INFO_SIZE
;
2044 off
= unicode_to_bin (wrbfd
, off
, vst
->language
);
2046 for (vs
= vst
->strings
; vs
!= NULL
; vs
= vs
->next
)
2048 struct bin_ver_info bvs
;
2049 rc_uint_type vs_off
, str_off
;
2051 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2054 off
+= BIN_VER_INFO_SIZE
;
2056 off
= unicode_to_bin (wrbfd
, off
, vs
->key
);
2058 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2061 off
= unicode_to_bin (wrbfd
, off
, vs
->value
);
2065 windres_put_16 (wrbfd
, bvs
.size
, off
- vs_off
);
2066 windres_put_16 (wrbfd
, bvs
.sig1
, (off
- str_off
) / 2);
2067 windres_put_16 (wrbfd
, bvs
.sig2
, 1);
2068 set_windres_bfd_content (wrbfd
, &bvs
, vs_off
,
2075 windres_put_16 (wrbfd
, bvst
.size
, off
- vst_off
);
2076 windres_put_16 (wrbfd
, bvst
.sig1
, 0);
2077 windres_put_16 (wrbfd
, bvst
.sig2
, 1);
2078 set_windres_bfd_content (wrbfd
, &bvst
, vst_off
,
2087 rc_uint_type vvd_off
, vvvd_off
;
2088 struct bin_ver_info bvvd
;
2089 const rc_ver_varinfo
*vv
;
2091 off
= string_to_unicode_bin (wrbfd
, off
, "VarFileInfo");
2093 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2096 off
+= BIN_VER_INFO_SIZE
;
2098 off
= unicode_to_bin (wrbfd
, off
, vi
->u
.var
.key
);
2100 off
+= (4 - ((off
- off_delta
) & 3)) & 3;
2104 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
2110 windres_put_16 (wrbfd
, &vvsd
[0], vv
->language
);
2111 windres_put_16 (wrbfd
, &vvsd
[2], vv
->charset
);
2112 set_windres_bfd_content (wrbfd
, vvsd
, off
, 4);
2118 windres_put_16 (wrbfd
, bvvd
.size
, off
- vvd_off
);
2119 windres_put_16 (wrbfd
, bvvd
.sig1
, off
- vvvd_off
);
2120 windres_put_16 (wrbfd
, bvvd
.sig2
, 0);
2121 set_windres_bfd_content (wrbfd
, &bvvd
, vvd_off
,
2131 windres_put_16 (wrbfd
, bv
.size
, off
- bv_off
);
2132 windres_put_16 (wrbfd
, bv
.sig1
, 0);
2133 windres_put_16 (wrbfd
, bv
.sig2
, 1);
2134 set_windres_bfd_content (wrbfd
, &bv
, bv_off
,
2141 windres_put_16 (wrbfd
, bvi
.size
, off
- start
);
2142 windres_put_16 (wrbfd
, bvi
.fixed_size
,
2143 versioninfo
->fixed
== NULL
? 0
2144 : BIN_FIXED_VERSIONINFO_SIZE
);
2145 windres_put_16 (wrbfd
, bvi
.sig2
, 0);
2146 set_windres_bfd_content (wrbfd
, &bvi
, start
, BIN_VER_INFO_SIZE
);
2151 /* Convert a generic resource to binary. */
2154 res_to_bin_generic (windres_bfd
*wrbfd
, rc_uint_type off
, rc_uint_type length
,
2155 const bfd_byte
*data
)
2157 if (wrbfd
&& length
!= 0)
2158 set_windres_bfd_content (wrbfd
, data
, off
, length
);
2159 return off
+ (rc_uint_type
) length
;