003-02-12 Dave Brolley <brolley@redhat.com>
[binutils.git] / binutils / resbin.c
blob079818c6fab911de89d2c5453d5e3e66e54e0b92
1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
22 /* This file contains functions to convert between the binary resource
23 format and the internal structures that we want to use. The same
24 binary resource format is used in both res and COFF files. */
26 #include "bfd.h"
27 #include "bucomm.h"
28 #include "libiberty.h"
29 #include "windres.h"
31 /* Macros to swap in values. */
33 #define get_8(s) (*((unsigned char *)(s)))
34 #define get_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s))
35 #define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s))
37 /* Local functions. */
39 static void toosmall PARAMS ((const char *));
40 static unichar *get_unicode
41 PARAMS ((const unsigned char *, unsigned long, int, int *));
42 static int get_resid
43 PARAMS ((struct res_id *, const unsigned char *, unsigned long, int));
44 static struct res_resource *bin_to_res_generic
45 PARAMS ((enum res_type, const unsigned char *, unsigned long));
46 static struct res_resource *bin_to_res_cursor
47 PARAMS ((const unsigned char *, unsigned long, int));
48 static struct res_resource *bin_to_res_menu
49 PARAMS ((const unsigned char *, unsigned long, int));
50 static struct menuitem *bin_to_res_menuitems
51 PARAMS ((const unsigned char *, unsigned long, int, int *));
52 static struct menuitem *bin_to_res_menuexitems
53 PARAMS ((const unsigned char *, unsigned long, int, int *));
54 static struct res_resource *bin_to_res_dialog
55 PARAMS ((const unsigned char *, unsigned long, int));
56 static struct res_resource *bin_to_res_string
57 PARAMS ((const unsigned char *, unsigned long, int));
58 static struct res_resource *bin_to_res_fontdir
59 PARAMS ((const unsigned char *, unsigned long, int));
60 static struct res_resource *bin_to_res_accelerators
61 PARAMS ((const unsigned char *, unsigned long, int));
62 static struct res_resource *bin_to_res_rcdata
63 PARAMS ((const unsigned char *, unsigned long, int));
64 static struct res_resource *bin_to_res_group_cursor
65 PARAMS ((const unsigned char *, unsigned long, int));
66 static struct res_resource *bin_to_res_group_icon
67 PARAMS ((const unsigned char *, unsigned long, int));
68 static struct res_resource *bin_to_res_version
69 PARAMS ((const unsigned char *, unsigned long, int));
70 static struct res_resource *bin_to_res_userdata
71 PARAMS ((const unsigned char *, unsigned long, int));
72 static void get_version_header
73 PARAMS ((const unsigned char *, unsigned long, int, const char *,
74 unichar **, int *, int *, int *, int *));
76 /* Given a resource type ID, a pointer to data, a length, return a
77 res_resource structure which represents that resource. The caller
78 is responsible for initializing the res_info and coff_info fields
79 of the returned structure. */
81 struct res_resource *
82 bin_to_res (type, data, length, big_endian)
83 struct res_id type;
84 const unsigned char *data;
85 unsigned long length;
86 int big_endian;
88 if (type.named)
89 return bin_to_res_userdata (data, length, big_endian);
90 else
92 switch (type.u.id)
94 default:
95 return bin_to_res_userdata (data, length, big_endian);
96 case RT_CURSOR:
97 return bin_to_res_cursor (data, length, big_endian);
98 case RT_BITMAP:
99 return bin_to_res_generic (RES_TYPE_BITMAP, data, length);
100 case RT_ICON:
101 return bin_to_res_generic (RES_TYPE_ICON, data, length);
102 case RT_MENU:
103 return bin_to_res_menu (data, length, big_endian);
104 case RT_DIALOG:
105 return bin_to_res_dialog (data, length, big_endian);
106 case RT_STRING:
107 return bin_to_res_string (data, length, big_endian);
108 case RT_FONTDIR:
109 return bin_to_res_fontdir (data, length, big_endian);
110 case RT_FONT:
111 return bin_to_res_generic (RES_TYPE_FONT, data, length);
112 case RT_ACCELERATOR:
113 return bin_to_res_accelerators (data, length, big_endian);
114 case RT_RCDATA:
115 return bin_to_res_rcdata (data, length, big_endian);
116 case RT_MESSAGETABLE:
117 return bin_to_res_generic (RES_TYPE_MESSAGETABLE, data, length);
118 case RT_GROUP_CURSOR:
119 return bin_to_res_group_cursor (data, length, big_endian);
120 case RT_GROUP_ICON:
121 return bin_to_res_group_icon (data, length, big_endian);
122 case RT_VERSION:
123 return bin_to_res_version (data, length, big_endian);
128 /* Give an error if the binary data is too small. */
130 static void
131 toosmall (msg)
132 const char *msg;
134 fatal (_("%s: not enough binary data"), msg);
137 /* Swap in a NULL terminated unicode string. */
139 static unichar *
140 get_unicode (data, length, big_endian, retlen)
141 const unsigned char *data;
142 unsigned long length;
143 int big_endian;
144 int *retlen;
146 int c, i;
147 unichar *ret;
149 c = 0;
150 while (1)
152 if (length < (unsigned long) c * 2 + 2)
153 toosmall (_("null terminated unicode string"));
154 if (get_16 (big_endian, data + c * 2) == 0)
155 break;
156 ++c;
159 ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
161 for (i = 0; i < c; i++)
162 ret[i] = get_16 (big_endian, data + i * 2);
163 ret[i] = 0;
165 if (retlen != NULL)
166 *retlen = c;
168 return ret;
171 /* Get a resource identifier. This returns the number of bytes used. */
173 static int
174 get_resid (id, data, length, big_endian)
175 struct res_id *id;
176 const unsigned char *data;
177 unsigned long length;
178 int big_endian;
180 int first;
182 if (length < 2)
183 toosmall (_("resource ID"));
185 first = get_16 (big_endian, data);
186 if (first == 0xffff)
188 if (length < 4)
189 toosmall (_("resource ID"));
190 id->named = 0;
191 id->u.id = get_16 (big_endian, data + 2);
192 return 4;
194 else
196 id->named = 1;
197 id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length);
198 return id->u.n.length * 2 + 2;
202 /* Convert a resource which just stores uninterpreted data from
203 binary. */
205 struct res_resource *
206 bin_to_res_generic (type, data, length)
207 enum res_type type;
208 const unsigned char *data;
209 unsigned long length;
211 struct res_resource *r;
213 r = (struct res_resource *) res_alloc (sizeof *r);
214 r->type = type;
215 r->u.data.data = data;
216 r->u.data.length = length;
218 return r;
221 /* Convert a cursor resource from binary. */
223 struct res_resource *
224 bin_to_res_cursor (data, length, big_endian)
225 const unsigned char *data;
226 unsigned long length;
227 int big_endian;
229 struct cursor *c;
230 struct res_resource *r;
232 if (length < 4)
233 toosmall (_("cursor"));
235 c = (struct cursor *) res_alloc (sizeof *c);
236 c->xhotspot = get_16 (big_endian, data);
237 c->yhotspot = get_16 (big_endian, data + 2);
238 c->length = length - 4;
239 c->data = data + 4;
241 r = (struct res_resource *) res_alloc (sizeof *r);
242 r->type = RES_TYPE_CURSOR;
243 r->u.cursor = c;
245 return r;
248 /* Convert a menu resource from binary. */
250 struct res_resource *
251 bin_to_res_menu (data, length, big_endian)
252 const unsigned char *data;
253 unsigned long length;
254 int big_endian;
256 struct res_resource *r;
257 struct menu *m;
258 int version, read;
260 r = (struct res_resource *) res_alloc (sizeof *r);
261 r->type = RES_TYPE_MENU;
263 m = (struct menu *) res_alloc (sizeof *m);
264 r->u.menu = m;
266 if (length < 2)
267 toosmall (_("menu header"));
269 version = get_16 (big_endian, data);
271 if (version == 0)
273 if (length < 4)
274 toosmall (_("menu header"));
275 m->help = 0;
276 m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian,
277 &read);
279 else if (version == 1)
281 unsigned int offset;
283 if (length < 8)
284 toosmall (_("menuex header"));
285 m->help = get_32 (big_endian, data + 4);
286 offset = get_16 (big_endian, data + 2);
287 if (offset + 4 >= length)
288 toosmall (_("menuex offset"));
289 m->items = bin_to_res_menuexitems (data + 4 + offset,
290 length - (4 + offset),
291 big_endian,
292 &read);
294 else
295 fatal (_("unsupported menu version %d"), version);
297 return r;
300 /* Convert menu items from binary. */
302 static struct menuitem *
303 bin_to_res_menuitems (data, length, big_endian, read)
304 const unsigned char *data;
305 unsigned long length;
306 int big_endian;
307 int *read;
309 struct menuitem *first, **pp;
311 first = NULL;
312 pp = &first;
314 *read = 0;
316 while (length > 0)
318 int flags, slen, itemlen;
319 unsigned int stroff;
320 struct menuitem *mi;
322 if (length < 4)
323 toosmall (_("menuitem header"));
325 mi = (struct menuitem *) res_alloc (sizeof *mi);
326 mi->state = 0;
327 mi->help = 0;
329 flags = get_16 (big_endian, data);
330 mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
332 if ((flags & MENUITEM_POPUP) == 0)
333 stroff = 4;
334 else
335 stroff = 2;
337 if (length < stroff + 2)
338 toosmall (_("menuitem header"));
340 if (get_16 (big_endian, data + stroff) == 0)
342 slen = 0;
343 mi->text = NULL;
345 else
346 mi->text = get_unicode (data + stroff, length - stroff, big_endian,
347 &slen);
349 itemlen = stroff + slen * 2 + 2;
351 if ((flags & MENUITEM_POPUP) == 0)
353 mi->popup = NULL;
354 mi->id = get_16 (big_endian, data + 2);
356 else
358 int subread;
360 mi->id = 0;
361 mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen,
362 big_endian, &subread);
363 itemlen += subread;
366 mi->next = NULL;
367 *pp = mi;
368 pp = &mi->next;
370 data += itemlen;
371 length -= itemlen;
372 *read += itemlen;
374 if ((flags & MENUITEM_ENDMENU) != 0)
375 return first;
378 return first;
381 /* Convert menuex items from binary. */
383 static struct menuitem *
384 bin_to_res_menuexitems (data, length, big_endian, read)
385 const unsigned char *data;
386 unsigned long length;
387 int big_endian;
388 int *read;
390 struct menuitem *first, **pp;
392 first = NULL;
393 pp = &first;
395 *read = 0;
397 while (length > 0)
399 int flags, slen;
400 unsigned int itemlen;
401 struct menuitem *mi;
403 if (length < 14)
404 toosmall (_("menuitem header"));
406 mi = (struct menuitem *) res_alloc (sizeof *mi);
407 mi->type = get_32 (big_endian, data);
408 mi->state = get_32 (big_endian, data + 4);
409 mi->id = get_16 (big_endian, data + 8);
411 flags = get_16 (big_endian, data + 10);
413 if (get_16 (big_endian, data + 12) == 0)
415 slen = 0;
416 mi->text = NULL;
418 else
419 mi->text = get_unicode (data + 12, length - 12, big_endian, &slen);
421 itemlen = 12 + slen * 2 + 2;
422 itemlen = (itemlen + 3) &~ 3;
424 if ((flags & 1) == 0)
426 mi->popup = NULL;
427 mi->help = 0;
429 else
431 int subread;
433 if (length < itemlen + 4)
434 toosmall (_("menuitem"));
435 mi->help = get_32 (big_endian, data + itemlen);
436 itemlen += 4;
438 mi->popup = bin_to_res_menuexitems (data + itemlen,
439 length - itemlen,
440 big_endian, &subread);
441 itemlen += subread;
444 mi->next = NULL;
445 *pp = mi;
446 pp = &mi->next;
448 data += itemlen;
449 length -= itemlen;
450 *read += itemlen;
452 if ((flags & 0x80) != 0)
453 return first;
456 return first;
459 /* Convert a dialog resource from binary. */
461 static struct res_resource *
462 bin_to_res_dialog (data, length, big_endian)
463 const unsigned char *data;
464 unsigned long length;
465 int big_endian;
467 int signature;
468 struct dialog *d;
469 int c, sublen, i;
470 unsigned int off;
471 struct dialog_control **pp;
472 struct res_resource *r;
474 if (length < 18)
475 toosmall (_("dialog header"));
477 d = (struct dialog *) res_alloc (sizeof *d);
479 signature = get_16 (big_endian, data + 2);
480 if (signature != 0xffff)
482 d->ex = NULL;
483 d->style = get_32 (big_endian, data);
484 d->exstyle = get_32 (big_endian, data + 4);
485 off = 8;
487 else
489 int version;
491 version = get_16 (big_endian, data);
492 if (version != 1)
493 fatal (_("unexpected DIALOGEX version %d"), version);
495 d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex));
496 d->ex->help = get_32 (big_endian, data + 4);
497 d->exstyle = get_32 (big_endian, data + 8);
498 d->style = get_32 (big_endian, data + 12);
499 off = 16;
502 if (length < off + 10)
503 toosmall (_("dialog header"));
505 c = get_16 (big_endian, data + off);
506 d->x = get_16 (big_endian, data + off + 2);
507 d->y = get_16 (big_endian, data + off + 4);
508 d->width = get_16 (big_endian, data + off + 6);
509 d->height = get_16 (big_endian, data + off + 8);
511 off += 10;
513 sublen = get_resid (&d->menu, data + off, length - off, big_endian);
514 off += sublen;
516 sublen = get_resid (&d->class, data + off, length - off, big_endian);
517 off += sublen;
519 d->caption = get_unicode (data + off, length - off, big_endian, &sublen);
520 off += sublen * 2 + 2;
521 if (sublen == 0)
522 d->caption = NULL;
524 if ((d->style & DS_SETFONT) == 0)
526 d->pointsize = 0;
527 d->font = NULL;
528 if (d->ex != NULL)
530 d->ex->weight = 0;
531 d->ex->italic = 0;
532 d->ex->charset = 1; /* Default charset. */
535 else
537 if (length < off + 2)
538 toosmall (_("dialog font point size"));
540 d->pointsize = get_16 (big_endian, data + off);
541 off += 2;
543 if (d->ex != NULL)
545 if (length < off + 4)
546 toosmall (_("dialogex font information"));
547 d->ex->weight = get_16 (big_endian, data + off);
548 d->ex->italic = get_8 (data + off + 2);
549 d->ex->charset = get_8 (data + off + 3);
550 off += 4;
553 d->font = get_unicode (data + off, length - off, big_endian, &sublen);
554 off += sublen * 2 + 2;
557 d->controls = NULL;
558 pp = &d->controls;
560 for (i = 0; i < c; i++)
562 struct dialog_control *dc;
563 int datalen;
565 off = (off + 3) &~ 3;
567 dc = (struct dialog_control *) res_alloc (sizeof *dc);
569 if (d->ex == NULL)
571 if (length < off + 8)
572 toosmall (_("dialog control"));
574 dc->style = get_32 (big_endian, data + off);
575 dc->exstyle = get_32 (big_endian, data + off + 4);
576 dc->help = 0;
577 off += 8;
579 else
581 if (length < off + 12)
582 toosmall (_("dialogex control"));
583 dc->help = get_32 (big_endian, data + off);
584 dc->exstyle = get_32 (big_endian, data + off + 4);
585 dc->style = get_32 (big_endian, data + off + 8);
586 off += 12;
589 if (length < off + 10)
590 toosmall (_("dialog control"));
592 dc->x = get_16 (big_endian, data + off);
593 dc->y = get_16 (big_endian, data + off + 2);
594 dc->width = get_16 (big_endian, data + off + 4);
595 dc->height = get_16 (big_endian, data + off + 6);
597 if (d->ex != NULL)
598 dc->id = get_32 (big_endian, data + off + 8);
599 else
600 dc->id = get_16 (big_endian, data + off + 8);
602 off += 10 + (d->ex != NULL ? 2 : 0);
604 sublen = get_resid (&dc->class, data + off, length - off, big_endian);
605 off += sublen;
607 sublen = get_resid (&dc->text, data + off, length - off, big_endian);
608 off += sublen;
610 if (length < off + 2)
611 toosmall (_("dialog control end"));
613 datalen = get_16 (big_endian, data + off);
614 off += 2;
616 if (datalen == 0)
617 dc->data = NULL;
618 else
620 off = (off + 3) &~ 3;
622 if (length < off + datalen)
623 toosmall (_("dialog control data"));
625 dc->data = ((struct rcdata_item *)
626 res_alloc (sizeof (struct rcdata_item)));
627 dc->data->next = NULL;
628 dc->data->type = RCDATA_BUFFER;
629 dc->data->u.buffer.length = datalen;
630 dc->data->u.buffer.data = data + off;
632 off += datalen;
635 dc->next = NULL;
636 *pp = dc;
637 pp = &dc->next;
640 r = (struct res_resource *) res_alloc (sizeof *r);
641 r->type = RES_TYPE_DIALOG;
642 r->u.dialog = d;
644 return r;
647 /* Convert a stringtable resource from binary. */
649 static struct res_resource *
650 bin_to_res_string (data, length, big_endian)
651 const unsigned char *data;
652 unsigned long length;
653 int big_endian;
655 struct stringtable *st;
656 int i;
657 struct res_resource *r;
659 st = (struct stringtable *) res_alloc (sizeof *st);
661 for (i = 0; i < 16; i++)
663 unsigned int slen;
665 if (length < 2)
666 toosmall (_("stringtable string length"));
667 slen = get_16 (big_endian, data);
668 st->strings[i].length = slen;
670 if (slen > 0)
672 unichar *s;
673 unsigned int j;
675 if (length < 2 + 2 * slen)
676 toosmall (_("stringtable string"));
678 s = (unichar *) res_alloc (slen * sizeof (unichar));
679 st->strings[i].string = s;
681 for (j = 0; j < slen; j++)
682 s[j] = get_16 (big_endian, data + 2 + j * 2);
685 data += 2 + 2 * slen;
686 length -= 2 + 2 * slen;
689 r = (struct res_resource *) res_alloc (sizeof *r);
690 r->type = RES_TYPE_STRINGTABLE;
691 r->u.stringtable = st;
693 return r;
696 /* Convert a fontdir resource from binary. */
698 static struct res_resource *
699 bin_to_res_fontdir (data, length, big_endian)
700 const unsigned char *data;
701 unsigned long length;
702 int big_endian;
704 int c, i;
705 struct fontdir *first, **pp;
706 struct res_resource *r;
708 if (length < 2)
709 toosmall (_("fontdir header"));
711 c = get_16 (big_endian, data);
713 first = NULL;
714 pp = &first;
716 for (i = 0; i < c; i++)
718 struct fontdir *fd;
719 unsigned int off;
721 if (length < 56)
722 toosmall (_("fontdir"));
724 fd = (struct fontdir *) res_alloc (sizeof *fd);
725 fd->index = get_16 (big_endian, data);
727 /* To work out the length of the fontdir data, we must get the
728 length of the device name and face name strings, even though
729 we don't store them in the fontdir structure. The
730 documentation says that these are NULL terminated char
731 strings, not Unicode strings. */
733 off = 56;
735 while (off < length && data[off] != '\0')
736 ++off;
737 if (off >= length)
738 toosmall (_("fontdir device name"));
739 ++off;
741 while (off < length && data[off] != '\0')
742 ++off;
743 if (off >= length)
744 toosmall (_("fontdir face name"));
745 ++off;
747 fd->length = off;
748 fd->data = data;
750 fd->next = NULL;
751 *pp = fd;
752 pp = &fd->next;
754 /* The documentation does not indicate that any rounding is
755 required. */
757 data += off;
758 length -= off;
761 r = (struct res_resource *) res_alloc (sizeof *r);
762 r->type = RES_TYPE_FONTDIR;
763 r->u.fontdir = first;
765 return r;
768 /* Convert an accelerators resource from binary. */
770 static struct res_resource *
771 bin_to_res_accelerators (data, length, big_endian)
772 const unsigned char *data;
773 unsigned long length;
774 int big_endian;
776 struct accelerator *first, **pp;
777 struct res_resource *r;
779 first = NULL;
780 pp = &first;
782 while (1)
784 struct accelerator *a;
786 if (length < 8)
787 toosmall (_("accelerator"));
789 a = (struct accelerator *) res_alloc (sizeof *a);
791 a->flags = get_16 (big_endian, data);
792 a->key = get_16 (big_endian, data + 2);
793 a->id = get_16 (big_endian, data + 4);
795 a->next = NULL;
796 *pp = a;
797 pp = &a->next;
799 if ((a->flags & ACC_LAST) != 0)
800 break;
802 data += 8;
803 length -= 8;
806 r = (struct res_resource *) res_alloc (sizeof *r);
807 r->type = RES_TYPE_ACCELERATOR;
808 r->u.acc = first;
810 return r;
813 /* Convert an rcdata resource from binary. */
815 static struct res_resource *
816 bin_to_res_rcdata (data, length, big_endian)
817 const unsigned char *data;
818 unsigned long length;
819 int big_endian ATTRIBUTE_UNUSED;
821 struct rcdata_item *ri;
822 struct res_resource *r;
824 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
826 ri->next = NULL;
827 ri->type = RCDATA_BUFFER;
828 ri->u.buffer.length = length;
829 ri->u.buffer.data = data;
831 r = (struct res_resource *) res_alloc (sizeof *r);
832 r->type = RES_TYPE_RCDATA;
833 r->u.rcdata = ri;
835 return r;
838 /* Convert a group cursor resource from binary. */
840 static struct res_resource *
841 bin_to_res_group_cursor (data, length, big_endian)
842 const unsigned char *data;
843 unsigned long length;
844 int big_endian;
846 int type, c, i;
847 struct group_cursor *first, **pp;
848 struct res_resource *r;
850 if (length < 6)
851 toosmall (_("group cursor header"));
853 type = get_16 (big_endian, data + 2);
854 if (type != 2)
855 fatal (_("unexpected group cursor type %d"), type);
857 c = get_16 (big_endian, data + 4);
859 data += 6;
860 length -= 6;
862 first = NULL;
863 pp = &first;
865 for (i = 0; i < c; i++)
867 struct group_cursor *gc;
869 if (length < 14)
870 toosmall (_("group cursor"));
872 gc = (struct group_cursor *) res_alloc (sizeof *gc);
874 gc->width = get_16 (big_endian, data);
875 gc->height = get_16 (big_endian, data + 2);
876 gc->planes = get_16 (big_endian, data + 4);
877 gc->bits = get_16 (big_endian, data + 6);
878 gc->bytes = get_32 (big_endian, data + 8);
879 gc->index = get_16 (big_endian, data + 12);
881 gc->next = NULL;
882 *pp = gc;
883 pp = &gc->next;
885 data += 14;
886 length -= 14;
889 r = (struct res_resource *) res_alloc (sizeof *r);
890 r->type = RES_TYPE_GROUP_CURSOR;
891 r->u.group_cursor = first;
893 return r;
896 /* Convert a group icon resource from binary. */
898 static struct res_resource *
899 bin_to_res_group_icon (data, length, big_endian)
900 const unsigned char *data;
901 unsigned long length;
902 int big_endian;
904 int type, c, i;
905 struct group_icon *first, **pp;
906 struct res_resource *r;
908 if (length < 6)
909 toosmall (_("group icon header"));
911 type = get_16 (big_endian, data + 2);
912 if (type != 1)
913 fatal (_("unexpected group icon type %d"), type);
915 c = get_16 (big_endian, data + 4);
917 data += 6;
918 length -= 6;
920 first = NULL;
921 pp = &first;
923 for (i = 0; i < c; i++)
925 struct group_icon *gi;
927 if (length < 14)
928 toosmall (_("group icon"));
930 gi = (struct group_icon *) res_alloc (sizeof *gi);
932 gi->width = data[0];
933 gi->height = data[1];
934 gi->colors = data[2];
935 gi->planes = get_16 (big_endian, data + 4);
936 gi->bits = get_16 (big_endian, data + 6);
937 gi->bytes = get_32 (big_endian, data + 8);
938 gi->index = get_16 (big_endian, data + 12);
940 gi->next = NULL;
941 *pp = gi;
942 pp = &gi->next;
944 data += 14;
945 length -= 14;
948 r = (struct res_resource *) res_alloc (sizeof *r);
949 r->type = RES_TYPE_GROUP_ICON;
950 r->u.group_icon = first;
952 return r;
955 /* Extract data from a version header. If KEY is not NULL, then the
956 key must be KEY; otherwise, the key is returned in *PKEY. This
957 sets *LEN to the total length, *VALLEN to the value length, *TYPE
958 to the type, and *OFF to the offset to the children. */
960 static void
961 get_version_header (data, length, big_endian, key, pkey, len, vallen, type,
962 off)
963 const unsigned char *data;
964 unsigned long length;
965 int big_endian;
966 const char *key;
967 unichar **pkey;
968 int *len;
969 int *vallen;
970 int *type;
971 int *off;
973 if (length < 8)
974 toosmall (key);
976 *len = get_16 (big_endian, data);
977 *vallen = get_16 (big_endian, data + 2);
978 *type = get_16 (big_endian, data + 4);
980 *off = 6;
982 length -= 6;
983 data += 6;
985 if (key == NULL)
987 int sublen;
989 *pkey = get_unicode (data, length, big_endian, &sublen);
990 *off += sublen * 2 + 2;
992 else
994 while (1)
996 if (length < 2)
997 toosmall (key);
998 if (get_16 (big_endian, data) != (unsigned char) *key)
999 fatal (_("unexpected version string"));
1001 *off += 2;
1002 length -= 2;
1003 data += 2;
1005 if (*key == '\0')
1006 break;
1008 ++key;
1012 *off = (*off + 3) &~ 3;
1015 /* Convert a version resource from binary. */
1017 static struct res_resource *
1018 bin_to_res_version (data, length, big_endian)
1019 const unsigned char *data;
1020 unsigned long length;
1021 int big_endian;
1023 int verlen, vallen, type, off;
1024 struct fixed_versioninfo *fi;
1025 struct ver_info *first, **pp;
1026 struct versioninfo *v;
1027 struct res_resource *r;
1029 get_version_header (data, length, big_endian, "VS_VERSION_INFO",
1030 (unichar **) NULL, &verlen, &vallen, &type, &off);
1032 if ((unsigned int) verlen != length)
1033 fatal (_("version length %d does not match resource length %lu"),
1034 verlen, length);
1036 if (type != 0)
1037 fatal (_("unexpected version type %d"), type);
1039 data += off;
1040 length -= off;
1042 if (vallen == 0)
1043 fi = NULL;
1044 else
1046 unsigned long signature, fiv;
1048 if (vallen != 52)
1049 fatal (_("unexpected fixed version information length %d"), vallen);
1051 if (length < 52)
1052 toosmall (_("fixed version info"));
1054 signature = get_32 (big_endian, data);
1055 if (signature != 0xfeef04bd)
1056 fatal (_("unexpected fixed version signature %lu"), signature);
1058 fiv = get_32 (big_endian, data + 4);
1059 if (fiv != 0 && fiv != 0x10000)
1060 fatal (_("unexpected fixed version info version %lu"), fiv);
1062 fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi);
1064 fi->file_version_ms = get_32 (big_endian, data + 8);
1065 fi->file_version_ls = get_32 (big_endian, data + 12);
1066 fi->product_version_ms = get_32 (big_endian, data + 16);
1067 fi->product_version_ls = get_32 (big_endian, data + 20);
1068 fi->file_flags_mask = get_32 (big_endian, data + 24);
1069 fi->file_flags = get_32 (big_endian, data + 28);
1070 fi->file_os = get_32 (big_endian, data + 32);
1071 fi->file_type = get_32 (big_endian, data + 36);
1072 fi->file_subtype = get_32 (big_endian, data + 40);
1073 fi->file_date_ms = get_32 (big_endian, data + 44);
1074 fi->file_date_ls = get_32 (big_endian, data + 48);
1076 data += 52;
1077 length -= 52;
1080 first = NULL;
1081 pp = &first;
1083 while (length > 0)
1085 struct ver_info *vi;
1086 int ch;
1088 if (length < 8)
1089 toosmall (_("version var info"));
1091 vi = (struct ver_info *) res_alloc (sizeof *vi);
1093 ch = get_16 (big_endian, data + 6);
1095 if (ch == 'S')
1097 struct ver_stringinfo **ppvs;
1099 vi->type = VERINFO_STRING;
1101 get_version_header (data, length, big_endian, "StringFileInfo",
1102 (unichar **) NULL, &verlen, &vallen, &type,
1103 &off);
1105 if (vallen != 0)
1106 fatal (_("unexpected stringfileinfo value length %d"), vallen);
1108 data += off;
1109 length -= off;
1111 get_version_header (data, length, big_endian, (const char *) NULL,
1112 &vi->u.string.language, &verlen, &vallen,
1113 &type, &off);
1115 if (vallen != 0)
1116 fatal (_("unexpected version stringtable value length %d"), vallen);
1118 data += off;
1119 length -= off;
1120 verlen -= off;
1122 vi->u.string.strings = NULL;
1123 ppvs = &vi->u.string.strings;
1125 /* It's convenient to round verlen to a 4 byte alignment,
1126 since we round the subvariables in the loop. */
1127 verlen = (verlen + 3) &~ 3;
1129 while (verlen > 0)
1131 struct ver_stringinfo *vs;
1132 int subverlen, vslen, valoff;
1134 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1136 get_version_header (data, length, big_endian,
1137 (const char *) NULL, &vs->key, &subverlen,
1138 &vallen, &type, &off);
1140 subverlen = (subverlen + 3) &~ 3;
1142 data += off;
1143 length -= off;
1145 vs->value = get_unicode (data, length, big_endian, &vslen);
1146 valoff = vslen * 2 + 2;
1147 valoff = (valoff + 3) &~ 3;
1149 if (off + valoff != subverlen)
1150 fatal (_("unexpected version string length %d != %d + %d"),
1151 subverlen, off, valoff);
1153 vs->next = NULL;
1154 *ppvs = vs;
1155 ppvs = &vs->next;
1157 data += valoff;
1158 length -= valoff;
1160 if (verlen < subverlen)
1161 fatal (_("unexpected version string length %d < %d"),
1162 verlen, subverlen);
1164 verlen -= subverlen;
1167 else if (ch == 'V')
1169 struct ver_varinfo **ppvv;
1171 vi->type = VERINFO_VAR;
1173 get_version_header (data, length, big_endian, "VarFileInfo",
1174 (unichar **) NULL, &verlen, &vallen, &type,
1175 &off);
1177 if (vallen != 0)
1178 fatal (_("unexpected varfileinfo value length %d"), vallen);
1180 data += off;
1181 length -= off;
1183 get_version_header (data, length, big_endian, (const char *) NULL,
1184 &vi->u.var.key, &verlen, &vallen, &type, &off);
1186 data += off;
1187 length -= off;
1189 vi->u.var.var = NULL;
1190 ppvv = &vi->u.var.var;
1192 while (vallen > 0)
1194 struct ver_varinfo *vv;
1196 if (length < 4)
1197 toosmall (_("version varfileinfo"));
1199 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1201 vv->language = get_16 (big_endian, data);
1202 vv->charset = get_16 (big_endian, data + 2);
1204 vv->next = NULL;
1205 *ppvv = vv;
1206 ppvv = &vv->next;
1208 data += 4;
1209 length -= 4;
1211 if (vallen < 4)
1212 fatal (_("unexpected version value length %d"), vallen);
1214 vallen -= 4;
1217 else
1218 fatal (_("unexpected version string"));
1220 vi->next = NULL;
1221 *pp = vi;
1222 pp = &vi->next;
1225 v = (struct versioninfo *) res_alloc (sizeof *v);
1226 v->fixed = fi;
1227 v->var = first;
1229 r = (struct res_resource *) res_alloc (sizeof *r);
1230 r->type = RES_TYPE_VERSIONINFO;
1231 r->u.versioninfo = v;
1233 return r;
1236 /* Convert an arbitrary user defined resource from binary. */
1238 static struct res_resource *
1239 bin_to_res_userdata (data, length, big_endian)
1240 const unsigned char *data;
1241 unsigned long length;
1242 int big_endian ATTRIBUTE_UNUSED;
1244 struct rcdata_item *ri;
1245 struct res_resource *r;
1247 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1249 ri->next = NULL;
1250 ri->type = RCDATA_BUFFER;
1251 ri->u.buffer.length = length;
1252 ri->u.buffer.data = data;
1254 r = (struct res_resource *) res_alloc (sizeof *r);
1255 r->type = RES_TYPE_USERDATA;
1256 r->u.rcdata = ri;
1258 return r;
1261 /* Macros to swap out values. */
1263 #define put_8(v, s) (*((unsigned char *) (s)) = (unsigned char) (v))
1264 #define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
1265 #define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
1267 /* Local functions used to convert resources to binary format. */
1269 static void dword_align_bin PARAMS ((struct bindata ***, unsigned long *));
1270 static struct bindata *resid_to_bin PARAMS ((struct res_id, int));
1271 static struct bindata *unicode_to_bin PARAMS ((const unichar *, int));
1272 static struct bindata *res_to_bin_accelerator
1273 PARAMS ((const struct accelerator *, int));
1274 static struct bindata *res_to_bin_cursor
1275 PARAMS ((const struct cursor *, int));
1276 static struct bindata *res_to_bin_group_cursor
1277 PARAMS ((const struct group_cursor *, int));
1278 static struct bindata *res_to_bin_dialog
1279 PARAMS ((const struct dialog *, int));
1280 static struct bindata *res_to_bin_fontdir
1281 PARAMS ((const struct fontdir *, int));
1282 static struct bindata *res_to_bin_group_icon
1283 PARAMS ((const struct group_icon *, int));
1284 static struct bindata *res_to_bin_menu
1285 PARAMS ((const struct menu *, int));
1286 static struct bindata *res_to_bin_menuitems
1287 PARAMS ((const struct menuitem *, int));
1288 static struct bindata *res_to_bin_menuexitems
1289 PARAMS ((const struct menuitem *, int));
1290 static struct bindata *res_to_bin_rcdata
1291 PARAMS ((const struct rcdata_item *, int));
1292 static struct bindata *res_to_bin_stringtable
1293 PARAMS ((const struct stringtable *, int));
1294 static struct bindata *string_to_unicode_bin PARAMS ((const char *, int));
1295 static struct bindata *res_to_bin_versioninfo
1296 PARAMS ((const struct versioninfo *, int));
1297 static struct bindata *res_to_bin_generic
1298 PARAMS ((unsigned long, const unsigned char *));
1300 /* Convert a resource to binary. */
1302 struct bindata *
1303 res_to_bin (res, big_endian)
1304 const struct res_resource *res;
1305 int big_endian;
1307 switch (res->type)
1309 default:
1310 abort ();
1311 case RES_TYPE_BITMAP:
1312 case RES_TYPE_FONT:
1313 case RES_TYPE_ICON:
1314 case RES_TYPE_MESSAGETABLE:
1315 return res_to_bin_generic (res->u.data.length, res->u.data.data);
1316 case RES_TYPE_ACCELERATOR:
1317 return res_to_bin_accelerator (res->u.acc, big_endian);
1318 case RES_TYPE_CURSOR:
1319 return res_to_bin_cursor (res->u.cursor, big_endian);
1320 case RES_TYPE_GROUP_CURSOR:
1321 return res_to_bin_group_cursor (res->u.group_cursor, big_endian);
1322 case RES_TYPE_DIALOG:
1323 return res_to_bin_dialog (res->u.dialog, big_endian);
1324 case RES_TYPE_FONTDIR:
1325 return res_to_bin_fontdir (res->u.fontdir, big_endian);
1326 case RES_TYPE_GROUP_ICON:
1327 return res_to_bin_group_icon (res->u.group_icon, big_endian);
1328 case RES_TYPE_MENU:
1329 return res_to_bin_menu (res->u.menu, big_endian);
1330 case RES_TYPE_RCDATA:
1331 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1332 case RES_TYPE_STRINGTABLE:
1333 return res_to_bin_stringtable (res->u.stringtable, big_endian);
1334 case RES_TYPE_USERDATA:
1335 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1336 case RES_TYPE_VERSIONINFO:
1337 return res_to_bin_versioninfo (res->u.versioninfo, big_endian);
1341 /* Align to a 32 bit boundary. PPP points to the of a list of bindata
1342 structures. LENGTH points to the length of the structures. If
1343 necessary, this adds a new bindata to bring length up to a 32 bit
1344 boundary. It updates *PPP and *LENGTH. */
1346 static void
1347 dword_align_bin (ppp, length)
1348 struct bindata ***ppp;
1349 unsigned long *length;
1351 int add;
1352 struct bindata *d;
1354 if ((*length & 3) == 0)
1355 return;
1357 add = 4 - (*length & 3);
1359 d = (struct bindata *) reswr_alloc (sizeof *d);
1360 d->length = add;
1361 d->data = (unsigned char *) reswr_alloc (add);
1362 memset (d->data, 0, add);
1364 d->next = NULL;
1365 **ppp = d;
1366 *ppp = &(**ppp)->next;
1368 *length += add;
1371 /* Convert a resource ID to binary. This always returns exactly one
1372 bindata structure. */
1374 static struct bindata *
1375 resid_to_bin (id, big_endian)
1376 struct res_id id;
1377 int big_endian;
1379 struct bindata *d;
1381 d = (struct bindata *) reswr_alloc (sizeof *d);
1383 if (! id.named)
1385 d->length = 4;
1386 d->data = (unsigned char *) reswr_alloc (4);
1387 put_16 (big_endian, 0xffff, d->data);
1388 put_16 (big_endian, id.u.id, d->data + 2);
1390 else
1392 int i;
1394 d->length = id.u.n.length * 2 + 2;
1395 d->data = (unsigned char *) reswr_alloc (d->length);
1396 for (i = 0; i < id.u.n.length; i++)
1397 put_16 (big_endian, id.u.n.name[i], d->data + i * 2);
1398 put_16 (big_endian, 0, d->data + i * 2);
1401 d->next = NULL;
1403 return d;
1406 /* Convert a null terminated unicode string to binary. This always
1407 returns exactly one bindata structure. */
1409 static struct bindata *
1410 unicode_to_bin (str, big_endian)
1411 const unichar *str;
1412 int big_endian;
1414 int len;
1415 struct bindata *d;
1417 len = 0;
1418 if (str != NULL)
1420 const unichar *s;
1422 for (s = str; *s != 0; s++)
1423 ++len;
1426 d = (struct bindata *) reswr_alloc (sizeof *d);
1427 d->length = len * 2 + 2;
1428 d->data = (unsigned char *) reswr_alloc (d->length);
1430 if (str == NULL)
1431 put_16 (big_endian, 0, d->data);
1432 else
1434 const unichar *s;
1435 int i;
1437 for (s = str, i = 0; *s != 0; s++, i++)
1438 put_16 (big_endian, *s, d->data + i * 2);
1439 put_16 (big_endian, 0, d->data + i * 2);
1442 d->next = NULL;
1444 return d;
1447 /* Convert an accelerator resource to binary. */
1449 static struct bindata *
1450 res_to_bin_accelerator (accelerators, big_endian)
1451 const struct accelerator *accelerators;
1452 int big_endian;
1454 struct bindata *first, **pp;
1455 const struct accelerator *a;
1457 first = NULL;
1458 pp = &first;
1460 for (a = accelerators; a != NULL; a = a->next)
1462 struct bindata *d;
1464 d = (struct bindata *) reswr_alloc (sizeof *d);
1465 d->length = 8;
1466 d->data = (unsigned char *) reswr_alloc (8);
1468 put_16 (big_endian,
1469 a->flags | (a->next != NULL ? 0 : ACC_LAST),
1470 d->data);
1471 put_16 (big_endian, a->key, d->data + 2);
1472 put_16 (big_endian, a->id, d->data + 4);
1473 put_16 (big_endian, 0, d->data + 8);
1475 d->next = NULL;
1476 *pp = d;
1477 pp = &d->next;
1480 return first;
1483 /* Convert a cursor resource to binary. */
1485 static struct bindata *
1486 res_to_bin_cursor (c, big_endian)
1487 const struct cursor *c;
1488 int big_endian;
1490 struct bindata *d;
1492 d = (struct bindata *) reswr_alloc (sizeof *d);
1493 d->length = 4;
1494 d->data = (unsigned char *) reswr_alloc (4);
1496 put_16 (big_endian, c->xhotspot, d->data);
1497 put_16 (big_endian, c->yhotspot, d->data + 2);
1499 d->next = (struct bindata *) reswr_alloc (sizeof *d);
1500 d->next->length = c->length;
1501 d->next->data = (unsigned char *) c->data;
1502 d->next->next = NULL;
1504 return d;
1507 /* Convert a group cursor resource to binary. */
1509 static struct bindata *
1510 res_to_bin_group_cursor (group_cursors, big_endian)
1511 const struct group_cursor *group_cursors;
1512 int big_endian;
1514 struct bindata *first, **pp;
1515 int c;
1516 const struct group_cursor *gc;
1518 first = (struct bindata *) reswr_alloc (sizeof *first);
1519 first->length = 6;
1520 first->data = (unsigned char *) reswr_alloc (6);
1522 put_16 (big_endian, 0, first->data);
1523 put_16 (big_endian, 2, first->data + 2);
1525 first->next = NULL;
1526 pp = &first->next;
1528 c = 0;
1529 for (gc = group_cursors; gc != NULL; gc = gc->next)
1531 struct bindata *d;
1533 ++c;
1535 d = (struct bindata *) reswr_alloc (sizeof *d);
1536 d->length = 14;
1537 d->data = (unsigned char *) reswr_alloc (14);
1539 put_16 (big_endian, gc->width, d->data);
1540 put_16 (big_endian, gc->height, d->data + 2);
1541 put_16 (big_endian, gc->planes, d->data + 4);
1542 put_16 (big_endian, gc->bits, d->data + 6);
1543 put_32 (big_endian, gc->bytes, d->data + 8);
1544 put_16 (big_endian, gc->index, d->data + 12);
1546 d->next = NULL;
1547 *pp = d;
1548 pp = &d->next;
1551 put_16 (big_endian, c, first->data + 4);
1553 return first;
1556 /* Convert a dialog resource to binary. */
1558 static struct bindata *
1559 res_to_bin_dialog (dialog, big_endian)
1560 const struct dialog *dialog;
1561 int big_endian;
1563 int dialogex;
1564 struct bindata *first, **pp;
1565 unsigned long length;
1566 int off, c;
1567 struct dialog_control *dc;
1569 dialogex = extended_dialog (dialog);
1571 first = (struct bindata *) reswr_alloc (sizeof *first);
1572 first->length = dialogex ? 26 : 18;
1573 first->data = (unsigned char *) reswr_alloc (first->length);
1575 length = first->length;
1577 if (! dialogex)
1579 put_32 (big_endian, dialog->style, first->data);
1580 put_32 (big_endian, dialog->exstyle, first->data + 4);
1581 off = 8;
1583 else
1585 put_16 (big_endian, 1, first->data);
1586 put_16 (big_endian, 0xffff, first->data + 2);
1588 if (dialog->ex == NULL)
1589 put_32 (big_endian, 0, first->data + 4);
1590 else
1591 put_32 (big_endian, dialog->ex->help, first->data + 4);
1592 put_32 (big_endian, dialog->exstyle, first->data + 8);
1593 put_32 (big_endian, dialog->style, first->data + 12);
1594 off = 16;
1597 put_16 (big_endian, dialog->x, first->data + off + 2);
1598 put_16 (big_endian, dialog->y, first->data + off + 4);
1599 put_16 (big_endian, dialog->width, first->data + off + 6);
1600 put_16 (big_endian, dialog->height, first->data + off + 8);
1602 pp = &first->next;
1604 *pp = resid_to_bin (dialog->menu, big_endian);
1605 length += (*pp)->length;
1606 pp = &(*pp)->next;
1608 *pp = resid_to_bin (dialog->class, big_endian);
1609 length += (*pp)->length;
1610 pp = &(*pp)->next;
1612 *pp = unicode_to_bin (dialog->caption, big_endian);
1613 length += (*pp)->length;
1614 pp = &(*pp)->next;
1616 if ((dialog->style & DS_SETFONT) != 0)
1618 struct bindata *d;
1620 d = (struct bindata *) reswr_alloc (sizeof *d);
1621 d->length = dialogex ? 6 : 2;
1622 d->data = (unsigned char *) reswr_alloc (d->length);
1624 length += d->length;
1626 put_16 (big_endian, dialog->pointsize, d->data);
1628 if (dialogex)
1630 if (dialog->ex == NULL)
1632 put_16 (big_endian, 0, d->data + 2);
1633 put_8 (0, d->data + 4);
1634 put_8 (1, d->data + 5);
1636 else
1638 put_16 (big_endian, dialog->ex->weight, d->data + 2);
1639 put_8 (dialog->ex->italic, d->data + 4);
1640 put_8 (dialog->ex->charset, d->data + 5);
1644 *pp = d;
1645 pp = &d->next;
1647 *pp = unicode_to_bin (dialog->font, big_endian);
1648 length += (*pp)->length;
1649 pp = &(*pp)->next;
1652 c = 0;
1653 for (dc = dialog->controls; dc != NULL; dc = dc->next)
1655 struct bindata *d;
1656 int dcoff;
1658 ++c;
1660 dword_align_bin (&pp, &length);
1662 d = (struct bindata *) reswr_alloc (sizeof *d);
1663 d->length = dialogex ? 24 : 18;
1664 d->data = (unsigned char *) reswr_alloc (d->length);
1666 length += d->length;
1668 if (! dialogex)
1670 put_32 (big_endian, dc->style, d->data);
1671 put_32 (big_endian, dc->exstyle, d->data + 4);
1672 dcoff = 8;
1674 else
1676 put_32 (big_endian, dc->help, d->data);
1677 put_32 (big_endian, dc->exstyle, d->data + 4);
1678 put_32 (big_endian, dc->style, d->data + 8);
1679 dcoff = 12;
1682 put_16 (big_endian, dc->x, d->data + dcoff);
1683 put_16 (big_endian, dc->y, d->data + dcoff + 2);
1684 put_16 (big_endian, dc->width, d->data + dcoff + 4);
1685 put_16 (big_endian, dc->height, d->data + dcoff + 6);
1687 if (dialogex)
1688 put_32 (big_endian, dc->id, d->data + dcoff + 8);
1689 else
1690 put_16 (big_endian, dc->id, d->data + dcoff + 8);
1692 *pp = d;
1693 pp = &d->next;
1695 *pp = resid_to_bin (dc->class, big_endian);
1696 length += (*pp)->length;
1697 pp = &(*pp)->next;
1699 *pp = resid_to_bin (dc->text, big_endian);
1700 length += (*pp)->length;
1701 pp = &(*pp)->next;
1703 d = (struct bindata *) reswr_alloc (sizeof *d);
1704 d->length = 2;
1705 d->data = (unsigned char *) reswr_alloc (2);
1707 length += 2;
1709 d->next = NULL;
1710 *pp = d;
1711 pp = &d->next;
1713 if (dc->data == NULL)
1714 put_16 (big_endian, 0, d->data);
1715 else
1717 unsigned long sublen;
1719 dword_align_bin (&pp, &length);
1721 *pp = res_to_bin_rcdata (dc->data, big_endian);
1722 sublen = 0;
1723 while (*pp != NULL)
1725 sublen += (*pp)->length;
1726 pp = &(*pp)->next;
1729 put_16 (big_endian, sublen, d->data);
1731 length += sublen;
1734 put_16 (big_endian, c, first->data + off);
1736 return first;
1739 /* Convert a fontdir resource to binary. */
1741 static struct bindata *
1742 res_to_bin_fontdir (fontdirs, big_endian)
1743 const struct fontdir *fontdirs;
1744 int big_endian;
1746 struct bindata *first, **pp;
1747 int c;
1748 const struct fontdir *fd;
1750 first = (struct bindata *) reswr_alloc (sizeof *first);
1751 first->length = 2;
1752 first->data = (unsigned char *) reswr_alloc (2);
1754 first->next = NULL;
1755 pp = &first->next;
1757 c = 0;
1758 for (fd = fontdirs; fd != NULL; fd = fd->next)
1760 struct bindata *d;
1762 ++c;
1764 d = (struct bindata *) reswr_alloc (sizeof *d);
1765 d->length = 2;
1766 d->data = (unsigned char *) reswr_alloc (2);
1768 put_16 (big_endian, fd->index, d->data);
1770 *pp = d;
1771 pp = &d->next;
1773 d = (struct bindata *) reswr_alloc (sizeof *d);
1774 d->length = fd->length;
1775 d->data = (unsigned char *) fd->data;
1777 d->next = NULL;
1778 *pp = d;
1779 pp = &d->next;
1782 put_16 (big_endian, c, first->data);
1784 return first;
1787 /* Convert a group icon resource to binary. */
1789 static struct bindata *
1790 res_to_bin_group_icon (group_icons, big_endian)
1791 const struct group_icon *group_icons;
1792 int big_endian;
1794 struct bindata *first, **pp;
1795 int c;
1796 const struct group_icon *gi;
1798 first = (struct bindata *) reswr_alloc (sizeof *first);
1799 first->length = 6;
1800 first->data = (unsigned char *) reswr_alloc (6);
1802 put_16 (big_endian, 0, first->data);
1803 put_16 (big_endian, 1, first->data + 2);
1805 first->next = NULL;
1806 pp = &first->next;
1808 c = 0;
1809 for (gi = group_icons; gi != NULL; gi = gi->next)
1811 struct bindata *d;
1813 ++c;
1815 d = (struct bindata *) reswr_alloc (sizeof *d);
1816 d->length = 14;
1817 d->data = (unsigned char *) reswr_alloc (14);
1819 d->data[0] = gi->width;
1820 d->data[1] = gi->height;
1821 d->data[2] = gi->colors;
1822 d->data[3] = 0;
1823 put_16 (big_endian, gi->planes, d->data + 4);
1824 put_16 (big_endian, gi->bits, d->data + 6);
1825 put_32 (big_endian, gi->bytes, d->data + 8);
1826 put_16 (big_endian, gi->index, d->data + 12);
1828 d->next = NULL;
1829 *pp = d;
1830 pp = &d->next;
1833 put_16 (big_endian, c, first->data + 4);
1835 return first;
1838 /* Convert a menu resource to binary. */
1840 static struct bindata *
1841 res_to_bin_menu (menu, big_endian)
1842 const struct menu *menu;
1843 int big_endian;
1845 int menuex;
1846 struct bindata *d;
1848 menuex = extended_menu (menu);
1850 d = (struct bindata *) reswr_alloc (sizeof *d);
1851 d->length = menuex ? 8 : 4;
1852 d->data = (unsigned char *) reswr_alloc (d->length);
1854 if (! menuex)
1856 put_16 (big_endian, 0, d->data);
1857 put_16 (big_endian, 0, d->data + 2);
1859 d->next = res_to_bin_menuitems (menu->items, big_endian);
1861 else
1863 put_16 (big_endian, 1, d->data);
1864 put_16 (big_endian, 4, d->data + 2);
1865 put_32 (big_endian, menu->help, d->data + 4);
1867 d->next = res_to_bin_menuexitems (menu->items, big_endian);
1870 return d;
1873 /* Convert menu items to binary. */
1875 static struct bindata *
1876 res_to_bin_menuitems (items, big_endian)
1877 const struct menuitem *items;
1878 int big_endian;
1880 struct bindata *first, **pp;
1881 const struct menuitem *mi;
1883 first = NULL;
1884 pp = &first;
1886 for (mi = items; mi != NULL; mi = mi->next)
1888 struct bindata *d;
1889 int flags;
1891 d = (struct bindata *) reswr_alloc (sizeof *d);
1892 d->length = mi->popup == NULL ? 4 : 2;
1893 d->data = (unsigned char *) reswr_alloc (d->length);
1895 flags = mi->type;
1896 if (mi->next == NULL)
1897 flags |= MENUITEM_ENDMENU;
1898 if (mi->popup != NULL)
1899 flags |= MENUITEM_POPUP;
1901 put_16 (big_endian, flags, d->data);
1903 if (mi->popup == NULL)
1904 put_16 (big_endian, mi->id, d->data + 2);
1906 *pp = d;
1907 pp = &d->next;
1909 *pp = unicode_to_bin (mi->text, big_endian);
1910 pp = &(*pp)->next;
1912 if (mi->popup != NULL)
1914 *pp = res_to_bin_menuitems (mi->popup, big_endian);
1915 while (*pp != NULL)
1916 pp = &(*pp)->next;
1920 return first;
1923 /* Convert menuex items to binary. */
1925 static struct bindata *
1926 res_to_bin_menuexitems (items, big_endian)
1927 const struct menuitem *items;
1928 int big_endian;
1930 struct bindata *first, **pp;
1931 unsigned long length;
1932 const struct menuitem *mi;
1934 first = NULL;
1935 pp = &first;
1937 length = 0;
1939 for (mi = items; mi != NULL; mi = mi->next)
1941 struct bindata *d;
1942 int flags;
1944 dword_align_bin (&pp, &length);
1946 d = (struct bindata *) reswr_alloc (sizeof *d);
1947 d->length = 12;
1948 d->data = (unsigned char *) reswr_alloc (12);
1950 length += 12;
1952 put_32 (big_endian, mi->type, d->data);
1953 put_32 (big_endian, mi->state, d->data + 4);
1954 put_16 (big_endian, mi->id, d->data + 8);
1956 flags = 0;
1957 if (mi->next == NULL)
1958 flags |= 0x80;
1959 if (mi->popup != NULL)
1960 flags |= 1;
1961 put_16 (big_endian, flags, d->data + 10);
1963 *pp = d;
1964 pp = &d->next;
1966 *pp = unicode_to_bin (mi->text, big_endian);
1967 length += (*pp)->length;
1968 pp = &(*pp)->next;
1970 if (mi->popup != NULL)
1972 dword_align_bin (&pp, &length);
1974 d = (struct bindata *) reswr_alloc (sizeof *d);
1975 d->length = 4;
1976 d->data = (unsigned char *) reswr_alloc (4);
1978 put_32 (big_endian, mi->help, d->data);
1980 *pp = d;
1981 pp = &d->next;
1983 *pp = res_to_bin_menuexitems (mi->popup, big_endian);
1984 while (*pp != NULL)
1986 length += (*pp)->length;
1987 pp = &(*pp)->next;
1992 return first;
1995 /* Convert an rcdata resource to binary. This is also used to convert
1996 other information which happens to be stored in rcdata_item lists
1997 to binary. */
1999 static struct bindata *
2000 res_to_bin_rcdata (items, big_endian)
2001 const struct rcdata_item *items;
2002 int big_endian;
2004 struct bindata *first, **pp;
2005 const struct rcdata_item *ri;
2007 first = NULL;
2008 pp = &first;
2010 for (ri = items; ri != NULL; ri = ri->next)
2012 struct bindata *d;
2014 d = (struct bindata *) reswr_alloc (sizeof *d);
2016 switch (ri->type)
2018 default:
2019 abort ();
2021 case RCDATA_WORD:
2022 d->length = 2;
2023 d->data = (unsigned char *) reswr_alloc (2);
2024 put_16 (big_endian, ri->u.word, d->data);
2025 break;
2027 case RCDATA_DWORD:
2028 d->length = 4;
2029 d->data = (unsigned char *) reswr_alloc (4);
2030 put_32 (big_endian, ri->u.dword, d->data);
2031 break;
2033 case RCDATA_STRING:
2034 d->length = ri->u.string.length;
2035 d->data = (unsigned char *) ri->u.string.s;
2036 break;
2038 case RCDATA_WSTRING:
2040 unsigned long i;
2042 d->length = ri->u.wstring.length * 2;
2043 d->data = (unsigned char *) reswr_alloc (d->length);
2044 for (i = 0; i < ri->u.wstring.length; i++)
2045 put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2);
2046 break;
2049 case RCDATA_BUFFER:
2050 d->length = ri->u.buffer.length;
2051 d->data = (unsigned char *) ri->u.buffer.data;
2052 break;
2055 d->next = NULL;
2056 *pp = d;
2057 pp = &d->next;
2060 return first;
2063 /* Convert a stringtable resource to binary. */
2065 static struct bindata *
2066 res_to_bin_stringtable (st, big_endian)
2067 const struct stringtable *st;
2068 int big_endian;
2070 struct bindata *first, **pp;
2071 int i;
2073 first = NULL;
2074 pp = &first;
2076 for (i = 0; i < 16; i++)
2078 int slen, j;
2079 struct bindata *d;
2080 unichar *s;
2082 slen = st->strings[i].length;
2083 s = st->strings[i].string;
2085 d = (struct bindata *) reswr_alloc (sizeof *d);
2086 d->length = 2 + slen * 2;
2087 d->data = (unsigned char *) reswr_alloc (d->length);
2089 put_16 (big_endian, slen, d->data);
2091 for (j = 0; j < slen; j++)
2092 put_16 (big_endian, s[j], d->data + 2 + j * 2);
2094 d->next = NULL;
2095 *pp = d;
2096 pp = &d->next;
2099 return first;
2102 /* Convert an ASCII string to a unicode binary string. This always
2103 returns exactly one bindata structure. */
2105 static struct bindata *
2106 string_to_unicode_bin (s, big_endian)
2107 const char *s;
2108 int big_endian;
2110 size_t len, i;
2111 struct bindata *d;
2113 len = strlen (s);
2115 d = (struct bindata *) reswr_alloc (sizeof *d);
2116 d->length = len * 2 + 2;
2117 d->data = (unsigned char *) reswr_alloc (d->length);
2119 for (i = 0; i < len; i++)
2120 put_16 (big_endian, s[i], d->data + i * 2);
2121 put_16 (big_endian, 0, d->data + i * 2);
2123 d->next = NULL;
2125 return d;
2128 /* Convert a versioninfo resource to binary. */
2130 static struct bindata *
2131 res_to_bin_versioninfo (versioninfo, big_endian)
2132 const struct versioninfo *versioninfo;
2133 int big_endian;
2135 struct bindata *first, **pp;
2136 unsigned long length;
2137 struct ver_info *vi;
2139 first = (struct bindata *) reswr_alloc (sizeof *first);
2140 first->length = 6;
2141 first->data = (unsigned char *) reswr_alloc (6);
2143 length = 6;
2145 if (versioninfo->fixed == NULL)
2146 put_16 (big_endian, 0, first->data + 2);
2147 else
2148 put_16 (big_endian, 52, first->data + 2);
2150 put_16 (big_endian, 0, first->data + 4);
2152 pp = &first->next;
2154 *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian);
2155 length += (*pp)->length;
2156 pp = &(*pp)->next;
2158 dword_align_bin (&pp, &length);
2160 if (versioninfo->fixed != NULL)
2162 const struct fixed_versioninfo *fi;
2163 struct bindata *d;
2165 d = (struct bindata *) reswr_alloc (sizeof *d);
2166 d->length = 52;
2167 d->data = (unsigned char *) reswr_alloc (52);
2169 length += 52;
2171 fi = versioninfo->fixed;
2173 put_32 (big_endian, 0xfeef04bd, d->data);
2174 put_32 (big_endian, 0x10000, d->data + 4);
2175 put_32 (big_endian, fi->file_version_ms, d->data + 8);
2176 put_32 (big_endian, fi->file_version_ls, d->data + 12);
2177 put_32 (big_endian, fi->product_version_ms, d->data + 16);
2178 put_32 (big_endian, fi->product_version_ls, d->data + 20);
2179 put_32 (big_endian, fi->file_flags_mask, d->data + 24);
2180 put_32 (big_endian, fi->file_flags, d->data + 28);
2181 put_32 (big_endian, fi->file_os, d->data + 32);
2182 put_32 (big_endian, fi->file_type, d->data + 36);
2183 put_32 (big_endian, fi->file_subtype, d->data + 40);
2184 put_32 (big_endian, fi->file_date_ms, d->data + 44);
2185 put_32 (big_endian, fi->file_date_ls, d->data + 48);
2187 d->next = NULL;
2188 *pp = d;
2189 pp = &d->next;
2192 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2194 struct bindata *vid;
2195 unsigned long vilen;
2197 dword_align_bin (&pp, &length);
2199 vid = (struct bindata *) reswr_alloc (sizeof *vid);
2200 vid->length = 6;
2201 vid->data = (unsigned char *) reswr_alloc (6);
2203 length += 6;
2204 vilen = 6;
2206 put_16 (big_endian, 0, vid->data + 2);
2207 put_16 (big_endian, 0, vid->data + 4);
2209 *pp = vid;
2210 pp = &vid->next;
2212 switch (vi->type)
2214 default:
2215 abort ();
2217 case VERINFO_STRING:
2219 unsigned long hold, vslen;
2220 struct bindata *vsd;
2221 const struct ver_stringinfo *vs;
2223 *pp = string_to_unicode_bin ("StringFileInfo", big_endian);
2224 length += (*pp)->length;
2225 vilen += (*pp)->length;
2226 pp = &(*pp)->next;
2228 hold = length;
2229 dword_align_bin (&pp, &length);
2230 vilen += length - hold;
2232 vsd = (struct bindata *) reswr_alloc (sizeof *vsd);
2233 vsd->length = 6;
2234 vsd->data = (unsigned char *) reswr_alloc (6);
2236 length += 6;
2237 vilen += 6;
2238 vslen = 6;
2240 put_16 (big_endian, 0, vsd->data + 2);
2241 put_16 (big_endian, 0, vsd->data + 4);
2243 *pp = vsd;
2244 pp = &vsd->next;
2246 *pp = unicode_to_bin (vi->u.string.language, big_endian);
2247 length += (*pp)->length;
2248 vilen += (*pp)->length;
2249 vslen += (*pp)->length;
2250 pp = &(*pp)->next;
2252 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2254 struct bindata *vssd;
2255 unsigned long vsslen;
2257 hold = length;
2258 dword_align_bin (&pp, &length);
2259 vilen += length - hold;
2260 vslen += length - hold;
2262 vssd = (struct bindata *) reswr_alloc (sizeof *vssd);
2263 vssd->length = 6;
2264 vssd->data = (unsigned char *) reswr_alloc (6);
2266 length += 6;
2267 vilen += 6;
2268 vslen += 6;
2269 vsslen = 6;
2271 put_16 (big_endian, 1, vssd->data + 4);
2273 *pp = vssd;
2274 pp = &vssd->next;
2276 *pp = unicode_to_bin (vs->key, big_endian);
2277 length += (*pp)->length;
2278 vilen += (*pp)->length;
2279 vslen += (*pp)->length;
2280 vsslen += (*pp)->length;
2281 pp = &(*pp)->next;
2283 hold = length;
2284 dword_align_bin (&pp, &length);
2285 vilen += length - hold;
2286 vslen += length - hold;
2287 vsslen += length - hold;
2289 *pp = unicode_to_bin (vs->value, big_endian);
2290 put_16 (big_endian, (*pp)->length / 2, vssd->data + 2);
2291 length += (*pp)->length;
2292 vilen += (*pp)->length;
2293 vslen += (*pp)->length;
2294 vsslen += (*pp)->length;
2295 pp = &(*pp)->next;
2297 put_16 (big_endian, vsslen, vssd->data);
2300 put_16 (big_endian, vslen, vsd->data);
2302 break;
2305 case VERINFO_VAR:
2307 unsigned long hold, vvlen, vvvlen;
2308 struct bindata *vvd;
2309 const struct ver_varinfo *vv;
2311 *pp = string_to_unicode_bin ("VarFileInfo", big_endian);
2312 length += (*pp)->length;
2313 vilen += (*pp)->length;
2314 pp = &(*pp)->next;
2316 hold = length;
2317 dword_align_bin (&pp, &length);
2318 vilen += length - hold;
2320 vvd = (struct bindata *) reswr_alloc (sizeof *vvd);
2321 vvd->length = 6;
2322 vvd->data = (unsigned char *) reswr_alloc (6);
2324 length += 6;
2325 vilen += 6;
2326 vvlen = 6;
2328 put_16 (big_endian, 0, vvd->data + 4);
2330 *pp = vvd;
2331 pp = &vvd->next;
2333 *pp = unicode_to_bin (vi->u.var.key, big_endian);
2334 length += (*pp)->length;
2335 vilen += (*pp)->length;
2336 vvlen += (*pp)->length;
2337 pp = &(*pp)->next;
2339 hold = length;
2340 dword_align_bin (&pp, &length);
2341 vilen += length - hold;
2342 vvlen += length - hold;
2344 vvvlen = 0;
2346 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2348 struct bindata *vvsd;
2350 vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd);
2351 vvsd->length = 4;
2352 vvsd->data = (unsigned char *) reswr_alloc (4);
2354 length += 4;
2355 vilen += 4;
2356 vvlen += 4;
2357 vvvlen += 4;
2359 put_16 (big_endian, vv->language, vvsd->data);
2360 put_16 (big_endian, vv->charset, vvsd->data + 2);
2362 vvsd->next = NULL;
2363 *pp = vvsd;
2364 pp = &vvsd->next;
2367 put_16 (big_endian, vvlen, vvd->data);
2368 put_16 (big_endian, vvvlen, vvd->data + 2);
2370 break;
2374 put_16 (big_endian, vilen, vid->data);
2377 put_16 (big_endian, length, first->data);
2379 return first;
2382 /* Convert a generic resource to binary. */
2384 static struct bindata *
2385 res_to_bin_generic (length, data)
2386 unsigned long length;
2387 const unsigned char *data;
2389 struct bindata *d;
2391 d = (struct bindata *) reswr_alloc (sizeof *d);
2392 d->length = length;
2393 d->data = (unsigned char *) data;
2395 d->next = NULL;
2397 return d;