merge from gcc
[binutils.git] / binutils / resbin.c
blobad14bdafcbbaea4e609178e7486fe7ae5b51bfc4
1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright 1997, 1998, 1999, 2002, 2003
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
6 This file is part of GNU Binutils.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
23 /* This file contains functions to convert between the binary resource
24 format and the internal structures that we want to use. The same
25 binary resource format is used in both res and COFF files. */
27 #include "bfd.h"
28 #include "bucomm.h"
29 #include "libiberty.h"
30 #include "windres.h"
32 /* Macros to swap in values. */
34 #define get_8(s) (*((unsigned char *)(s)))
35 #define get_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s))
36 #define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s))
38 /* Local functions. */
40 static void toosmall (const char *);
42 static unichar *get_unicode
43 (const unsigned char *, unsigned long, int, int *);
44 static int get_resid
45 (struct res_id *, const unsigned char *, unsigned long, int);
46 static struct res_resource *bin_to_res_generic
47 (enum res_type, const unsigned char *, unsigned long);
48 static struct res_resource *bin_to_res_cursor
49 (const unsigned char *, unsigned long, int);
50 static struct res_resource *bin_to_res_menu
51 (const unsigned char *, unsigned long, int);
52 static struct menuitem *bin_to_res_menuitems
53 (const unsigned char *, unsigned long, int, int *);
54 static struct menuitem *bin_to_res_menuexitems
55 (const unsigned char *, unsigned long, int, int *);
56 static struct res_resource *bin_to_res_dialog
57 (const unsigned char *, unsigned long, int);
58 static struct res_resource *bin_to_res_string
59 (const unsigned char *, unsigned long, int);
60 static struct res_resource *bin_to_res_fontdir
61 (const unsigned char *, unsigned long, int);
62 static struct res_resource *bin_to_res_accelerators
63 (const unsigned char *, unsigned long, int);
64 static struct res_resource *bin_to_res_rcdata
65 (const unsigned char *, unsigned long, int);
66 static struct res_resource *bin_to_res_group_cursor
67 (const unsigned char *, unsigned long, int);
68 static struct res_resource *bin_to_res_group_icon
69 (const unsigned char *, unsigned long, int);
70 static struct res_resource *bin_to_res_version
71 (const unsigned char *, unsigned long, int);
72 static struct res_resource *bin_to_res_userdata
73 (const unsigned char *, unsigned long, int);
74 static void get_version_header
75 (const unsigned char *, unsigned long, int, const char *,
76 unichar **, int *, int *, int *, int *);
78 /* Given a resource type ID, a pointer to data, a length, return a
79 res_resource structure which represents that resource. The caller
80 is responsible for initializing the res_info and coff_info fields
81 of the returned structure. */
83 struct res_resource *
84 bin_to_res (struct res_id type, const unsigned char *data,
85 unsigned long length, int big_endian)
87 if (type.named)
88 return bin_to_res_userdata (data, length, big_endian);
89 else
91 switch (type.u.id)
93 default:
94 return bin_to_res_userdata (data, length, big_endian);
95 case RT_CURSOR:
96 return bin_to_res_cursor (data, length, big_endian);
97 case RT_BITMAP:
98 return bin_to_res_generic (RES_TYPE_BITMAP, data, length);
99 case RT_ICON:
100 return bin_to_res_generic (RES_TYPE_ICON, data, length);
101 case RT_MENU:
102 return bin_to_res_menu (data, length, big_endian);
103 case RT_DIALOG:
104 return bin_to_res_dialog (data, length, big_endian);
105 case RT_STRING:
106 return bin_to_res_string (data, length, big_endian);
107 case RT_FONTDIR:
108 return bin_to_res_fontdir (data, length, big_endian);
109 case RT_FONT:
110 return bin_to_res_generic (RES_TYPE_FONT, data, length);
111 case RT_ACCELERATOR:
112 return bin_to_res_accelerators (data, length, big_endian);
113 case RT_RCDATA:
114 return bin_to_res_rcdata (data, length, big_endian);
115 case RT_MESSAGETABLE:
116 return bin_to_res_generic (RES_TYPE_MESSAGETABLE, data, length);
117 case RT_GROUP_CURSOR:
118 return bin_to_res_group_cursor (data, length, big_endian);
119 case RT_GROUP_ICON:
120 return bin_to_res_group_icon (data, length, big_endian);
121 case RT_VERSION:
122 return bin_to_res_version (data, length, big_endian);
127 /* Give an error if the binary data is too small. */
129 static void
130 toosmall (const char *msg)
132 fatal (_("%s: not enough binary data"), msg);
135 /* Swap in a NULL terminated unicode string. */
137 static unichar *
138 get_unicode (const unsigned char *data, unsigned long length,
139 int big_endian, int *retlen)
141 int c, i;
142 unichar *ret;
144 c = 0;
145 while (1)
147 if (length < (unsigned long) c * 2 + 2)
148 toosmall (_("null terminated unicode string"));
149 if (get_16 (big_endian, data + c * 2) == 0)
150 break;
151 ++c;
154 ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
156 for (i = 0; i < c; i++)
157 ret[i] = get_16 (big_endian, data + i * 2);
158 ret[i] = 0;
160 if (retlen != NULL)
161 *retlen = c;
163 return ret;
166 /* Get a resource identifier. This returns the number of bytes used. */
168 static int
169 get_resid (struct res_id *id, const unsigned char *data,
170 unsigned long length, int big_endian)
172 int first;
174 if (length < 2)
175 toosmall (_("resource ID"));
177 first = get_16 (big_endian, data);
178 if (first == 0xffff)
180 if (length < 4)
181 toosmall (_("resource ID"));
182 id->named = 0;
183 id->u.id = get_16 (big_endian, data + 2);
184 return 4;
186 else
188 id->named = 1;
189 id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length);
190 return id->u.n.length * 2 + 2;
194 /* Convert a resource which just stores uninterpreted data from
195 binary. */
197 struct res_resource *
198 bin_to_res_generic (enum res_type type, const unsigned char *data,
199 unsigned long length)
201 struct res_resource *r;
203 r = (struct res_resource *) res_alloc (sizeof *r);
204 r->type = type;
205 r->u.data.data = data;
206 r->u.data.length = length;
208 return r;
211 /* Convert a cursor resource from binary. */
213 struct res_resource *
214 bin_to_res_cursor (const unsigned char *data, unsigned long length,
215 int big_endian)
217 struct cursor *c;
218 struct res_resource *r;
220 if (length < 4)
221 toosmall (_("cursor"));
223 c = (struct cursor *) res_alloc (sizeof *c);
224 c->xhotspot = get_16 (big_endian, data);
225 c->yhotspot = get_16 (big_endian, data + 2);
226 c->length = length - 4;
227 c->data = data + 4;
229 r = (struct res_resource *) res_alloc (sizeof *r);
230 r->type = RES_TYPE_CURSOR;
231 r->u.cursor = c;
233 return r;
236 /* Convert a menu resource from binary. */
238 struct res_resource *
239 bin_to_res_menu (const unsigned char *data, unsigned long length,
240 int big_endian)
242 struct res_resource *r;
243 struct menu *m;
244 int version, read;
246 r = (struct res_resource *) res_alloc (sizeof *r);
247 r->type = RES_TYPE_MENU;
249 m = (struct menu *) res_alloc (sizeof *m);
250 r->u.menu = m;
252 if (length < 2)
253 toosmall (_("menu header"));
255 version = get_16 (big_endian, data);
257 if (version == 0)
259 if (length < 4)
260 toosmall (_("menu header"));
261 m->help = 0;
262 m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian,
263 &read);
265 else if (version == 1)
267 unsigned int offset;
269 if (length < 8)
270 toosmall (_("menuex header"));
271 m->help = get_32 (big_endian, data + 4);
272 offset = get_16 (big_endian, data + 2);
273 if (offset + 4 >= length)
274 toosmall (_("menuex offset"));
275 m->items = bin_to_res_menuexitems (data + 4 + offset,
276 length - (4 + offset),
277 big_endian,
278 &read);
280 else
281 fatal (_("unsupported menu version %d"), version);
283 return r;
286 /* Convert menu items from binary. */
288 static struct menuitem *
289 bin_to_res_menuitems (const unsigned char *data, unsigned long length,
290 int big_endian, int *read)
292 struct menuitem *first, **pp;
294 first = NULL;
295 pp = &first;
297 *read = 0;
299 while (length > 0)
301 int flags, slen, itemlen;
302 unsigned int stroff;
303 struct menuitem *mi;
305 if (length < 4)
306 toosmall (_("menuitem header"));
308 mi = (struct menuitem *) res_alloc (sizeof *mi);
309 mi->state = 0;
310 mi->help = 0;
312 flags = get_16 (big_endian, data);
313 mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
315 if ((flags & MENUITEM_POPUP) == 0)
316 stroff = 4;
317 else
318 stroff = 2;
320 if (length < stroff + 2)
321 toosmall (_("menuitem header"));
323 if (get_16 (big_endian, data + stroff) == 0)
325 slen = 0;
326 mi->text = NULL;
328 else
329 mi->text = get_unicode (data + stroff, length - stroff, big_endian,
330 &slen);
332 itemlen = stroff + slen * 2 + 2;
334 if ((flags & MENUITEM_POPUP) == 0)
336 mi->popup = NULL;
337 mi->id = get_16 (big_endian, data + 2);
339 else
341 int subread;
343 mi->id = 0;
344 mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen,
345 big_endian, &subread);
346 itemlen += subread;
349 mi->next = NULL;
350 *pp = mi;
351 pp = &mi->next;
353 data += itemlen;
354 length -= itemlen;
355 *read += itemlen;
357 if ((flags & MENUITEM_ENDMENU) != 0)
358 return first;
361 return first;
364 /* Convert menuex items from binary. */
366 static struct menuitem *
367 bin_to_res_menuexitems (const unsigned char *data, unsigned long length,
368 int big_endian, int *read)
370 struct menuitem *first, **pp;
372 first = NULL;
373 pp = &first;
375 *read = 0;
377 while (length > 0)
379 int flags, slen;
380 unsigned int itemlen;
381 struct menuitem *mi;
383 if (length < 14)
384 toosmall (_("menuitem header"));
386 mi = (struct menuitem *) res_alloc (sizeof *mi);
387 mi->type = get_32 (big_endian, data);
388 mi->state = get_32 (big_endian, data + 4);
389 mi->id = get_16 (big_endian, data + 8);
391 flags = get_16 (big_endian, data + 10);
393 if (get_16 (big_endian, data + 12) == 0)
395 slen = 0;
396 mi->text = NULL;
398 else
399 mi->text = get_unicode (data + 12, length - 12, big_endian, &slen);
401 itemlen = 12 + slen * 2 + 2;
402 itemlen = (itemlen + 3) &~ 3;
404 if ((flags & 1) == 0)
406 mi->popup = NULL;
407 mi->help = 0;
409 else
411 int subread;
413 if (length < itemlen + 4)
414 toosmall (_("menuitem"));
415 mi->help = get_32 (big_endian, data + itemlen);
416 itemlen += 4;
418 mi->popup = bin_to_res_menuexitems (data + itemlen,
419 length - itemlen,
420 big_endian, &subread);
421 itemlen += subread;
424 mi->next = NULL;
425 *pp = mi;
426 pp = &mi->next;
428 data += itemlen;
429 length -= itemlen;
430 *read += itemlen;
432 if ((flags & 0x80) != 0)
433 return first;
436 return first;
439 /* Convert a dialog resource from binary. */
441 static struct res_resource *
442 bin_to_res_dialog (const unsigned char *data, unsigned long length,
443 int big_endian)
445 int signature;
446 struct dialog *d;
447 int c, sublen, i;
448 unsigned int off;
449 struct dialog_control **pp;
450 struct res_resource *r;
452 if (length < 18)
453 toosmall (_("dialog header"));
455 d = (struct dialog *) res_alloc (sizeof *d);
457 signature = get_16 (big_endian, data + 2);
458 if (signature != 0xffff)
460 d->ex = NULL;
461 d->style = get_32 (big_endian, data);
462 d->exstyle = get_32 (big_endian, data + 4);
463 off = 8;
465 else
467 int version;
469 version = get_16 (big_endian, data);
470 if (version != 1)
471 fatal (_("unexpected DIALOGEX version %d"), version);
473 d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex));
474 d->ex->help = get_32 (big_endian, data + 4);
475 d->exstyle = get_32 (big_endian, data + 8);
476 d->style = get_32 (big_endian, data + 12);
477 off = 16;
480 if (length < off + 10)
481 toosmall (_("dialog header"));
483 c = get_16 (big_endian, data + off);
484 d->x = get_16 (big_endian, data + off + 2);
485 d->y = get_16 (big_endian, data + off + 4);
486 d->width = get_16 (big_endian, data + off + 6);
487 d->height = get_16 (big_endian, data + off + 8);
489 off += 10;
491 sublen = get_resid (&d->menu, data + off, length - off, big_endian);
492 off += sublen;
494 sublen = get_resid (&d->class, data + off, length - off, big_endian);
495 off += sublen;
497 d->caption = get_unicode (data + off, length - off, big_endian, &sublen);
498 off += sublen * 2 + 2;
499 if (sublen == 0)
500 d->caption = NULL;
502 if ((d->style & DS_SETFONT) == 0)
504 d->pointsize = 0;
505 d->font = NULL;
506 if (d->ex != NULL)
508 d->ex->weight = 0;
509 d->ex->italic = 0;
510 d->ex->charset = 1; /* Default charset. */
513 else
515 if (length < off + 2)
516 toosmall (_("dialog font point size"));
518 d->pointsize = get_16 (big_endian, data + off);
519 off += 2;
521 if (d->ex != NULL)
523 if (length < off + 4)
524 toosmall (_("dialogex font information"));
525 d->ex->weight = get_16 (big_endian, data + off);
526 d->ex->italic = get_8 (data + off + 2);
527 d->ex->charset = get_8 (data + off + 3);
528 off += 4;
531 d->font = get_unicode (data + off, length - off, big_endian, &sublen);
532 off += sublen * 2 + 2;
535 d->controls = NULL;
536 pp = &d->controls;
538 for (i = 0; i < c; i++)
540 struct dialog_control *dc;
541 int datalen;
543 off = (off + 3) &~ 3;
545 dc = (struct dialog_control *) res_alloc (sizeof *dc);
547 if (d->ex == NULL)
549 if (length < off + 8)
550 toosmall (_("dialog control"));
552 dc->style = get_32 (big_endian, data + off);
553 dc->exstyle = get_32 (big_endian, data + off + 4);
554 dc->help = 0;
555 off += 8;
557 else
559 if (length < off + 12)
560 toosmall (_("dialogex control"));
561 dc->help = get_32 (big_endian, data + off);
562 dc->exstyle = get_32 (big_endian, data + off + 4);
563 dc->style = get_32 (big_endian, data + off + 8);
564 off += 12;
567 if (length < off + 10)
568 toosmall (_("dialog control"));
570 dc->x = get_16 (big_endian, data + off);
571 dc->y = get_16 (big_endian, data + off + 2);
572 dc->width = get_16 (big_endian, data + off + 4);
573 dc->height = get_16 (big_endian, data + off + 6);
575 if (d->ex != NULL)
576 dc->id = get_32 (big_endian, data + off + 8);
577 else
578 dc->id = get_16 (big_endian, data + off + 8);
580 off += 10 + (d->ex != NULL ? 2 : 0);
582 sublen = get_resid (&dc->class, data + off, length - off, big_endian);
583 off += sublen;
585 sublen = get_resid (&dc->text, data + off, length - off, big_endian);
586 off += sublen;
588 if (length < off + 2)
589 toosmall (_("dialog control end"));
591 datalen = get_16 (big_endian, data + off);
592 off += 2;
594 if (datalen == 0)
595 dc->data = NULL;
596 else
598 off = (off + 3) &~ 3;
600 if (length < off + datalen)
601 toosmall (_("dialog control data"));
603 dc->data = ((struct rcdata_item *)
604 res_alloc (sizeof (struct rcdata_item)));
605 dc->data->next = NULL;
606 dc->data->type = RCDATA_BUFFER;
607 dc->data->u.buffer.length = datalen;
608 dc->data->u.buffer.data = data + off;
610 off += datalen;
613 dc->next = NULL;
614 *pp = dc;
615 pp = &dc->next;
618 r = (struct res_resource *) res_alloc (sizeof *r);
619 r->type = RES_TYPE_DIALOG;
620 r->u.dialog = d;
622 return r;
625 /* Convert a stringtable resource from binary. */
627 static struct res_resource *
628 bin_to_res_string (const unsigned char *data, unsigned long length,
629 int big_endian)
631 struct stringtable *st;
632 int i;
633 struct res_resource *r;
635 st = (struct stringtable *) res_alloc (sizeof *st);
637 for (i = 0; i < 16; i++)
639 unsigned int slen;
641 if (length < 2)
642 toosmall (_("stringtable string length"));
643 slen = get_16 (big_endian, data);
644 st->strings[i].length = slen;
646 if (slen > 0)
648 unichar *s;
649 unsigned int j;
651 if (length < 2 + 2 * slen)
652 toosmall (_("stringtable string"));
654 s = (unichar *) res_alloc (slen * sizeof (unichar));
655 st->strings[i].string = s;
657 for (j = 0; j < slen; j++)
658 s[j] = get_16 (big_endian, data + 2 + j * 2);
661 data += 2 + 2 * slen;
662 length -= 2 + 2 * slen;
665 r = (struct res_resource *) res_alloc (sizeof *r);
666 r->type = RES_TYPE_STRINGTABLE;
667 r->u.stringtable = st;
669 return r;
672 /* Convert a fontdir resource from binary. */
674 static struct res_resource *
675 bin_to_res_fontdir (const unsigned char *data, unsigned long length,
676 int big_endian)
678 int c, i;
679 struct fontdir *first, **pp;
680 struct res_resource *r;
682 if (length < 2)
683 toosmall (_("fontdir header"));
685 c = get_16 (big_endian, data);
687 first = NULL;
688 pp = &first;
690 for (i = 0; i < c; i++)
692 struct fontdir *fd;
693 unsigned int off;
695 if (length < 56)
696 toosmall (_("fontdir"));
698 fd = (struct fontdir *) res_alloc (sizeof *fd);
699 fd->index = get_16 (big_endian, data);
701 /* To work out the length of the fontdir data, we must get the
702 length of the device name and face name strings, even though
703 we don't store them in the fontdir structure. The
704 documentation says that these are NULL terminated char
705 strings, not Unicode strings. */
707 off = 56;
709 while (off < length && data[off] != '\0')
710 ++off;
711 if (off >= length)
712 toosmall (_("fontdir device name"));
713 ++off;
715 while (off < length && data[off] != '\0')
716 ++off;
717 if (off >= length)
718 toosmall (_("fontdir face name"));
719 ++off;
721 fd->length = off;
722 fd->data = data;
724 fd->next = NULL;
725 *pp = fd;
726 pp = &fd->next;
728 /* The documentation does not indicate that any rounding is
729 required. */
731 data += off;
732 length -= off;
735 r = (struct res_resource *) res_alloc (sizeof *r);
736 r->type = RES_TYPE_FONTDIR;
737 r->u.fontdir = first;
739 return r;
742 /* Convert an accelerators resource from binary. */
744 static struct res_resource *
745 bin_to_res_accelerators (const unsigned char *data, unsigned long length,
746 int big_endian)
748 struct accelerator *first, **pp;
749 struct res_resource *r;
751 first = NULL;
752 pp = &first;
754 while (1)
756 struct accelerator *a;
758 if (length < 8)
759 toosmall (_("accelerator"));
761 a = (struct accelerator *) res_alloc (sizeof *a);
763 a->flags = get_16 (big_endian, data);
764 a->key = get_16 (big_endian, data + 2);
765 a->id = get_16 (big_endian, data + 4);
767 a->next = NULL;
768 *pp = a;
769 pp = &a->next;
771 if ((a->flags & ACC_LAST) != 0)
772 break;
774 data += 8;
775 length -= 8;
778 r = (struct res_resource *) res_alloc (sizeof *r);
779 r->type = RES_TYPE_ACCELERATOR;
780 r->u.acc = first;
782 return r;
785 /* Convert an rcdata resource from binary. */
787 static struct res_resource *
788 bin_to_res_rcdata (const unsigned char *data, unsigned long length,
789 int big_endian ATTRIBUTE_UNUSED)
791 struct rcdata_item *ri;
792 struct res_resource *r;
794 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
796 ri->next = NULL;
797 ri->type = RCDATA_BUFFER;
798 ri->u.buffer.length = length;
799 ri->u.buffer.data = data;
801 r = (struct res_resource *) res_alloc (sizeof *r);
802 r->type = RES_TYPE_RCDATA;
803 r->u.rcdata = ri;
805 return r;
808 /* Convert a group cursor resource from binary. */
810 static struct res_resource *
811 bin_to_res_group_cursor (const unsigned char *data, unsigned long length,
812 int big_endian)
814 int type, c, i;
815 struct group_cursor *first, **pp;
816 struct res_resource *r;
818 if (length < 6)
819 toosmall (_("group cursor header"));
821 type = get_16 (big_endian, data + 2);
822 if (type != 2)
823 fatal (_("unexpected group cursor type %d"), type);
825 c = get_16 (big_endian, data + 4);
827 data += 6;
828 length -= 6;
830 first = NULL;
831 pp = &first;
833 for (i = 0; i < c; i++)
835 struct group_cursor *gc;
837 if (length < 14)
838 toosmall (_("group cursor"));
840 gc = (struct group_cursor *) res_alloc (sizeof *gc);
842 gc->width = get_16 (big_endian, data);
843 gc->height = get_16 (big_endian, data + 2);
844 gc->planes = get_16 (big_endian, data + 4);
845 gc->bits = get_16 (big_endian, data + 6);
846 gc->bytes = get_32 (big_endian, data + 8);
847 gc->index = get_16 (big_endian, data + 12);
849 gc->next = NULL;
850 *pp = gc;
851 pp = &gc->next;
853 data += 14;
854 length -= 14;
857 r = (struct res_resource *) res_alloc (sizeof *r);
858 r->type = RES_TYPE_GROUP_CURSOR;
859 r->u.group_cursor = first;
861 return r;
864 /* Convert a group icon resource from binary. */
866 static struct res_resource *
867 bin_to_res_group_icon (const unsigned char *data, unsigned long length,
868 int big_endian)
870 int type, c, i;
871 struct group_icon *first, **pp;
872 struct res_resource *r;
874 if (length < 6)
875 toosmall (_("group icon header"));
877 type = get_16 (big_endian, data + 2);
878 if (type != 1)
879 fatal (_("unexpected group icon type %d"), type);
881 c = get_16 (big_endian, data + 4);
883 data += 6;
884 length -= 6;
886 first = NULL;
887 pp = &first;
889 for (i = 0; i < c; i++)
891 struct group_icon *gi;
893 if (length < 14)
894 toosmall (_("group icon"));
896 gi = (struct group_icon *) res_alloc (sizeof *gi);
898 gi->width = data[0];
899 gi->height = data[1];
900 gi->colors = data[2];
901 gi->planes = get_16 (big_endian, data + 4);
902 gi->bits = get_16 (big_endian, data + 6);
903 gi->bytes = get_32 (big_endian, data + 8);
904 gi->index = get_16 (big_endian, data + 12);
906 gi->next = NULL;
907 *pp = gi;
908 pp = &gi->next;
910 data += 14;
911 length -= 14;
914 r = (struct res_resource *) res_alloc (sizeof *r);
915 r->type = RES_TYPE_GROUP_ICON;
916 r->u.group_icon = first;
918 return r;
921 /* Extract data from a version header. If KEY is not NULL, then the
922 key must be KEY; otherwise, the key is returned in *PKEY. This
923 sets *LEN to the total length, *VALLEN to the value length, *TYPE
924 to the type, and *OFF to the offset to the children. */
926 static void
927 get_version_header (const unsigned char *data, unsigned long length,
928 int big_endian, const char *key, unichar **pkey,
929 int *len, int *vallen, int *type, int *off)
931 if (length < 8)
932 toosmall (key);
934 *len = get_16 (big_endian, data);
935 *vallen = get_16 (big_endian, data + 2);
936 *type = get_16 (big_endian, data + 4);
938 *off = 6;
940 length -= 6;
941 data += 6;
943 if (key == NULL)
945 int sublen;
947 *pkey = get_unicode (data, length, big_endian, &sublen);
948 *off += sublen * 2 + 2;
950 else
952 while (1)
954 if (length < 2)
955 toosmall (key);
956 if (get_16 (big_endian, data) != (unsigned char) *key)
957 fatal (_("unexpected version string"));
959 *off += 2;
960 length -= 2;
961 data += 2;
963 if (*key == '\0')
964 break;
966 ++key;
970 *off = (*off + 3) &~ 3;
973 /* Convert a version resource from binary. */
975 static struct res_resource *
976 bin_to_res_version (const unsigned char *data, unsigned long length,
977 int big_endian)
979 int verlen, vallen, type, off;
980 struct fixed_versioninfo *fi;
981 struct ver_info *first, **pp;
982 struct versioninfo *v;
983 struct res_resource *r;
985 get_version_header (data, length, big_endian, "VS_VERSION_INFO",
986 (unichar **) NULL, &verlen, &vallen, &type, &off);
988 if ((unsigned int) verlen != length)
989 fatal (_("version length %d does not match resource length %lu"),
990 verlen, length);
992 if (type != 0)
993 fatal (_("unexpected version type %d"), type);
995 data += off;
996 length -= off;
998 if (vallen == 0)
999 fi = NULL;
1000 else
1002 unsigned long signature, fiv;
1004 if (vallen != 52)
1005 fatal (_("unexpected fixed version information length %d"), vallen);
1007 if (length < 52)
1008 toosmall (_("fixed version info"));
1010 signature = get_32 (big_endian, data);
1011 if (signature != 0xfeef04bd)
1012 fatal (_("unexpected fixed version signature %lu"), signature);
1014 fiv = get_32 (big_endian, data + 4);
1015 if (fiv != 0 && fiv != 0x10000)
1016 fatal (_("unexpected fixed version info version %lu"), fiv);
1018 fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi);
1020 fi->file_version_ms = get_32 (big_endian, data + 8);
1021 fi->file_version_ls = get_32 (big_endian, data + 12);
1022 fi->product_version_ms = get_32 (big_endian, data + 16);
1023 fi->product_version_ls = get_32 (big_endian, data + 20);
1024 fi->file_flags_mask = get_32 (big_endian, data + 24);
1025 fi->file_flags = get_32 (big_endian, data + 28);
1026 fi->file_os = get_32 (big_endian, data + 32);
1027 fi->file_type = get_32 (big_endian, data + 36);
1028 fi->file_subtype = get_32 (big_endian, data + 40);
1029 fi->file_date_ms = get_32 (big_endian, data + 44);
1030 fi->file_date_ls = get_32 (big_endian, data + 48);
1032 data += 52;
1033 length -= 52;
1036 first = NULL;
1037 pp = &first;
1039 while (length > 0)
1041 struct ver_info *vi;
1042 int ch;
1044 if (length < 8)
1045 toosmall (_("version var info"));
1047 vi = (struct ver_info *) res_alloc (sizeof *vi);
1049 ch = get_16 (big_endian, data + 6);
1051 if (ch == 'S')
1053 struct ver_stringinfo **ppvs;
1055 vi->type = VERINFO_STRING;
1057 get_version_header (data, length, big_endian, "StringFileInfo",
1058 (unichar **) NULL, &verlen, &vallen, &type,
1059 &off);
1061 if (vallen != 0)
1062 fatal (_("unexpected stringfileinfo value length %d"), vallen);
1064 data += off;
1065 length -= off;
1067 get_version_header (data, length, big_endian, (const char *) NULL,
1068 &vi->u.string.language, &verlen, &vallen,
1069 &type, &off);
1071 if (vallen != 0)
1072 fatal (_("unexpected version stringtable value length %d"), vallen);
1074 data += off;
1075 length -= off;
1076 verlen -= off;
1078 vi->u.string.strings = NULL;
1079 ppvs = &vi->u.string.strings;
1081 /* It's convenient to round verlen to a 4 byte alignment,
1082 since we round the subvariables in the loop. */
1083 verlen = (verlen + 3) &~ 3;
1085 while (verlen > 0)
1087 struct ver_stringinfo *vs;
1088 int subverlen, vslen, valoff;
1090 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1092 get_version_header (data, length, big_endian,
1093 (const char *) NULL, &vs->key, &subverlen,
1094 &vallen, &type, &off);
1096 subverlen = (subverlen + 3) &~ 3;
1098 data += off;
1099 length -= off;
1101 vs->value = get_unicode (data, length, big_endian, &vslen);
1102 valoff = vslen * 2 + 2;
1103 valoff = (valoff + 3) &~ 3;
1105 if (off + valoff != subverlen)
1106 fatal (_("unexpected version string length %d != %d + %d"),
1107 subverlen, off, valoff);
1109 vs->next = NULL;
1110 *ppvs = vs;
1111 ppvs = &vs->next;
1113 data += valoff;
1114 length -= valoff;
1116 if (verlen < subverlen)
1117 fatal (_("unexpected version string length %d < %d"),
1118 verlen, subverlen);
1120 verlen -= subverlen;
1123 else if (ch == 'V')
1125 struct ver_varinfo **ppvv;
1127 vi->type = VERINFO_VAR;
1129 get_version_header (data, length, big_endian, "VarFileInfo",
1130 (unichar **) NULL, &verlen, &vallen, &type,
1131 &off);
1133 if (vallen != 0)
1134 fatal (_("unexpected varfileinfo value length %d"), vallen);
1136 data += off;
1137 length -= off;
1139 get_version_header (data, length, big_endian, (const char *) NULL,
1140 &vi->u.var.key, &verlen, &vallen, &type, &off);
1142 data += off;
1143 length -= off;
1145 vi->u.var.var = NULL;
1146 ppvv = &vi->u.var.var;
1148 while (vallen > 0)
1150 struct ver_varinfo *vv;
1152 if (length < 4)
1153 toosmall (_("version varfileinfo"));
1155 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1157 vv->language = get_16 (big_endian, data);
1158 vv->charset = get_16 (big_endian, data + 2);
1160 vv->next = NULL;
1161 *ppvv = vv;
1162 ppvv = &vv->next;
1164 data += 4;
1165 length -= 4;
1167 if (vallen < 4)
1168 fatal (_("unexpected version value length %d"), vallen);
1170 vallen -= 4;
1173 else
1174 fatal (_("unexpected version string"));
1176 vi->next = NULL;
1177 *pp = vi;
1178 pp = &vi->next;
1181 v = (struct versioninfo *) res_alloc (sizeof *v);
1182 v->fixed = fi;
1183 v->var = first;
1185 r = (struct res_resource *) res_alloc (sizeof *r);
1186 r->type = RES_TYPE_VERSIONINFO;
1187 r->u.versioninfo = v;
1189 return r;
1192 /* Convert an arbitrary user defined resource from binary. */
1194 static struct res_resource *
1195 bin_to_res_userdata (const unsigned char *data, unsigned long length,
1196 int big_endian ATTRIBUTE_UNUSED)
1198 struct rcdata_item *ri;
1199 struct res_resource *r;
1201 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1203 ri->next = NULL;
1204 ri->type = RCDATA_BUFFER;
1205 ri->u.buffer.length = length;
1206 ri->u.buffer.data = data;
1208 r = (struct res_resource *) res_alloc (sizeof *r);
1209 r->type = RES_TYPE_USERDATA;
1210 r->u.rcdata = ri;
1212 return r;
1215 /* Macros to swap out values. */
1217 #define put_8(v, s) (*((unsigned char *) (s)) = (unsigned char) (v))
1218 #define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
1219 #define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
1221 /* Local functions used to convert resources to binary format. */
1223 static void dword_align_bin (struct bindata ***, unsigned long *);
1224 static struct bindata *resid_to_bin (struct res_id, int);
1225 static struct bindata *unicode_to_bin (const unichar *, int);
1226 static struct bindata *res_to_bin_accelerator
1227 (const struct accelerator *, int);
1228 static struct bindata *res_to_bin_cursor
1229 (const struct cursor *, int);
1230 static struct bindata *res_to_bin_group_cursor
1231 (const struct group_cursor *, int);
1232 static struct bindata *res_to_bin_dialog
1233 (const struct dialog *, int);
1234 static struct bindata *res_to_bin_fontdir
1235 (const struct fontdir *, int);
1236 static struct bindata *res_to_bin_group_icon
1237 (const struct group_icon *, int);
1238 static struct bindata *res_to_bin_menu
1239 (const struct menu *, int);
1240 static struct bindata *res_to_bin_menuitems
1241 (const struct menuitem *, int);
1242 static struct bindata *res_to_bin_menuexitems
1243 (const struct menuitem *, int);
1244 static struct bindata *res_to_bin_rcdata
1245 (const struct rcdata_item *, int);
1246 static struct bindata *res_to_bin_stringtable
1247 (const struct stringtable *, int);
1248 static struct bindata *string_to_unicode_bin (const char *, int);
1249 static struct bindata *res_to_bin_versioninfo
1250 (const struct versioninfo *, int);
1251 static struct bindata *res_to_bin_generic
1252 (unsigned long, const unsigned char *);
1254 /* Convert a resource to binary. */
1256 struct bindata *
1257 res_to_bin (const struct res_resource *res, int big_endian)
1259 switch (res->type)
1261 default:
1262 abort ();
1263 case RES_TYPE_BITMAP:
1264 case RES_TYPE_FONT:
1265 case RES_TYPE_ICON:
1266 case RES_TYPE_MESSAGETABLE:
1267 return res_to_bin_generic (res->u.data.length, res->u.data.data);
1268 case RES_TYPE_ACCELERATOR:
1269 return res_to_bin_accelerator (res->u.acc, big_endian);
1270 case RES_TYPE_CURSOR:
1271 return res_to_bin_cursor (res->u.cursor, big_endian);
1272 case RES_TYPE_GROUP_CURSOR:
1273 return res_to_bin_group_cursor (res->u.group_cursor, big_endian);
1274 case RES_TYPE_DIALOG:
1275 return res_to_bin_dialog (res->u.dialog, big_endian);
1276 case RES_TYPE_FONTDIR:
1277 return res_to_bin_fontdir (res->u.fontdir, big_endian);
1278 case RES_TYPE_GROUP_ICON:
1279 return res_to_bin_group_icon (res->u.group_icon, big_endian);
1280 case RES_TYPE_MENU:
1281 return res_to_bin_menu (res->u.menu, big_endian);
1282 case RES_TYPE_RCDATA:
1283 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1284 case RES_TYPE_STRINGTABLE:
1285 return res_to_bin_stringtable (res->u.stringtable, big_endian);
1286 case RES_TYPE_USERDATA:
1287 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1288 case RES_TYPE_VERSIONINFO:
1289 return res_to_bin_versioninfo (res->u.versioninfo, big_endian);
1293 /* Align to a 32 bit boundary. PPP points to the of a list of bindata
1294 structures. LENGTH points to the length of the structures. If
1295 necessary, this adds a new bindata to bring length up to a 32 bit
1296 boundary. It updates *PPP and *LENGTH. */
1298 static void
1299 dword_align_bin (struct bindata ***ppp, unsigned long *length)
1301 int add;
1302 struct bindata *d;
1304 if ((*length & 3) == 0)
1305 return;
1307 add = 4 - (*length & 3);
1309 d = (struct bindata *) reswr_alloc (sizeof *d);
1310 d->length = add;
1311 d->data = (unsigned char *) reswr_alloc (add);
1312 memset (d->data, 0, add);
1314 d->next = NULL;
1315 **ppp = d;
1316 *ppp = &(**ppp)->next;
1318 *length += add;
1321 /* Convert a resource ID to binary. This always returns exactly one
1322 bindata structure. */
1324 static struct bindata *
1325 resid_to_bin (struct res_id id, int big_endian)
1327 struct bindata *d;
1329 d = (struct bindata *) reswr_alloc (sizeof *d);
1331 if (! id.named)
1333 d->length = 4;
1334 d->data = (unsigned char *) reswr_alloc (4);
1335 put_16 (big_endian, 0xffff, d->data);
1336 put_16 (big_endian, id.u.id, d->data + 2);
1338 else
1340 int i;
1342 d->length = id.u.n.length * 2 + 2;
1343 d->data = (unsigned char *) reswr_alloc (d->length);
1344 for (i = 0; i < id.u.n.length; i++)
1345 put_16 (big_endian, id.u.n.name[i], d->data + i * 2);
1346 put_16 (big_endian, 0, d->data + i * 2);
1349 d->next = NULL;
1351 return d;
1354 /* Convert a null terminated unicode string to binary. This always
1355 returns exactly one bindata structure. */
1357 static struct bindata *
1358 unicode_to_bin (const unichar *str, int big_endian)
1360 int len;
1361 struct bindata *d;
1363 len = 0;
1364 if (str != NULL)
1366 const unichar *s;
1368 for (s = str; *s != 0; s++)
1369 ++len;
1372 d = (struct bindata *) reswr_alloc (sizeof *d);
1373 d->length = len * 2 + 2;
1374 d->data = (unsigned char *) reswr_alloc (d->length);
1376 if (str == NULL)
1377 put_16 (big_endian, 0, d->data);
1378 else
1380 const unichar *s;
1381 int i;
1383 for (s = str, i = 0; *s != 0; s++, i++)
1384 put_16 (big_endian, *s, d->data + i * 2);
1385 put_16 (big_endian, 0, d->data + i * 2);
1388 d->next = NULL;
1390 return d;
1393 /* Convert an accelerator resource to binary. */
1395 static struct bindata *
1396 res_to_bin_accelerator (const struct accelerator *accelerators,
1397 int big_endian)
1399 struct bindata *first, **pp;
1400 const struct accelerator *a;
1402 first = NULL;
1403 pp = &first;
1405 for (a = accelerators; a != NULL; a = a->next)
1407 struct bindata *d;
1409 d = (struct bindata *) reswr_alloc (sizeof *d);
1410 d->length = 8;
1411 d->data = (unsigned char *) reswr_alloc (8);
1413 put_16 (big_endian,
1414 a->flags | (a->next != NULL ? 0 : ACC_LAST),
1415 d->data);
1416 put_16 (big_endian, a->key, d->data + 2);
1417 put_16 (big_endian, a->id, d->data + 4);
1418 put_16 (big_endian, 0, d->data + 8);
1420 d->next = NULL;
1421 *pp = d;
1422 pp = &d->next;
1425 return first;
1428 /* Convert a cursor resource to binary. */
1430 static struct bindata *
1431 res_to_bin_cursor (const struct cursor *c, int big_endian)
1433 struct bindata *d;
1435 d = (struct bindata *) reswr_alloc (sizeof *d);
1436 d->length = 4;
1437 d->data = (unsigned char *) reswr_alloc (4);
1439 put_16 (big_endian, c->xhotspot, d->data);
1440 put_16 (big_endian, c->yhotspot, d->data + 2);
1442 d->next = (struct bindata *) reswr_alloc (sizeof *d);
1443 d->next->length = c->length;
1444 d->next->data = (unsigned char *) c->data;
1445 d->next->next = NULL;
1447 return d;
1450 /* Convert a group cursor resource to binary. */
1452 static struct bindata *
1453 res_to_bin_group_cursor (const struct group_cursor *group_cursors,
1454 int big_endian)
1456 struct bindata *first, **pp;
1457 int c;
1458 const struct group_cursor *gc;
1460 first = (struct bindata *) reswr_alloc (sizeof *first);
1461 first->length = 6;
1462 first->data = (unsigned char *) reswr_alloc (6);
1464 put_16 (big_endian, 0, first->data);
1465 put_16 (big_endian, 2, first->data + 2);
1467 first->next = NULL;
1468 pp = &first->next;
1470 c = 0;
1471 for (gc = group_cursors; gc != NULL; gc = gc->next)
1473 struct bindata *d;
1475 ++c;
1477 d = (struct bindata *) reswr_alloc (sizeof *d);
1478 d->length = 14;
1479 d->data = (unsigned char *) reswr_alloc (14);
1481 put_16 (big_endian, gc->width, d->data);
1482 put_16 (big_endian, gc->height, d->data + 2);
1483 put_16 (big_endian, gc->planes, d->data + 4);
1484 put_16 (big_endian, gc->bits, d->data + 6);
1485 put_32 (big_endian, gc->bytes, d->data + 8);
1486 put_16 (big_endian, gc->index, d->data + 12);
1488 d->next = NULL;
1489 *pp = d;
1490 pp = &d->next;
1493 put_16 (big_endian, c, first->data + 4);
1495 return first;
1498 /* Convert a dialog resource to binary. */
1500 static struct bindata *
1501 res_to_bin_dialog (const struct dialog *dialog, int big_endian)
1503 int dialogex;
1504 struct bindata *first, **pp;
1505 unsigned long length;
1506 int off, c;
1507 struct dialog_control *dc;
1509 dialogex = extended_dialog (dialog);
1511 first = (struct bindata *) reswr_alloc (sizeof *first);
1512 first->length = dialogex ? 26 : 18;
1513 first->data = (unsigned char *) reswr_alloc (first->length);
1515 length = first->length;
1517 if (! dialogex)
1519 put_32 (big_endian, dialog->style, first->data);
1520 put_32 (big_endian, dialog->exstyle, first->data + 4);
1521 off = 8;
1523 else
1525 put_16 (big_endian, 1, first->data);
1526 put_16 (big_endian, 0xffff, first->data + 2);
1528 if (dialog->ex == NULL)
1529 put_32 (big_endian, 0, first->data + 4);
1530 else
1531 put_32 (big_endian, dialog->ex->help, first->data + 4);
1532 put_32 (big_endian, dialog->exstyle, first->data + 8);
1533 put_32 (big_endian, dialog->style, first->data + 12);
1534 off = 16;
1537 put_16 (big_endian, dialog->x, first->data + off + 2);
1538 put_16 (big_endian, dialog->y, first->data + off + 4);
1539 put_16 (big_endian, dialog->width, first->data + off + 6);
1540 put_16 (big_endian, dialog->height, first->data + off + 8);
1542 pp = &first->next;
1544 *pp = resid_to_bin (dialog->menu, big_endian);
1545 length += (*pp)->length;
1546 pp = &(*pp)->next;
1548 *pp = resid_to_bin (dialog->class, big_endian);
1549 length += (*pp)->length;
1550 pp = &(*pp)->next;
1552 *pp = unicode_to_bin (dialog->caption, big_endian);
1553 length += (*pp)->length;
1554 pp = &(*pp)->next;
1556 if ((dialog->style & DS_SETFONT) != 0)
1558 struct bindata *d;
1560 d = (struct bindata *) reswr_alloc (sizeof *d);
1561 d->length = dialogex ? 6 : 2;
1562 d->data = (unsigned char *) reswr_alloc (d->length);
1564 length += d->length;
1566 put_16 (big_endian, dialog->pointsize, d->data);
1568 if (dialogex)
1570 if (dialog->ex == NULL)
1572 put_16 (big_endian, 0, d->data + 2);
1573 put_8 (0, d->data + 4);
1574 put_8 (1, d->data + 5);
1576 else
1578 put_16 (big_endian, dialog->ex->weight, d->data + 2);
1579 put_8 (dialog->ex->italic, d->data + 4);
1580 put_8 (dialog->ex->charset, d->data + 5);
1584 *pp = d;
1585 pp = &d->next;
1587 *pp = unicode_to_bin (dialog->font, big_endian);
1588 length += (*pp)->length;
1589 pp = &(*pp)->next;
1592 c = 0;
1593 for (dc = dialog->controls; dc != NULL; dc = dc->next)
1595 struct bindata *d;
1596 int dcoff;
1598 ++c;
1600 dword_align_bin (&pp, &length);
1602 d = (struct bindata *) reswr_alloc (sizeof *d);
1603 d->length = dialogex ? 24 : 18;
1604 d->data = (unsigned char *) reswr_alloc (d->length);
1606 length += d->length;
1608 if (! dialogex)
1610 put_32 (big_endian, dc->style, d->data);
1611 put_32 (big_endian, dc->exstyle, d->data + 4);
1612 dcoff = 8;
1614 else
1616 put_32 (big_endian, dc->help, d->data);
1617 put_32 (big_endian, dc->exstyle, d->data + 4);
1618 put_32 (big_endian, dc->style, d->data + 8);
1619 dcoff = 12;
1622 put_16 (big_endian, dc->x, d->data + dcoff);
1623 put_16 (big_endian, dc->y, d->data + dcoff + 2);
1624 put_16 (big_endian, dc->width, d->data + dcoff + 4);
1625 put_16 (big_endian, dc->height, d->data + dcoff + 6);
1627 if (dialogex)
1628 put_32 (big_endian, dc->id, d->data + dcoff + 8);
1629 else
1630 put_16 (big_endian, dc->id, d->data + dcoff + 8);
1632 *pp = d;
1633 pp = &d->next;
1635 *pp = resid_to_bin (dc->class, big_endian);
1636 length += (*pp)->length;
1637 pp = &(*pp)->next;
1639 *pp = resid_to_bin (dc->text, big_endian);
1640 length += (*pp)->length;
1641 pp = &(*pp)->next;
1643 d = (struct bindata *) reswr_alloc (sizeof *d);
1644 d->length = 2;
1645 d->data = (unsigned char *) reswr_alloc (2);
1647 length += 2;
1649 d->next = NULL;
1650 *pp = d;
1651 pp = &d->next;
1653 if (dc->data == NULL)
1654 put_16 (big_endian, 0, d->data);
1655 else
1657 unsigned long sublen;
1659 dword_align_bin (&pp, &length);
1661 *pp = res_to_bin_rcdata (dc->data, big_endian);
1662 sublen = 0;
1663 while (*pp != NULL)
1665 sublen += (*pp)->length;
1666 pp = &(*pp)->next;
1669 put_16 (big_endian, sublen, d->data);
1671 length += sublen;
1674 put_16 (big_endian, c, first->data + off);
1676 return first;
1679 /* Convert a fontdir resource to binary. */
1681 static struct bindata *
1682 res_to_bin_fontdir (const struct fontdir *fontdirs, int big_endian)
1684 struct bindata *first, **pp;
1685 int c;
1686 const struct fontdir *fd;
1688 first = (struct bindata *) reswr_alloc (sizeof *first);
1689 first->length = 2;
1690 first->data = (unsigned char *) reswr_alloc (2);
1692 first->next = NULL;
1693 pp = &first->next;
1695 c = 0;
1696 for (fd = fontdirs; fd != NULL; fd = fd->next)
1698 struct bindata *d;
1700 ++c;
1702 d = (struct bindata *) reswr_alloc (sizeof *d);
1703 d->length = 2;
1704 d->data = (unsigned char *) reswr_alloc (2);
1706 put_16 (big_endian, fd->index, d->data);
1708 *pp = d;
1709 pp = &d->next;
1711 d = (struct bindata *) reswr_alloc (sizeof *d);
1712 d->length = fd->length;
1713 d->data = (unsigned char *) fd->data;
1715 d->next = NULL;
1716 *pp = d;
1717 pp = &d->next;
1720 put_16 (big_endian, c, first->data);
1722 return first;
1725 /* Convert a group icon resource to binary. */
1727 static struct bindata *
1728 res_to_bin_group_icon (const struct group_icon *group_icons, int big_endian)
1730 struct bindata *first, **pp;
1731 int c;
1732 const struct group_icon *gi;
1734 first = (struct bindata *) reswr_alloc (sizeof *first);
1735 first->length = 6;
1736 first->data = (unsigned char *) reswr_alloc (6);
1738 put_16 (big_endian, 0, first->data);
1739 put_16 (big_endian, 1, first->data + 2);
1741 first->next = NULL;
1742 pp = &first->next;
1744 c = 0;
1745 for (gi = group_icons; gi != NULL; gi = gi->next)
1747 struct bindata *d;
1749 ++c;
1751 d = (struct bindata *) reswr_alloc (sizeof *d);
1752 d->length = 14;
1753 d->data = (unsigned char *) reswr_alloc (14);
1755 d->data[0] = gi->width;
1756 d->data[1] = gi->height;
1757 d->data[2] = gi->colors;
1758 d->data[3] = 0;
1759 put_16 (big_endian, gi->planes, d->data + 4);
1760 put_16 (big_endian, gi->bits, d->data + 6);
1761 put_32 (big_endian, gi->bytes, d->data + 8);
1762 put_16 (big_endian, gi->index, d->data + 12);
1764 d->next = NULL;
1765 *pp = d;
1766 pp = &d->next;
1769 put_16 (big_endian, c, first->data + 4);
1771 return first;
1774 /* Convert a menu resource to binary. */
1776 static struct bindata *
1777 res_to_bin_menu (const struct menu *menu, int big_endian)
1779 int menuex;
1780 struct bindata *d;
1782 menuex = extended_menu (menu);
1784 d = (struct bindata *) reswr_alloc (sizeof *d);
1785 d->length = menuex ? 8 : 4;
1786 d->data = (unsigned char *) reswr_alloc (d->length);
1788 if (! menuex)
1790 put_16 (big_endian, 0, d->data);
1791 put_16 (big_endian, 0, d->data + 2);
1793 d->next = res_to_bin_menuitems (menu->items, big_endian);
1795 else
1797 put_16 (big_endian, 1, d->data);
1798 put_16 (big_endian, 4, d->data + 2);
1799 put_32 (big_endian, menu->help, d->data + 4);
1801 d->next = res_to_bin_menuexitems (menu->items, big_endian);
1804 return d;
1807 /* Convert menu items to binary. */
1809 static struct bindata *
1810 res_to_bin_menuitems (const struct menuitem *items, int big_endian)
1812 struct bindata *first, **pp;
1813 const struct menuitem *mi;
1815 first = NULL;
1816 pp = &first;
1818 for (mi = items; mi != NULL; mi = mi->next)
1820 struct bindata *d;
1821 int flags;
1823 d = (struct bindata *) reswr_alloc (sizeof *d);
1824 d->length = mi->popup == NULL ? 4 : 2;
1825 d->data = (unsigned char *) reswr_alloc (d->length);
1827 flags = mi->type;
1828 if (mi->next == NULL)
1829 flags |= MENUITEM_ENDMENU;
1830 if (mi->popup != NULL)
1831 flags |= MENUITEM_POPUP;
1833 put_16 (big_endian, flags, d->data);
1835 if (mi->popup == NULL)
1836 put_16 (big_endian, mi->id, d->data + 2);
1838 *pp = d;
1839 pp = &d->next;
1841 *pp = unicode_to_bin (mi->text, big_endian);
1842 pp = &(*pp)->next;
1844 if (mi->popup != NULL)
1846 *pp = res_to_bin_menuitems (mi->popup, big_endian);
1847 while (*pp != NULL)
1848 pp = &(*pp)->next;
1852 return first;
1855 /* Convert menuex items to binary. */
1857 static struct bindata *
1858 res_to_bin_menuexitems (const struct menuitem *items, int big_endian)
1860 struct bindata *first, **pp;
1861 unsigned long length;
1862 const struct menuitem *mi;
1864 first = NULL;
1865 pp = &first;
1867 length = 0;
1869 for (mi = items; mi != NULL; mi = mi->next)
1871 struct bindata *d;
1872 int flags;
1874 dword_align_bin (&pp, &length);
1876 d = (struct bindata *) reswr_alloc (sizeof *d);
1877 d->length = 12;
1878 d->data = (unsigned char *) reswr_alloc (12);
1880 length += 12;
1882 put_32 (big_endian, mi->type, d->data);
1883 put_32 (big_endian, mi->state, d->data + 4);
1884 put_16 (big_endian, mi->id, d->data + 8);
1886 flags = 0;
1887 if (mi->next == NULL)
1888 flags |= 0x80;
1889 if (mi->popup != NULL)
1890 flags |= 1;
1891 put_16 (big_endian, flags, d->data + 10);
1893 *pp = d;
1894 pp = &d->next;
1896 *pp = unicode_to_bin (mi->text, big_endian);
1897 length += (*pp)->length;
1898 pp = &(*pp)->next;
1900 if (mi->popup != NULL)
1902 dword_align_bin (&pp, &length);
1904 d = (struct bindata *) reswr_alloc (sizeof *d);
1905 d->length = 4;
1906 d->data = (unsigned char *) reswr_alloc (4);
1908 put_32 (big_endian, mi->help, d->data);
1910 *pp = d;
1911 pp = &d->next;
1913 *pp = res_to_bin_menuexitems (mi->popup, big_endian);
1914 while (*pp != NULL)
1916 length += (*pp)->length;
1917 pp = &(*pp)->next;
1922 return first;
1925 /* Convert an rcdata resource to binary. This is also used to convert
1926 other information which happens to be stored in rcdata_item lists
1927 to binary. */
1929 static struct bindata *
1930 res_to_bin_rcdata (const struct rcdata_item *items, int big_endian)
1932 struct bindata *first, **pp;
1933 const struct rcdata_item *ri;
1935 first = NULL;
1936 pp = &first;
1938 for (ri = items; ri != NULL; ri = ri->next)
1940 struct bindata *d;
1942 d = (struct bindata *) reswr_alloc (sizeof *d);
1944 switch (ri->type)
1946 default:
1947 abort ();
1949 case RCDATA_WORD:
1950 d->length = 2;
1951 d->data = (unsigned char *) reswr_alloc (2);
1952 put_16 (big_endian, ri->u.word, d->data);
1953 break;
1955 case RCDATA_DWORD:
1956 d->length = 4;
1957 d->data = (unsigned char *) reswr_alloc (4);
1958 put_32 (big_endian, ri->u.dword, d->data);
1959 break;
1961 case RCDATA_STRING:
1962 d->length = ri->u.string.length;
1963 d->data = (unsigned char *) ri->u.string.s;
1964 break;
1966 case RCDATA_WSTRING:
1968 unsigned long i;
1970 d->length = ri->u.wstring.length * 2;
1971 d->data = (unsigned char *) reswr_alloc (d->length);
1972 for (i = 0; i < ri->u.wstring.length; i++)
1973 put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2);
1974 break;
1977 case RCDATA_BUFFER:
1978 d->length = ri->u.buffer.length;
1979 d->data = (unsigned char *) ri->u.buffer.data;
1980 break;
1983 d->next = NULL;
1984 *pp = d;
1985 pp = &d->next;
1988 return first;
1991 /* Convert a stringtable resource to binary. */
1993 static struct bindata *
1994 res_to_bin_stringtable (const struct stringtable *st, int big_endian)
1996 struct bindata *first, **pp;
1997 int i;
1999 first = NULL;
2000 pp = &first;
2002 for (i = 0; i < 16; i++)
2004 int slen, j;
2005 struct bindata *d;
2006 unichar *s;
2008 slen = st->strings[i].length;
2009 s = st->strings[i].string;
2011 d = (struct bindata *) reswr_alloc (sizeof *d);
2012 d->length = 2 + slen * 2;
2013 d->data = (unsigned char *) reswr_alloc (d->length);
2015 put_16 (big_endian, slen, d->data);
2017 for (j = 0; j < slen; j++)
2018 put_16 (big_endian, s[j], d->data + 2 + j * 2);
2020 d->next = NULL;
2021 *pp = d;
2022 pp = &d->next;
2025 return first;
2028 /* Convert an ASCII string to a unicode binary string. This always
2029 returns exactly one bindata structure. */
2031 static struct bindata *
2032 string_to_unicode_bin (const char *s, int big_endian)
2034 size_t len, i;
2035 struct bindata *d;
2037 len = strlen (s);
2039 d = (struct bindata *) reswr_alloc (sizeof *d);
2040 d->length = len * 2 + 2;
2041 d->data = (unsigned char *) reswr_alloc (d->length);
2043 for (i = 0; i < len; i++)
2044 put_16 (big_endian, s[i], d->data + i * 2);
2045 put_16 (big_endian, 0, d->data + i * 2);
2047 d->next = NULL;
2049 return d;
2052 /* Convert a versioninfo resource to binary. */
2054 static struct bindata *
2055 res_to_bin_versioninfo (const struct versioninfo *versioninfo, int big_endian)
2057 struct bindata *first, **pp;
2058 unsigned long length;
2059 struct ver_info *vi;
2061 first = (struct bindata *) reswr_alloc (sizeof *first);
2062 first->length = 6;
2063 first->data = (unsigned char *) reswr_alloc (6);
2065 length = 6;
2067 if (versioninfo->fixed == NULL)
2068 put_16 (big_endian, 0, first->data + 2);
2069 else
2070 put_16 (big_endian, 52, first->data + 2);
2072 put_16 (big_endian, 0, first->data + 4);
2074 pp = &first->next;
2076 *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian);
2077 length += (*pp)->length;
2078 pp = &(*pp)->next;
2080 dword_align_bin (&pp, &length);
2082 if (versioninfo->fixed != NULL)
2084 const struct fixed_versioninfo *fi;
2085 struct bindata *d;
2087 d = (struct bindata *) reswr_alloc (sizeof *d);
2088 d->length = 52;
2089 d->data = (unsigned char *) reswr_alloc (52);
2091 length += 52;
2093 fi = versioninfo->fixed;
2095 put_32 (big_endian, 0xfeef04bd, d->data);
2096 put_32 (big_endian, 0x10000, d->data + 4);
2097 put_32 (big_endian, fi->file_version_ms, d->data + 8);
2098 put_32 (big_endian, fi->file_version_ls, d->data + 12);
2099 put_32 (big_endian, fi->product_version_ms, d->data + 16);
2100 put_32 (big_endian, fi->product_version_ls, d->data + 20);
2101 put_32 (big_endian, fi->file_flags_mask, d->data + 24);
2102 put_32 (big_endian, fi->file_flags, d->data + 28);
2103 put_32 (big_endian, fi->file_os, d->data + 32);
2104 put_32 (big_endian, fi->file_type, d->data + 36);
2105 put_32 (big_endian, fi->file_subtype, d->data + 40);
2106 put_32 (big_endian, fi->file_date_ms, d->data + 44);
2107 put_32 (big_endian, fi->file_date_ls, d->data + 48);
2109 d->next = NULL;
2110 *pp = d;
2111 pp = &d->next;
2114 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2116 struct bindata *vid;
2117 unsigned long vilen;
2119 dword_align_bin (&pp, &length);
2121 vid = (struct bindata *) reswr_alloc (sizeof *vid);
2122 vid->length = 6;
2123 vid->data = (unsigned char *) reswr_alloc (6);
2125 length += 6;
2126 vilen = 6;
2128 put_16 (big_endian, 0, vid->data + 2);
2129 put_16 (big_endian, 0, vid->data + 4);
2131 *pp = vid;
2132 pp = &vid->next;
2134 switch (vi->type)
2136 default:
2137 abort ();
2139 case VERINFO_STRING:
2141 unsigned long hold, vslen;
2142 struct bindata *vsd;
2143 const struct ver_stringinfo *vs;
2145 *pp = string_to_unicode_bin ("StringFileInfo", big_endian);
2146 length += (*pp)->length;
2147 vilen += (*pp)->length;
2148 pp = &(*pp)->next;
2150 hold = length;
2151 dword_align_bin (&pp, &length);
2152 vilen += length - hold;
2154 vsd = (struct bindata *) reswr_alloc (sizeof *vsd);
2155 vsd->length = 6;
2156 vsd->data = (unsigned char *) reswr_alloc (6);
2158 length += 6;
2159 vilen += 6;
2160 vslen = 6;
2162 put_16 (big_endian, 0, vsd->data + 2);
2163 put_16 (big_endian, 0, vsd->data + 4);
2165 *pp = vsd;
2166 pp = &vsd->next;
2168 *pp = unicode_to_bin (vi->u.string.language, big_endian);
2169 length += (*pp)->length;
2170 vilen += (*pp)->length;
2171 vslen += (*pp)->length;
2172 pp = &(*pp)->next;
2174 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2176 struct bindata *vssd;
2177 unsigned long vsslen;
2179 hold = length;
2180 dword_align_bin (&pp, &length);
2181 vilen += length - hold;
2182 vslen += length - hold;
2184 vssd = (struct bindata *) reswr_alloc (sizeof *vssd);
2185 vssd->length = 6;
2186 vssd->data = (unsigned char *) reswr_alloc (6);
2188 length += 6;
2189 vilen += 6;
2190 vslen += 6;
2191 vsslen = 6;
2193 put_16 (big_endian, 1, vssd->data + 4);
2195 *pp = vssd;
2196 pp = &vssd->next;
2198 *pp = unicode_to_bin (vs->key, big_endian);
2199 length += (*pp)->length;
2200 vilen += (*pp)->length;
2201 vslen += (*pp)->length;
2202 vsslen += (*pp)->length;
2203 pp = &(*pp)->next;
2205 hold = length;
2206 dword_align_bin (&pp, &length);
2207 vilen += length - hold;
2208 vslen += length - hold;
2209 vsslen += length - hold;
2211 *pp = unicode_to_bin (vs->value, big_endian);
2212 put_16 (big_endian, (*pp)->length / 2, vssd->data + 2);
2213 length += (*pp)->length;
2214 vilen += (*pp)->length;
2215 vslen += (*pp)->length;
2216 vsslen += (*pp)->length;
2217 pp = &(*pp)->next;
2219 put_16 (big_endian, vsslen, vssd->data);
2222 put_16 (big_endian, vslen, vsd->data);
2224 break;
2227 case VERINFO_VAR:
2229 unsigned long hold, vvlen, vvvlen;
2230 struct bindata *vvd;
2231 const struct ver_varinfo *vv;
2233 *pp = string_to_unicode_bin ("VarFileInfo", big_endian);
2234 length += (*pp)->length;
2235 vilen += (*pp)->length;
2236 pp = &(*pp)->next;
2238 hold = length;
2239 dword_align_bin (&pp, &length);
2240 vilen += length - hold;
2242 vvd = (struct bindata *) reswr_alloc (sizeof *vvd);
2243 vvd->length = 6;
2244 vvd->data = (unsigned char *) reswr_alloc (6);
2246 length += 6;
2247 vilen += 6;
2248 vvlen = 6;
2250 put_16 (big_endian, 0, vvd->data + 4);
2252 *pp = vvd;
2253 pp = &vvd->next;
2255 *pp = unicode_to_bin (vi->u.var.key, big_endian);
2256 length += (*pp)->length;
2257 vilen += (*pp)->length;
2258 vvlen += (*pp)->length;
2259 pp = &(*pp)->next;
2261 hold = length;
2262 dword_align_bin (&pp, &length);
2263 vilen += length - hold;
2264 vvlen += length - hold;
2266 vvvlen = 0;
2268 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2270 struct bindata *vvsd;
2272 vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd);
2273 vvsd->length = 4;
2274 vvsd->data = (unsigned char *) reswr_alloc (4);
2276 length += 4;
2277 vilen += 4;
2278 vvlen += 4;
2279 vvvlen += 4;
2281 put_16 (big_endian, vv->language, vvsd->data);
2282 put_16 (big_endian, vv->charset, vvsd->data + 2);
2284 vvsd->next = NULL;
2285 *pp = vvsd;
2286 pp = &vvsd->next;
2289 put_16 (big_endian, vvlen, vvd->data);
2290 put_16 (big_endian, vvvlen, vvd->data + 2);
2292 break;
2296 put_16 (big_endian, vilen, vid->data);
2299 put_16 (big_endian, length, first->data);
2301 return first;
2304 /* Convert a generic resource to binary. */
2306 static struct bindata *
2307 res_to_bin_generic (unsigned long length, const unsigned char *data)
2309 struct bindata *d;
2311 d = (struct bindata *) reswr_alloc (sizeof *d);
2312 d->length = length;
2313 d->data = (unsigned char *) data;
2315 d->next = NULL;
2317 return d;