1999-09-11 Donn Terry <donn@interix.com>
[binutils.git] / binutils / resbin.c
blob8fc07fbb29253928b7aad22c7252dc7fdcb62b6c
1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright 1997, 1998 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_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s))
34 #define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s))
36 /* Local functions. */
38 static void toosmall PARAMS ((const char *));
39 static unichar *get_unicode
40 PARAMS ((const unsigned char *, unsigned long, int, int *));
41 static int get_resid
42 PARAMS ((struct res_id *, const unsigned char *, unsigned long, int));
43 static struct res_resource *bin_to_res_generic
44 PARAMS ((enum res_type, const unsigned char *, unsigned long));
45 static struct res_resource *bin_to_res_cursor
46 PARAMS ((const unsigned char *, unsigned long, int));
47 static struct res_resource *bin_to_res_menu
48 PARAMS ((const unsigned char *, unsigned long, int));
49 static struct menuitem *bin_to_res_menuitems
50 PARAMS ((const unsigned char *, unsigned long, int, int *));
51 static struct menuitem *bin_to_res_menuexitems
52 PARAMS ((const unsigned char *, unsigned long, int, int *));
53 static struct res_resource *bin_to_res_dialog
54 PARAMS ((const unsigned char *, unsigned long, int));
55 static struct res_resource *bin_to_res_string
56 PARAMS ((const unsigned char *, unsigned long, int));
57 static struct res_resource *bin_to_res_fontdir
58 PARAMS ((const unsigned char *, unsigned long, int));
59 static struct res_resource *bin_to_res_accelerators
60 PARAMS ((const unsigned char *, unsigned long, int));
61 static struct res_resource *bin_to_res_rcdata
62 PARAMS ((const unsigned char *, unsigned long, int));
63 static struct res_resource *bin_to_res_group_cursor
64 PARAMS ((const unsigned char *, unsigned long, int));
65 static struct res_resource *bin_to_res_group_icon
66 PARAMS ((const unsigned char *, unsigned long, int));
67 static struct res_resource *bin_to_res_version
68 PARAMS ((const unsigned char *, unsigned long, int));
69 static struct res_resource *bin_to_res_userdata
70 PARAMS ((const unsigned char *, unsigned long, int));
72 /* Given a resource type ID, a pointer to data, a length, return a
73 res_resource structure which represents that resource. The caller
74 is responsible for initializing the res_info and coff_info fields
75 of the returned structure. */
77 struct res_resource *
78 bin_to_res (type, data, length, big_endian)
79 struct res_id type;
80 const unsigned char *data;
81 unsigned long length;
82 int big_endian;
84 if (type.named)
85 return bin_to_res_userdata (data, length, big_endian);
86 else
88 switch (type.u.id)
90 default:
91 return bin_to_res_userdata (data, length, big_endian);
92 case RT_CURSOR:
93 return bin_to_res_cursor (data, length, big_endian);
94 case RT_BITMAP:
95 return bin_to_res_generic (RES_TYPE_BITMAP, data, length);
96 case RT_ICON:
97 return bin_to_res_generic (RES_TYPE_ICON, data, length);
98 case RT_MENU:
99 return bin_to_res_menu (data, length, big_endian);
100 case RT_DIALOG:
101 return bin_to_res_dialog (data, length, big_endian);
102 case RT_STRING:
103 return bin_to_res_string (data, length, big_endian);
104 case RT_FONTDIR:
105 return bin_to_res_fontdir (data, length, big_endian);
106 case RT_FONT:
107 return bin_to_res_generic (RES_TYPE_FONT, data, length);
108 case RT_ACCELERATOR:
109 return bin_to_res_accelerators (data, length, big_endian);
110 case RT_RCDATA:
111 return bin_to_res_rcdata (data, length, big_endian);
112 case RT_MESSAGETABLE:
113 return bin_to_res_generic (RES_TYPE_MESSAGETABLE, data, length);
114 case RT_GROUP_CURSOR:
115 return bin_to_res_group_cursor (data, length, big_endian);
116 case RT_GROUP_ICON:
117 return bin_to_res_group_icon (data, length, big_endian);
118 case RT_VERSION:
119 return bin_to_res_version (data, length, big_endian);
124 /* Give an error if the binary data is too small. */
126 static void
127 toosmall (msg)
128 const char *msg;
130 fatal (_("%s: not enough binary data"), msg);
133 /* Swap in a NULL terminated unicode string. */
135 static unichar *
136 get_unicode (data, length, big_endian, retlen)
137 const unsigned char *data;
138 unsigned long length;
139 int big_endian;
140 int *retlen;
142 int c, i;
143 unichar *ret;
145 c = 0;
146 while (1)
148 if (length < (unsigned long) c * 2 + 2)
149 toosmall (_("null terminated unicode string"));
150 if (get_16 (big_endian, data + c * 2) == 0)
151 break;
152 ++c;
155 ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
157 for (i = 0; i < c; i++)
158 ret[i] = get_16 (big_endian, data + i * 2);
159 ret[i] = 0;
161 if (retlen != NULL)
162 *retlen = c;
164 return ret;
167 /* Get a resource identifier. This returns the number of bytes used. */
169 static int
170 get_resid (id, data, length, big_endian)
171 struct res_id *id;
172 const unsigned char *data;
173 unsigned long length;
174 int big_endian;
176 int first;
178 if (length < 2)
179 toosmall (_("resource ID"));
181 first = get_16 (big_endian, data);
182 if (first == 0xffff)
184 if (length < 4)
185 toosmall (_("resource ID"));
186 id->named = 0;
187 id->u.id = get_16 (big_endian, data + 2);
188 return 4;
190 else
192 id->named = 1;
193 id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length);
194 return id->u.n.length * 2 + 2;
198 /* Convert a resource which just stores uninterpreted data from
199 binary. */
201 struct res_resource *
202 bin_to_res_generic (type, data, length)
203 enum res_type type;
204 const unsigned char *data;
205 unsigned long length;
207 struct res_resource *r;
209 r = (struct res_resource *) res_alloc (sizeof *r);
210 r->type = type;
211 r->u.data.data = data;
212 r->u.data.length = length;
214 return r;
217 /* Convert a cursor resource from binary. */
219 struct res_resource *
220 bin_to_res_cursor (data, length, big_endian)
221 const unsigned char *data;
222 unsigned long length;
223 int big_endian;
225 struct cursor *c;
226 struct res_resource *r;
228 if (length < 4)
229 toosmall (_("cursor"));
231 c = (struct cursor *) res_alloc (sizeof *c);
232 c->xhotspot = get_16 (big_endian, data);
233 c->yhotspot = get_16 (big_endian, data + 2);
234 c->length = length - 4;
235 c->data = data + 4;
237 r = (struct res_resource *) res_alloc (sizeof *r);
238 r->type = RES_TYPE_CURSOR;
239 r->u.cursor = c;
241 return r;
244 /* Convert a menu resource from binary. */
246 struct res_resource *
247 bin_to_res_menu (data, length, big_endian)
248 const unsigned char *data;
249 unsigned long length;
250 int big_endian;
252 struct res_resource *r;
253 struct menu *m;
254 int version, read;
256 r = (struct res_resource *) res_alloc (sizeof *r);
257 r->type = RES_TYPE_MENU;
259 m = (struct menu *) res_alloc (sizeof *m);
260 r->u.menu = m;
262 if (length < 2)
263 toosmall (_("menu header"));
265 version = get_16 (big_endian, data);
267 if (version == 0)
269 if (length < 4)
270 toosmall (_("menu header"));
271 m->help = 0;
272 m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian,
273 &read);
275 else if (version == 1)
277 unsigned int offset;
279 if (length < 8)
280 toosmall (_("menuex header"));
281 m->help = get_32 (big_endian, data + 4);
282 offset = get_16 (big_endian, data + 2);
283 if (offset + 4 >= length)
284 toosmall (_("menuex offset"));
285 m->items = bin_to_res_menuexitems (data + 4 + offset,
286 length - (4 + offset),
287 big_endian,
288 &read);
290 else
291 fatal (_("unsupported menu version %d"), version);
293 return r;
296 /* Convert menu items from binary. */
298 static struct menuitem *
299 bin_to_res_menuitems (data, length, big_endian, read)
300 const unsigned char *data;
301 unsigned long length;
302 int big_endian;
303 int *read;
305 struct menuitem *first, **pp;
307 first = NULL;
308 pp = &first;
310 *read = 0;
312 while (length > 0)
314 int flags, slen, itemlen;
315 unsigned int stroff;
316 struct menuitem *mi;
318 if (length < 4)
319 toosmall (_("menuitem header"));
321 mi = (struct menuitem *) res_alloc (sizeof *mi);
322 mi->state = 0;
323 mi->help = 0;
325 flags = get_16 (big_endian, data);
326 mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
328 if ((flags & MENUITEM_POPUP) == 0)
329 stroff = 4;
330 else
331 stroff = 2;
333 if (length < stroff + 2)
334 toosmall (_("menuitem header"));
336 if (get_16 (big_endian, data + stroff) == 0)
338 slen = 0;
339 mi->text = NULL;
341 else
342 mi->text = get_unicode (data + stroff, length - stroff, big_endian,
343 &slen);
345 itemlen = stroff + slen * 2 + 2;
347 if ((flags & MENUITEM_POPUP) == 0)
349 mi->popup = NULL;
350 mi->id = get_16 (big_endian, data + 2);
352 else
354 int subread;
356 mi->id = 0;
357 mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen,
358 big_endian, &subread);
359 itemlen += subread;
362 mi->next = NULL;
363 *pp = mi;
364 pp = &mi->next;
366 data += itemlen;
367 length -= itemlen;
368 *read += itemlen;
370 if ((flags & MENUITEM_ENDMENU) != 0)
371 return first;
374 return first;
377 /* Convert menuex items from binary. */
379 static struct menuitem *
380 bin_to_res_menuexitems (data, length, big_endian, read)
381 const unsigned char *data;
382 unsigned long length;
383 int big_endian;
384 int *read;
386 struct menuitem *first, **pp;
388 first = NULL;
389 pp = &first;
391 *read = 0;
393 while (length > 0)
395 int flags, slen;
396 unsigned int itemlen;
397 struct menuitem *mi;
399 if (length < 14)
400 toosmall (_("menuitem header"));
402 mi = (struct menuitem *) res_alloc (sizeof *mi);
403 mi->type = get_32 (big_endian, data);
404 mi->state = get_32 (big_endian, data + 4);
405 mi->id = get_16 (big_endian, data + 8);
407 flags = get_16 (big_endian, data + 10);
409 if (get_16 (big_endian, data + 12) == 0)
411 slen = 0;
412 mi->text = NULL;
414 else
415 mi->text = get_unicode (data + 12, length - 12, big_endian, &slen);
417 itemlen = 12 + slen * 2 + 2;
418 itemlen = (itemlen + 3) &~ 3;
420 if ((flags & 1) == 0)
422 mi->popup = NULL;
423 mi->help = 0;
425 else
427 int subread;
429 if (length < itemlen + 4)
430 toosmall (_("menuitem"));
431 mi->help = get_32 (big_endian, data + itemlen);
432 itemlen += 4;
434 mi->popup = bin_to_res_menuexitems (data + itemlen,
435 length - itemlen,
436 big_endian, &subread);
437 itemlen += subread;
440 mi->next = NULL;
441 *pp = mi;
442 pp = &mi->next;
444 data += itemlen;
445 length -= itemlen;
446 *read += itemlen;
448 if ((flags & 0x80) != 0)
449 return first;
452 return first;
455 /* Convert a dialog resource from binary. */
457 static struct res_resource *
458 bin_to_res_dialog (data, length, big_endian)
459 const unsigned char *data;
460 unsigned long length;
461 int big_endian;
463 int version;
464 struct dialog *d;
465 int c, sublen, i;
466 unsigned int off;
467 struct dialog_control **pp;
468 struct res_resource *r;
470 if (length < 18)
471 toosmall (_("dialog header"));
473 d = (struct dialog *) res_alloc (sizeof *d);
475 version = get_16 (big_endian, data);
476 if (version != 1)
478 d->ex = NULL;
479 d->style = get_32 (big_endian, data);
480 d->exstyle = get_32 (big_endian, data + 4);
481 off = 8;
483 else
485 int signature;
487 signature = get_16 (big_endian, data + 2);
488 if (signature != 0xffff)
489 fatal (_("unexpected dialog signature %d"), signature);
491 d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex));
492 d->ex->help = get_32 (big_endian, data + 4);
493 d->exstyle = get_32 (big_endian, data + 8);
494 d->style = get_32 (big_endian, data + 12);
495 off = 16;
498 if (length < off + 10)
499 toosmall (_("dialog header"));
501 c = get_16 (big_endian, data + off);
502 d->x = get_16 (big_endian, data + off + 2);
503 d->y = get_16 (big_endian, data + off + 4);
504 d->width = get_16 (big_endian, data + off + 6);
505 d->height = get_16 (big_endian, data + off + 8);
507 off += 10;
509 sublen = get_resid (&d->menu, data + off, length - off, big_endian);
510 off += sublen;
512 sublen = get_resid (&d->class, data + off, length - off, big_endian);
513 off += sublen;
515 d->caption = get_unicode (data + off, length - off, big_endian, &sublen);
516 off += sublen * 2 + 2;
518 if ((d->style & DS_SETFONT) == 0)
520 d->pointsize = 0;
521 d->font = NULL;
522 if (d->ex != NULL)
524 d->ex->weight = 0;
525 d->ex->italic = 0;
528 else
530 if (length < off + 2)
531 toosmall (_("dialog font point size"));
533 d->pointsize = get_16 (big_endian, data + off);
534 off += 2;
536 if (d->ex != NULL)
538 if (length < off + 4)
539 toosmall (_("dialogex font information"));
540 d->ex->weight = get_16 (big_endian, data + off);
541 d->ex->italic = get_16 (big_endian, data + off + 2);
542 off += 4;
545 d->font = get_unicode (data + off, length - off, big_endian, &sublen);
546 off += sublen * 2 + 2;
549 d->controls = NULL;
550 pp = &d->controls;
552 for (i = 0; i < c; i++)
554 struct dialog_control *dc;
555 int datalen;
557 off = (off + 3) &~ 3;
559 dc = (struct dialog_control *) res_alloc (sizeof *dc);
561 if (d->ex == NULL)
563 if (length < off + 8)
564 toosmall (_("dialog control"));
566 dc->style = get_32 (big_endian, data + off);
567 dc->exstyle = get_32 (big_endian, data + off + 4);
568 dc->help = 0;
569 off += 8;
571 else
573 if (length < off + 12)
574 toosmall (_("dialogex control"));
575 dc->help = get_32 (big_endian, data + off);
576 dc->exstyle = get_32 (big_endian, data + off + 4);
577 dc->style = get_32 (big_endian, data + off + 8);
578 off += 12;
581 if (length < off + 10)
582 toosmall (_("dialog control"));
584 dc->x = get_16 (big_endian, data + off);
585 dc->y = get_16 (big_endian, data + off + 2);
586 dc->width = get_16 (big_endian, data + off + 4);
587 dc->height = get_16 (big_endian, data + off + 6);
589 if (d->ex != NULL)
590 dc->id = get_32 (big_endian, data + off + 8);
591 else
592 dc->id = get_16 (big_endian, data + off + 8);
594 off += 10 + (d->ex != NULL ? 2 : 0);
596 sublen = get_resid (&dc->class, data + off, length - off, big_endian);
597 off += sublen;
599 sublen = get_resid (&dc->text, data + off, length - off, big_endian);
600 off += sublen;
602 if (length < off + 2)
603 toosmall (_("dialog control end"));
605 datalen = get_16 (big_endian, data + off);
606 off += 2;
608 if (datalen == 0)
609 dc->data = NULL;
610 else
612 off = (off + 3) &~ 3;
614 if (length < off + datalen)
615 toosmall (_("dialog control data"));
617 dc->data = ((struct rcdata_item *)
618 res_alloc (sizeof (struct rcdata_item)));
619 dc->data->next = NULL;
620 dc->data->type = RCDATA_BUFFER;
621 dc->data->u.buffer.length = datalen;
622 dc->data->u.buffer.data = data + off;
624 off += datalen;
627 dc->next = NULL;
628 *pp = dc;
629 pp = &dc->next;
632 r = (struct res_resource *) res_alloc (sizeof *r);
633 r->type = RES_TYPE_DIALOG;
634 r->u.dialog = d;
636 return r;
639 /* Convert a stringtable resource from binary. */
641 static struct res_resource *
642 bin_to_res_string (data, length, big_endian)
643 const unsigned char *data;
644 unsigned long length;
645 int big_endian;
647 struct stringtable *st;
648 int i;
649 struct res_resource *r;
651 st = (struct stringtable *) res_alloc (sizeof *st);
653 for (i = 0; i < 16; i++)
655 unsigned int slen;
657 if (length < 2)
658 toosmall (_("stringtable string length"));
659 slen = get_16 (big_endian, data);
660 st->strings[i].length = slen;
662 if (slen > 0)
664 unichar *s;
665 unsigned int j;
667 if (length < 2 + 2 * slen)
668 toosmall (_("stringtable string"));
670 s = (unichar *) res_alloc (slen * sizeof (unichar));
671 st->strings[i].string = s;
673 for (j = 0; j < slen; j++)
674 s[j] = get_16 (big_endian, data + 2 + j * 2);
677 data += 2 + 2 * slen;
678 length -= 2 + 2 * slen;
681 r = (struct res_resource *) res_alloc (sizeof *r);
682 r->type = RES_TYPE_STRINGTABLE;
683 r->u.stringtable = st;
685 return r;
688 /* Convert a fontdir resource from binary. */
690 static struct res_resource *
691 bin_to_res_fontdir (data, length, big_endian)
692 const unsigned char *data;
693 unsigned long length;
694 int big_endian;
696 int c, i;
697 struct fontdir *first, **pp;
698 struct res_resource *r;
700 if (length < 2)
701 toosmall (_("fontdir header"));
703 c = get_16 (big_endian, data);
705 first = NULL;
706 pp = &first;
708 for (i = 0; i < c; i++)
710 struct fontdir *fd;
711 unsigned int off;
713 if (length < 56)
714 toosmall (_("fontdir"));
716 fd = (struct fontdir *) res_alloc (sizeof *fd);
717 fd->index = get_16 (big_endian, data);
719 /* To work out the length of the fontdir data, we must get the
720 length of the device name and face name strings, even though
721 we don't store them in the fontdir structure. The
722 documentation says that these are NULL terminated char
723 strings, not Unicode strings. */
725 off = 56;
727 while (off < length && data[off] != '\0')
728 ++off;
729 if (off >= length)
730 toosmall (_("fontdir device name"));
731 ++off;
733 while (off < length && data[off] != '\0')
734 ++off;
735 if (off >= length)
736 toosmall (_("fontdir face name"));
737 ++off;
739 fd->length = off;
740 fd->data = data;
742 fd->next = NULL;
743 *pp = fd;
744 pp = &fd->next;
746 /* The documentation does not indicate that any rounding is
747 required. */
749 data += off;
750 length -= off;
753 r = (struct res_resource *) res_alloc (sizeof *r);
754 r->type = RES_TYPE_FONTDIR;
755 r->u.fontdir = first;
757 return r;
760 /* Convert an accelerators resource from binary. */
762 static struct res_resource *
763 bin_to_res_accelerators (data, length, big_endian)
764 const unsigned char *data;
765 unsigned long length;
766 int big_endian;
768 struct accelerator *first, **pp;
769 struct res_resource *r;
771 first = NULL;
772 pp = &first;
774 while (1)
776 struct accelerator *a;
778 if (length < 8)
779 toosmall (_("accelerator"));
781 a = (struct accelerator *) res_alloc (sizeof *a);
783 a->flags = get_16 (big_endian, data);
784 a->key = get_16 (big_endian, data + 2);
785 a->id = get_16 (big_endian, data + 4);
787 a->next = NULL;
788 *pp = a;
789 pp = &a->next;
791 if ((a->flags & ACC_LAST) != 0)
792 break;
794 data += 8;
795 length -= 8;
798 r = (struct res_resource *) res_alloc (sizeof *r);
799 r->type = RES_TYPE_ACCELERATOR;
800 r->u.acc = first;
802 return r;
805 /* Convert an rcdata resource from binary. */
807 static struct res_resource *
808 bin_to_res_rcdata (data, length, big_endian)
809 const unsigned char *data;
810 unsigned long length;
811 int big_endian;
813 struct rcdata_item *ri;
814 struct res_resource *r;
816 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
818 ri->next = NULL;
819 ri->type = RCDATA_BUFFER;
820 ri->u.buffer.length = length;
821 ri->u.buffer.data = data;
823 r = (struct res_resource *) res_alloc (sizeof *r);
824 r->type = RES_TYPE_RCDATA;
825 r->u.rcdata = ri;
827 return r;
830 /* Convert a group cursor resource from binary. */
832 static struct res_resource *
833 bin_to_res_group_cursor (data, length, big_endian)
834 const unsigned char *data;
835 unsigned long length;
836 int big_endian;
838 int type, c, i;
839 struct group_cursor *first, **pp;
840 struct res_resource *r;
842 if (length < 6)
843 toosmall (_("group cursor header"));
845 type = get_16 (big_endian, data + 2);
846 if (type != 2)
847 fatal (_("unexpected group cursor type %d"), type);
849 c = get_16 (big_endian, data + 4);
851 data += 6;
852 length -= 6;
854 first = NULL;
855 pp = &first;
857 for (i = 0; i < c; i++)
859 struct group_cursor *gc;
861 if (length < 14)
862 toosmall (_("group cursor"));
864 gc = (struct group_cursor *) res_alloc (sizeof *gc);
866 gc->width = get_16 (big_endian, data);
867 gc->height = get_16 (big_endian, data + 2);
868 gc->planes = get_16 (big_endian, data + 4);
869 gc->bits = get_16 (big_endian, data + 6);
870 gc->bytes = get_32 (big_endian, data + 8);
871 gc->index = get_16 (big_endian, data + 12);
873 gc->next = NULL;
874 *pp = gc;
875 pp = &gc->next;
877 data += 14;
878 length -= 14;
881 r = (struct res_resource *) res_alloc (sizeof *r);
882 r->type = RES_TYPE_GROUP_CURSOR;
883 r->u.group_cursor = first;
885 return r;
888 /* Convert a group icon resource from binary. */
890 static struct res_resource *
891 bin_to_res_group_icon (data, length, big_endian)
892 const unsigned char *data;
893 unsigned long length;
894 int big_endian;
896 int type, c, i;
897 struct group_icon *first, **pp;
898 struct res_resource *r;
900 if (length < 6)
901 toosmall (_("group icon header"));
903 type = get_16 (big_endian, data + 2);
904 if (type != 1)
905 fatal (_("unexpected group icon type %d"), type);
907 c = get_16 (big_endian, data + 4);
909 data += 6;
910 length -= 6;
912 first = NULL;
913 pp = &first;
915 for (i = 0; i < c; i++)
917 struct group_icon *gi;
919 if (length < 14)
920 toosmall (_("group icon"));
922 gi = (struct group_icon *) res_alloc (sizeof *gi);
924 gi->width = data[0];
925 gi->height = data[1];
926 gi->colors = data[2];
927 gi->planes = get_16 (big_endian, data + 4);
928 gi->bits = get_16 (big_endian, data + 6);
929 gi->bytes = get_32 (big_endian, data + 8);
930 gi->index = get_16 (big_endian, data + 12);
932 gi->next = NULL;
933 *pp = gi;
934 pp = &gi->next;
936 data += 14;
937 length -= 14;
940 r = (struct res_resource *) res_alloc (sizeof *r);
941 r->type = RES_TYPE_GROUP_ICON;
942 r->u.group_icon = first;
944 return r;
947 /* Extract data from a version header. If KEY is not NULL, then the
948 key must be KEY; otherwise, the key is returned in *PKEY. This
949 sets *LEN to the total length, *VALLEN to the value length, *TYPE
950 to the type, and *OFF to the offset to the children. */
952 static void
953 get_version_header (data, length, big_endian, key, pkey, len, vallen, type,
954 off)
955 const unsigned char *data;
956 unsigned long length;
957 int big_endian;
958 const char *key;
959 unichar **pkey;
960 int *len;
961 int *vallen;
962 int *type;
963 int *off;
965 if (length < 8)
966 toosmall (key);
968 *len = get_16 (big_endian, data);
969 *vallen = get_16 (big_endian, data + 2);
970 *type = get_16 (big_endian, data + 4);
972 *off = 6;
974 length -= 6;
975 data += 6;
977 if (key == NULL)
979 int sublen;
981 *pkey = get_unicode (data, length, big_endian, &sublen);
982 *off += sublen * 2 + 2;
984 else
986 while (1)
988 if (length < 2)
989 toosmall (key);
990 if (get_16 (big_endian, data) != (unsigned char) *key)
991 fatal (_("unexpected version string"));
993 *off += 2;
994 length -= 2;
995 data += 2;
997 if (*key == '\0')
998 break;
1000 ++key;
1004 *off = (*off + 3) &~ 3;
1007 /* Convert a version resource from binary. */
1009 static struct res_resource *
1010 bin_to_res_version (data, length, big_endian)
1011 const unsigned char *data;
1012 unsigned long length;
1013 int big_endian;
1015 int verlen, vallen, type, off;
1016 struct fixed_versioninfo *fi;
1017 struct ver_info *first, **pp;
1018 struct versioninfo *v;
1019 struct res_resource *r;
1021 get_version_header (data, length, big_endian, "VS_VERSION_INFO",
1022 (unichar *) NULL, &verlen, &vallen, &type, &off);
1024 if ((unsigned int) verlen != length)
1025 fatal (_("version length %d does not match resource length %lu"),
1026 verlen, length);
1028 if (type != 0)
1029 fatal (_("unexpected version type %d"), type);
1031 data += off;
1032 length -= off;
1034 if (vallen == 0)
1035 fi = NULL;
1036 else
1038 unsigned long signature, fiv;
1040 if (vallen != 52)
1041 fatal (_("unexpected fixed version information length %d"), vallen);
1043 if (length < 52)
1044 toosmall (_("fixed version info"));
1046 signature = get_32 (big_endian, data);
1047 if (signature != 0xfeef04bd)
1048 fatal (_("unexpected fixed version signature %lu"), signature);
1050 fiv = get_32 (big_endian, data + 4);
1051 if (fiv != 0 && fiv != 0x10000)
1052 fatal (_("unexpected fixed version info version %lu"), fiv);
1054 fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi);
1056 fi->file_version_ms = get_32 (big_endian, data + 8);
1057 fi->file_version_ls = get_32 (big_endian, data + 12);
1058 fi->product_version_ms = get_32 (big_endian, data + 16);
1059 fi->product_version_ls = get_32 (big_endian, data + 20);
1060 fi->file_flags_mask = get_32 (big_endian, data + 24);
1061 fi->file_flags = get_32 (big_endian, data + 28);
1062 fi->file_os = get_32 (big_endian, data + 32);
1063 fi->file_type = get_32 (big_endian, data + 36);
1064 fi->file_subtype = get_32 (big_endian, data + 40);
1065 fi->file_date_ms = get_32 (big_endian, data + 44);
1066 fi->file_date_ls = get_32 (big_endian, data + 48);
1068 data += 52;
1069 length -= 52;
1072 first = NULL;
1073 pp = &first;
1075 while (length > 0)
1077 struct ver_info *vi;
1078 int ch;
1080 if (length < 8)
1081 toosmall (_("version var info"));
1083 vi = (struct ver_info *) res_alloc (sizeof *vi);
1085 ch = get_16 (big_endian, data + 6);
1087 if (ch == 'S')
1089 struct ver_stringinfo **ppvs;
1091 vi->type = VERINFO_STRING;
1093 get_version_header (data, length, big_endian, "StringFileInfo",
1094 (unichar *) NULL, &verlen, &vallen, &type,
1095 &off);
1097 if (vallen != 0)
1098 fatal (_("unexpected stringfileinfo value length %d"), vallen);
1100 data += off;
1101 length -= off;
1103 get_version_header (data, length, big_endian, (const char *) NULL,
1104 &vi->u.string.language, &verlen, &vallen,
1105 &type, &off);
1107 if (vallen != 0)
1108 fatal (_("unexpected version stringtable value length %d"), vallen);
1110 data += off;
1111 length -= off;
1112 verlen -= off;
1114 vi->u.string.strings = NULL;
1115 ppvs = &vi->u.string.strings;
1117 /* It's convenient to round verlen to a 4 byte alignment,
1118 since we round the subvariables in the loop. */
1119 verlen = (verlen + 3) &~ 3;
1121 while (verlen > 0)
1123 struct ver_stringinfo *vs;
1124 int subverlen, vslen, valoff;
1126 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1128 get_version_header (data, length, big_endian,
1129 (const char *) NULL, &vs->key, &subverlen,
1130 &vallen, &type, &off);
1132 subverlen = (subverlen + 3) &~ 3;
1134 data += off;
1135 length -= off;
1137 vs->value = get_unicode (data, length, big_endian, &vslen);
1138 valoff = vslen * 2 + 2;
1139 valoff = (valoff + 3) &~ 3;
1141 if (off + valoff != subverlen)
1142 fatal (_("unexpected version string length %d != %d + %d"),
1143 subverlen, off, valoff);
1145 vs->next = NULL;
1146 *ppvs = vs;
1147 ppvs = &vs->next;
1149 data += valoff;
1150 length -= valoff;
1152 if (verlen < subverlen)
1153 fatal (_("unexpected version string length %d < %d"),
1154 verlen, subverlen);
1156 verlen -= subverlen;
1159 else if (ch == 'V')
1161 struct ver_varinfo **ppvv;
1163 vi->type = VERINFO_VAR;
1165 get_version_header (data, length, big_endian, "VarFileInfo",
1166 (unichar *) NULL, &verlen, &vallen, &type,
1167 &off);
1169 if (vallen != 0)
1170 fatal (_("unexpected varfileinfo value length %d"), vallen);
1172 data += off;
1173 length -= off;
1175 get_version_header (data, length, big_endian, (const char *) NULL,
1176 &vi->u.var.key, &verlen, &vallen, &type, &off);
1178 data += off;
1179 length -= off;
1181 vi->u.var.var = NULL;
1182 ppvv = &vi->u.var.var;
1184 while (vallen > 0)
1186 struct ver_varinfo *vv;
1188 if (length < 4)
1189 toosmall (_("version varfileinfo"));
1191 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1193 vv->language = get_16 (big_endian, data);
1194 vv->charset = get_16 (big_endian, data + 2);
1196 vv->next = NULL;
1197 *ppvv = vv;
1198 ppvv = &vv->next;
1200 data += 4;
1201 length -= 4;
1203 if (vallen < 4)
1204 fatal (_("unexpected version value length %d"), vallen);
1206 vallen -= 4;
1209 else
1210 fatal (_("unexpected version string"));
1212 vi->next = NULL;
1213 *pp = vi;
1214 pp = &vi->next;
1217 v = (struct versioninfo *) res_alloc (sizeof *v);
1218 v->fixed = fi;
1219 v->var = first;
1221 r = (struct res_resource *) res_alloc (sizeof *r);
1222 r->type = RES_TYPE_VERSIONINFO;
1223 r->u.versioninfo = v;
1225 return r;
1228 /* Convert an arbitrary user defined resource from binary. */
1230 static struct res_resource *
1231 bin_to_res_userdata (data, length, big_endian)
1232 const unsigned char *data;
1233 unsigned long length;
1234 int big_endian;
1236 struct rcdata_item *ri;
1237 struct res_resource *r;
1239 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1241 ri->next = NULL;
1242 ri->type = RCDATA_BUFFER;
1243 ri->u.buffer.length = length;
1244 ri->u.buffer.data = data;
1246 r = (struct res_resource *) res_alloc (sizeof *r);
1247 r->type = RES_TYPE_USERDATA;
1248 r->u.rcdata = ri;
1250 return r;
1253 /* Macros to swap out values. */
1255 #define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
1256 #define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
1258 /* Local functions used to convert resources to binary format. */
1260 static void dword_align_bin PARAMS ((struct bindata ***, unsigned long *));
1261 static struct bindata *resid_to_bin PARAMS ((struct res_id, int));
1262 static struct bindata *unicode_to_bin PARAMS ((const unichar *, int));
1263 static struct bindata *res_to_bin_accelerator
1264 PARAMS ((const struct accelerator *, int));
1265 static struct bindata *res_to_bin_cursor
1266 PARAMS ((const struct cursor *, int));
1267 static struct bindata *res_to_bin_group_cursor
1268 PARAMS ((const struct group_cursor *, int));
1269 static struct bindata *res_to_bin_dialog
1270 PARAMS ((const struct dialog *, int));
1271 static struct bindata *res_to_bin_fontdir
1272 PARAMS ((const struct fontdir *, int));
1273 static struct bindata *res_to_bin_group_icon
1274 PARAMS ((const struct group_icon *, int));
1275 static struct bindata *res_to_bin_menu
1276 PARAMS ((const struct menu *, int));
1277 static struct bindata *res_to_bin_menuitems
1278 PARAMS ((const struct menuitem *, int));
1279 static struct bindata *res_to_bin_menuexitems
1280 PARAMS ((const struct menuitem *, int));
1281 static struct bindata *res_to_bin_rcdata
1282 PARAMS ((const struct rcdata_item *, int));
1283 static struct bindata *res_to_bin_stringtable
1284 PARAMS ((const struct stringtable *, int));
1285 static struct bindata *string_to_unicode_bin PARAMS ((const char *, int));
1286 static struct bindata *res_to_bin_versioninfo
1287 PARAMS ((const struct versioninfo *, int));
1288 static struct bindata *res_to_bin_generic
1289 PARAMS ((unsigned long, const unsigned char *));
1291 /* Convert a resource to binary. */
1293 struct bindata *
1294 res_to_bin (res, big_endian)
1295 const struct res_resource *res;
1296 int big_endian;
1298 switch (res->type)
1300 default:
1301 abort ();
1302 case RES_TYPE_BITMAP:
1303 case RES_TYPE_FONT:
1304 case RES_TYPE_ICON:
1305 case RES_TYPE_MESSAGETABLE:
1306 return res_to_bin_generic (res->u.data.length, res->u.data.data);
1307 case RES_TYPE_ACCELERATOR:
1308 return res_to_bin_accelerator (res->u.acc, big_endian);
1309 case RES_TYPE_CURSOR:
1310 return res_to_bin_cursor (res->u.cursor, big_endian);
1311 case RES_TYPE_GROUP_CURSOR:
1312 return res_to_bin_group_cursor (res->u.group_cursor, big_endian);
1313 case RES_TYPE_DIALOG:
1314 return res_to_bin_dialog (res->u.dialog, big_endian);
1315 case RES_TYPE_FONTDIR:
1316 return res_to_bin_fontdir (res->u.fontdir, big_endian);
1317 case RES_TYPE_GROUP_ICON:
1318 return res_to_bin_group_icon (res->u.group_icon, big_endian);
1319 case RES_TYPE_MENU:
1320 return res_to_bin_menu (res->u.menu, big_endian);
1321 case RES_TYPE_RCDATA:
1322 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1323 case RES_TYPE_STRINGTABLE:
1324 return res_to_bin_stringtable (res->u.stringtable, big_endian);
1325 case RES_TYPE_USERDATA:
1326 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1327 case RES_TYPE_VERSIONINFO:
1328 return res_to_bin_versioninfo (res->u.versioninfo, big_endian);
1332 /* Align to a 32 bit boundary. PPP points to the of a list of bindata
1333 structures. LENGTH points to the length of the structures. If
1334 necessary, this adds a new bindata to bring length up to a 32 bit
1335 boundary. It updates *PPP and *LENGTH. */
1337 static void
1338 dword_align_bin (ppp, length)
1339 struct bindata ***ppp;
1340 unsigned long *length;
1342 int add;
1343 struct bindata *d;
1345 if ((*length & 3) == 0)
1346 return;
1348 add = 4 - (*length & 3);
1350 d = (struct bindata *) reswr_alloc (sizeof *d);
1351 d->length = add;
1352 d->data = (unsigned char *) reswr_alloc (add);
1353 memset (d->data, 0, add);
1355 d->next = NULL;
1356 **ppp = d;
1357 *ppp = &(**ppp)->next;
1359 *length += add;
1362 /* Convert a resource ID to binary. This always returns exactly one
1363 bindata structure. */
1365 static struct bindata *
1366 resid_to_bin (id, big_endian)
1367 struct res_id id;
1368 int big_endian;
1370 struct bindata *d;
1372 d = (struct bindata *) reswr_alloc (sizeof *d);
1374 if (! id.named)
1376 d->length = 4;
1377 d->data = (unsigned char *) reswr_alloc (4);
1378 put_16 (big_endian, 0xffff, d->data);
1379 put_16 (big_endian, id.u.id, d->data + 2);
1381 else
1383 int i;
1385 d->length = id.u.n.length * 2 + 2;
1386 d->data = (unsigned char *) reswr_alloc (d->length);
1387 for (i = 0; i < id.u.n.length; i++)
1388 put_16 (big_endian, id.u.n.name[i], d->data + i * 2);
1389 put_16 (big_endian, 0, d->data + i * 2);
1392 d->next = NULL;
1394 return d;
1397 /* Convert a null terminated unicode string to binary. This always
1398 returns exactly one bindata structure. */
1400 static struct bindata *
1401 unicode_to_bin (str, big_endian)
1402 const unichar *str;
1403 int big_endian;
1405 int len;
1406 struct bindata *d;
1408 len = 0;
1409 if (str != NULL)
1411 const unichar *s;
1413 for (s = str; *s != 0; s++)
1414 ++len;
1417 d = (struct bindata *) reswr_alloc (sizeof *d);
1418 d->length = len * 2 + 2;
1419 d->data = (unsigned char *) reswr_alloc (d->length);
1421 if (str == NULL)
1422 put_16 (big_endian, 0, d->data);
1423 else
1425 const unichar *s;
1426 int i;
1428 for (s = str, i = 0; *s != 0; s++, i++)
1429 put_16 (big_endian, *s, d->data + i * 2);
1430 put_16 (big_endian, 0, d->data + i * 2);
1433 d->next = NULL;
1435 return d;
1438 /* Convert an accelerator resource to binary. */
1440 static struct bindata *
1441 res_to_bin_accelerator (accelerators, big_endian)
1442 const struct accelerator *accelerators;
1443 int big_endian;
1445 struct bindata *first, **pp;
1446 const struct accelerator *a;
1448 first = NULL;
1449 pp = &first;
1451 for (a = accelerators; a != NULL; a = a->next)
1453 struct bindata *d;
1455 d = (struct bindata *) reswr_alloc (sizeof *d);
1456 d->length = 8;
1457 d->data = (unsigned char *) reswr_alloc (8);
1459 put_16 (big_endian,
1460 a->flags | (a->next != NULL ? 0 : ACC_LAST),
1461 d->data);
1462 put_16 (big_endian, a->key, d->data + 2);
1463 put_16 (big_endian, a->id, d->data + 4);
1464 put_16 (big_endian, 0, d->data + 8);
1466 d->next = NULL;
1467 *pp = d;
1468 pp = &d->next;
1471 return first;
1474 /* Convert a cursor resource to binary. */
1476 static struct bindata *
1477 res_to_bin_cursor (c, big_endian)
1478 const struct cursor *c;
1479 int big_endian;
1481 struct bindata *d;
1483 d = (struct bindata *) reswr_alloc (sizeof *d);
1484 d->length = 4;
1485 d->data = (unsigned char *) reswr_alloc (4);
1487 put_16 (big_endian, c->xhotspot, d->data);
1488 put_16 (big_endian, c->yhotspot, d->data + 2);
1490 d->next = (struct bindata *) reswr_alloc (sizeof *d);
1491 d->next->length = c->length;
1492 d->next->data = (unsigned char *) c->data;
1493 d->next->next = NULL;
1495 return d;
1498 /* Convert a group cursor resource to binary. */
1500 static struct bindata *
1501 res_to_bin_group_cursor (group_cursors, big_endian)
1502 const struct group_cursor *group_cursors;
1503 int big_endian;
1505 struct bindata *first, **pp;
1506 int c;
1507 const struct group_cursor *gc;
1509 first = (struct bindata *) reswr_alloc (sizeof *first);
1510 first->length = 6;
1511 first->data = (unsigned char *) reswr_alloc (6);
1513 put_16 (big_endian, 0, first->data);
1514 put_16 (big_endian, 2, first->data + 2);
1516 first->next = NULL;
1517 pp = &first->next;
1519 c = 0;
1520 for (gc = group_cursors; gc != NULL; gc = gc->next)
1522 struct bindata *d;
1524 ++c;
1526 d = (struct bindata *) reswr_alloc (sizeof *d);
1527 d->length = 14;
1528 d->data = (unsigned char *) reswr_alloc (14);
1530 put_16 (big_endian, gc->width, d->data);
1531 put_16 (big_endian, gc->height, d->data + 2);
1532 put_16 (big_endian, gc->planes, d->data + 4);
1533 put_16 (big_endian, gc->bits, d->data + 6);
1534 put_32 (big_endian, gc->bytes, d->data + 8);
1535 put_16 (big_endian, gc->index, d->data + 12);
1537 d->next = NULL;
1538 *pp = d;
1539 pp = &d->next;
1542 put_16 (big_endian, c, first->data + 4);
1544 return first;
1547 /* Convert a dialog resource to binary. */
1549 static struct bindata *
1550 res_to_bin_dialog (dialog, big_endian)
1551 const struct dialog *dialog;
1552 int big_endian;
1554 int dialogex;
1555 struct bindata *first, **pp;
1556 unsigned long length;
1557 int off, c;
1558 struct dialog_control *dc;
1560 dialogex = extended_dialog (dialog);
1562 first = (struct bindata *) reswr_alloc (sizeof *first);
1563 first->length = dialogex ? 26 : 18;
1564 first->data = (unsigned char *) reswr_alloc (first->length);
1566 length = first->length;
1568 if (! dialogex)
1570 put_32 (big_endian, dialog->style, first->data);
1571 put_32 (big_endian, dialog->exstyle, first->data + 4);
1572 off = 8;
1574 else
1576 put_16 (big_endian, 1, first->data);
1577 put_16 (big_endian, 0xffff, first->data + 2);
1579 if (dialog->ex == NULL)
1580 put_32 (big_endian, 0, first->data + 4);
1581 else
1582 put_32 (big_endian, dialog->ex->help, first->data + 4);
1583 put_32 (big_endian, dialog->exstyle, first->data + 8);
1584 put_32 (big_endian, dialog->style, first->data + 12);
1585 off = 16;
1588 put_16 (big_endian, dialog->x, first->data + off + 2);
1589 put_16 (big_endian, dialog->y, first->data + off + 4);
1590 put_16 (big_endian, dialog->width, first->data + off + 6);
1591 put_16 (big_endian, dialog->height, first->data + off + 8);
1593 pp = &first->next;
1595 *pp = resid_to_bin (dialog->menu, big_endian);
1596 length += (*pp)->length;
1597 pp = &(*pp)->next;
1599 *pp = resid_to_bin (dialog->class, big_endian);
1600 length += (*pp)->length;
1601 pp = &(*pp)->next;
1603 *pp = unicode_to_bin (dialog->caption, big_endian);
1604 length += (*pp)->length;
1605 pp = &(*pp)->next;
1607 if ((dialog->style & DS_SETFONT) != 0)
1609 struct bindata *d;
1611 d = (struct bindata *) reswr_alloc (sizeof *d);
1612 d->length = dialogex ? 6 : 2;
1613 d->data = (unsigned char *) reswr_alloc (d->length);
1615 length += d->length;
1617 put_16 (big_endian, dialog->pointsize, d->data);
1619 if (dialogex)
1621 if (dialog->ex == NULL)
1623 put_16 (big_endian, 0, d->data + 2);
1624 put_16 (big_endian, 0, d->data + 4);
1626 else
1628 put_16 (big_endian, dialog->ex->weight, d->data + 2);
1629 put_16 (big_endian, dialog->ex->italic, d->data + 4);
1633 *pp = d;
1634 pp = &d->next;
1636 *pp = unicode_to_bin (dialog->font, big_endian);
1637 length += (*pp)->length;
1638 pp = &(*pp)->next;
1641 c = 0;
1642 for (dc = dialog->controls; dc != NULL; dc = dc->next)
1644 struct bindata *d;
1645 int dcoff;
1647 ++c;
1649 dword_align_bin (&pp, &length);
1651 d = (struct bindata *) reswr_alloc (sizeof *d);
1652 d->length = dialogex ? 24 : 18;
1653 d->data = (unsigned char *) reswr_alloc (d->length);
1655 length += d->length;
1657 if (! dialogex)
1659 put_32 (big_endian, dc->style, d->data);
1660 put_32 (big_endian, dc->exstyle, d->data + 4);
1661 dcoff = 8;
1663 else
1665 put_32 (big_endian, dc->help, d->data);
1666 put_32 (big_endian, dc->exstyle, d->data + 4);
1667 put_32 (big_endian, dc->style, d->data + 8);
1668 dcoff = 12;
1671 put_16 (big_endian, dc->x, d->data + dcoff);
1672 put_16 (big_endian, dc->y, d->data + dcoff + 2);
1673 put_16 (big_endian, dc->width, d->data + dcoff + 4);
1674 put_16 (big_endian, dc->height, d->data + dcoff + 6);
1676 if (dialogex)
1677 put_32 (big_endian, dc->id, d->data + dcoff + 8);
1678 else
1679 put_16 (big_endian, dc->id, d->data + dcoff + 8);
1681 *pp = d;
1682 pp = &d->next;
1684 *pp = resid_to_bin (dc->class, big_endian);
1685 length += (*pp)->length;
1686 pp = &(*pp)->next;
1688 *pp = resid_to_bin (dc->text, big_endian);
1689 length += (*pp)->length;
1690 pp = &(*pp)->next;
1692 d = (struct bindata *) reswr_alloc (sizeof *d);
1693 d->length = 2;
1694 d->data = (unsigned char *) reswr_alloc (2);
1696 length += 2;
1698 d->next = NULL;
1699 *pp = d;
1700 pp = &d->next;
1702 if (dc->data == NULL)
1703 put_16 (big_endian, 0, d->data);
1704 else
1706 unsigned long sublen;
1708 dword_align_bin (&pp, &length);
1710 *pp = res_to_bin_rcdata (dc->data, big_endian);
1711 sublen = 0;
1712 while (*pp != NULL)
1714 sublen += (*pp)->length;
1715 pp = &(*pp)->next;
1718 put_16 (big_endian, sublen, d->data);
1720 length += sublen;
1723 put_16 (big_endian, c, first->data + off);
1725 return first;
1728 /* Convert a fontdir resource to binary. */
1730 static struct bindata *
1731 res_to_bin_fontdir (fontdirs, big_endian)
1732 const struct fontdir *fontdirs;
1733 int big_endian;
1735 struct bindata *first, **pp;
1736 int c;
1737 const struct fontdir *fd;
1739 first = (struct bindata *) reswr_alloc (sizeof *first);
1740 first->length = 2;
1741 first->data = (unsigned char *) reswr_alloc (2);
1743 first->next = NULL;
1744 pp = &first->next;
1746 c = 0;
1747 for (fd = fontdirs; fd != NULL; fd = fd->next)
1749 struct bindata *d;
1751 ++c;
1753 d = (struct bindata *) reswr_alloc (sizeof *d);
1754 d->length = 2;
1755 d->data = (unsigned char *) reswr_alloc (2);
1757 put_16 (big_endian, fd->index, d->data);
1759 *pp = d;
1760 pp = &d->next;
1762 d = (struct bindata *) reswr_alloc (sizeof *d);
1763 d->length = fd->length;
1764 d->data = (unsigned char *) fd->data;
1766 d->next = NULL;
1767 *pp = d;
1768 pp = &d->next;
1771 put_16 (big_endian, c, first->data);
1773 return first;
1776 /* Convert a group icon resource to binary. */
1778 static struct bindata *
1779 res_to_bin_group_icon (group_icons, big_endian)
1780 const struct group_icon *group_icons;
1781 int big_endian;
1783 struct bindata *first, **pp;
1784 int c;
1785 const struct group_icon *gi;
1787 first = (struct bindata *) reswr_alloc (sizeof *first);
1788 first->length = 6;
1789 first->data = (unsigned char *) reswr_alloc (6);
1791 put_16 (big_endian, 0, first->data);
1792 put_16 (big_endian, 1, first->data + 2);
1794 first->next = NULL;
1795 pp = &first->next;
1797 c = 0;
1798 for (gi = group_icons; gi != NULL; gi = gi->next)
1800 struct bindata *d;
1802 ++c;
1804 d = (struct bindata *) reswr_alloc (sizeof *d);
1805 d->length = 14;
1806 d->data = (unsigned char *) reswr_alloc (14);
1808 d->data[0] = gi->width;
1809 d->data[1] = gi->height;
1810 d->data[2] = gi->colors;
1811 d->data[3] = 0;
1812 put_16 (big_endian, gi->planes, d->data + 4);
1813 put_16 (big_endian, gi->bits, d->data + 6);
1814 put_32 (big_endian, gi->bytes, d->data + 8);
1815 put_16 (big_endian, gi->index, d->data + 12);
1817 d->next = NULL;
1818 *pp = d;
1819 pp = &d->next;
1822 put_16 (big_endian, c, first->data + 4);
1824 return first;
1827 /* Convert a menu resource to binary. */
1829 static struct bindata *
1830 res_to_bin_menu (menu, big_endian)
1831 const struct menu *menu;
1832 int big_endian;
1834 int menuex;
1835 struct bindata *d;
1837 menuex = extended_menu (menu);
1839 d = (struct bindata *) reswr_alloc (sizeof *d);
1840 d->length = menuex ? 8 : 4;
1841 d->data = (unsigned char *) reswr_alloc (d->length);
1843 if (! menuex)
1845 put_16 (big_endian, 0, d->data);
1846 put_16 (big_endian, 0, d->data + 2);
1848 d->next = res_to_bin_menuitems (menu->items, big_endian);
1850 else
1852 put_16 (big_endian, 1, d->data);
1853 put_16 (big_endian, 4, d->data + 2);
1854 put_32 (big_endian, menu->help, d->data + 4);
1856 d->next = res_to_bin_menuexitems (menu->items, big_endian);
1859 return d;
1862 /* Convert menu items to binary. */
1864 static struct bindata *
1865 res_to_bin_menuitems (items, big_endian)
1866 const struct menuitem *items;
1867 int big_endian;
1869 struct bindata *first, **pp;
1870 const struct menuitem *mi;
1872 first = NULL;
1873 pp = &first;
1875 for (mi = items; mi != NULL; mi = mi->next)
1877 struct bindata *d;
1878 int flags;
1880 d = (struct bindata *) reswr_alloc (sizeof *d);
1881 d->length = mi->popup == NULL ? 4 : 2;
1882 d->data = (unsigned char *) reswr_alloc (d->length);
1884 flags = mi->type;
1885 if (mi->next == NULL)
1886 flags |= MENUITEM_ENDMENU;
1887 if (mi->popup != NULL)
1888 flags |= MENUITEM_POPUP;
1890 put_16 (big_endian, flags, d->data);
1892 if (mi->popup == NULL)
1893 put_16 (big_endian, mi->id, d->data + 2);
1895 *pp = d;
1896 pp = &d->next;
1898 *pp = unicode_to_bin (mi->text, big_endian);
1899 pp = &(*pp)->next;
1901 if (mi->popup != NULL)
1903 *pp = res_to_bin_menuitems (mi->popup, big_endian);
1904 while (*pp != NULL)
1905 pp = &(*pp)->next;
1909 return first;
1912 /* Convert menuex items to binary. */
1914 static struct bindata *
1915 res_to_bin_menuexitems (items, big_endian)
1916 const struct menuitem *items;
1917 int big_endian;
1919 struct bindata *first, **pp;
1920 unsigned long length;
1921 const struct menuitem *mi;
1923 first = NULL;
1924 pp = &first;
1926 length = 0;
1928 for (mi = items; mi != NULL; mi = mi->next)
1930 struct bindata *d;
1931 int flags;
1933 dword_align_bin (&pp, &length);
1935 d = (struct bindata *) reswr_alloc (sizeof *d);
1936 d->length = 12;
1937 d->data = (unsigned char *) reswr_alloc (12);
1939 length += 12;
1941 put_32 (big_endian, mi->type, d->data);
1942 put_32 (big_endian, mi->state, d->data + 4);
1943 put_16 (big_endian, mi->id, d->data + 8);
1945 flags = 0;
1946 if (mi->next == NULL)
1947 flags |= 0x80;
1948 if (mi->popup != NULL)
1949 flags |= 1;
1950 put_16 (big_endian, flags, d->data + 10);
1952 *pp = d;
1953 pp = &d->next;
1955 *pp = unicode_to_bin (mi->text, big_endian);
1956 length += (*pp)->length;
1957 pp = &(*pp)->next;
1959 if (mi->popup != NULL)
1961 dword_align_bin (&pp, &length);
1963 d = (struct bindata *) reswr_alloc (sizeof *d);
1964 d->length = 4;
1965 d->data = (unsigned char *) reswr_alloc (4);
1967 put_32 (big_endian, mi->help, d->data);
1969 *pp = d;
1970 pp = &d->next;
1972 *pp = res_to_bin_menuexitems (mi->popup, big_endian);
1973 while (*pp != NULL)
1975 length += (*pp)->length;
1976 pp = &(*pp)->next;
1981 return first;
1984 /* Convert an rcdata resource to binary. This is also used to convert
1985 other information which happens to be stored in rcdata_item lists
1986 to binary. */
1988 static struct bindata *
1989 res_to_bin_rcdata (items, big_endian)
1990 const struct rcdata_item *items;
1991 int big_endian;
1993 struct bindata *first, **pp;
1994 const struct rcdata_item *ri;
1996 first = NULL;
1997 pp = &first;
1999 for (ri = items; ri != NULL; ri = ri->next)
2001 struct bindata *d;
2003 d = (struct bindata *) reswr_alloc (sizeof *d);
2005 switch (ri->type)
2007 default:
2008 abort ();
2010 case RCDATA_WORD:
2011 d->length = 2;
2012 d->data = (unsigned char *) reswr_alloc (2);
2013 put_16 (big_endian, ri->u.word, d->data);
2014 break;
2016 case RCDATA_DWORD:
2017 d->length = 4;
2018 d->data = (unsigned char *) reswr_alloc (4);
2019 put_32 (big_endian, ri->u.dword, d->data);
2020 break;
2022 case RCDATA_STRING:
2023 d->length = ri->u.string.length;
2024 d->data = (unsigned char *) ri->u.string.s;
2025 break;
2027 case RCDATA_WSTRING:
2029 unsigned long i;
2031 d->length = ri->u.wstring.length * 2;
2032 d->data = (unsigned char *) reswr_alloc (d->length);
2033 for (i = 0; i < ri->u.wstring.length; i++)
2034 put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2);
2035 break;
2038 case RCDATA_BUFFER:
2039 d->length = ri->u.buffer.length;
2040 d->data = (unsigned char *) ri->u.buffer.data;
2041 break;
2044 d->next = NULL;
2045 *pp = d;
2046 pp = &d->next;
2049 return first;
2052 /* Convert a stringtable resource to binary. */
2054 static struct bindata *
2055 res_to_bin_stringtable (st, big_endian)
2056 const struct stringtable *st;
2057 int big_endian;
2059 struct bindata *first, **pp;
2060 int i;
2062 first = NULL;
2063 pp = &first;
2065 for (i = 0; i < 16; i++)
2067 int slen, j;
2068 struct bindata *d;
2069 unichar *s;
2071 slen = st->strings[i].length;
2072 s = st->strings[i].string;
2074 d = (struct bindata *) reswr_alloc (sizeof *d);
2075 d->length = 2 + slen * 2;
2076 d->data = (unsigned char *) reswr_alloc (d->length);
2078 put_16 (big_endian, slen, d->data);
2080 for (j = 0; j < slen; j++)
2081 put_16 (big_endian, s[j], d->data + 2 + j * 2);
2083 d->next = NULL;
2084 *pp = d;
2085 pp = &d->next;
2088 return first;
2091 /* Convert an ASCII string to a unicode binary string. This always
2092 returns exactly one bindata structure. */
2094 static struct bindata *
2095 string_to_unicode_bin (s, big_endian)
2096 const char *s;
2097 int big_endian;
2099 size_t len, i;
2100 struct bindata *d;
2102 len = strlen (s);
2104 d = (struct bindata *) reswr_alloc (sizeof *d);
2105 d->length = len * 2 + 2;
2106 d->data = (unsigned char *) reswr_alloc (d->length);
2108 for (i = 0; i < len; i++)
2109 put_16 (big_endian, s[i], d->data + i * 2);
2110 put_16 (big_endian, 0, d->data + i * 2);
2112 d->next = NULL;
2114 return d;
2117 /* Convert a versioninfo resource to binary. */
2119 static struct bindata *
2120 res_to_bin_versioninfo (versioninfo, big_endian)
2121 const struct versioninfo *versioninfo;
2122 int big_endian;
2124 struct bindata *first, **pp;
2125 unsigned long length;
2126 struct ver_info *vi;
2128 first = (struct bindata *) reswr_alloc (sizeof *first);
2129 first->length = 6;
2130 first->data = (unsigned char *) reswr_alloc (6);
2132 length = 6;
2134 if (versioninfo->fixed == NULL)
2135 put_16 (big_endian, 0, first->data + 2);
2136 else
2137 put_16 (big_endian, 52, first->data + 2);
2139 put_16 (big_endian, 0, first->data + 4);
2141 pp = &first->next;
2143 *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian);
2144 length += (*pp)->length;
2145 pp = &(*pp)->next;
2147 dword_align_bin (&pp, &length);
2149 if (versioninfo->fixed != NULL)
2151 const struct fixed_versioninfo *fi;
2152 struct bindata *d;
2154 d = (struct bindata *) reswr_alloc (sizeof *d);
2155 d->length = 52;
2156 d->data = (unsigned char *) reswr_alloc (52);
2158 length += 52;
2160 fi = versioninfo->fixed;
2162 put_32 (big_endian, 0xfeef04bd, d->data);
2163 put_32 (big_endian, 0x10000, d->data + 4);
2164 put_32 (big_endian, fi->file_version_ms, d->data + 8);
2165 put_32 (big_endian, fi->file_version_ls, d->data + 12);
2166 put_32 (big_endian, fi->product_version_ms, d->data + 16);
2167 put_32 (big_endian, fi->product_version_ls, d->data + 20);
2168 put_32 (big_endian, fi->file_flags_mask, d->data + 24);
2169 put_32 (big_endian, fi->file_flags, d->data + 28);
2170 put_32 (big_endian, fi->file_os, d->data + 32);
2171 put_32 (big_endian, fi->file_type, d->data + 36);
2172 put_32 (big_endian, fi->file_subtype, d->data + 40);
2173 put_32 (big_endian, fi->file_date_ms, d->data + 44);
2174 put_32 (big_endian, fi->file_date_ls, d->data + 48);
2176 d->next = NULL;
2177 *pp = d;
2178 pp = &d->next;
2181 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2183 struct bindata *vid;
2184 unsigned long vilen;
2186 dword_align_bin (&pp, &length);
2188 vid = (struct bindata *) reswr_alloc (sizeof *vid);
2189 vid->length = 6;
2190 vid->data = (unsigned char *) reswr_alloc (6);
2192 length += 6;
2193 vilen = 6;
2195 put_16 (big_endian, 0, vid->data + 2);
2196 put_16 (big_endian, 0, vid->data + 4);
2198 *pp = vid;
2199 pp = &vid->next;
2201 switch (vi->type)
2203 default:
2204 abort ();
2206 case VERINFO_STRING:
2208 unsigned long hold, vslen;
2209 struct bindata *vsd;
2210 const struct ver_stringinfo *vs;
2212 *pp = string_to_unicode_bin ("StringFileInfo", big_endian);
2213 length += (*pp)->length;
2214 vilen += (*pp)->length;
2215 pp = &(*pp)->next;
2217 hold = length;
2218 dword_align_bin (&pp, &length);
2219 vilen += length - hold;
2221 vsd = (struct bindata *) reswr_alloc (sizeof *vsd);
2222 vsd->length = 6;
2223 vsd->data = (unsigned char *) reswr_alloc (6);
2225 length += 6;
2226 vilen += 6;
2227 vslen = 6;
2229 put_16 (big_endian, 0, vsd->data + 2);
2230 put_16 (big_endian, 0, vsd->data + 4);
2232 *pp = vsd;
2233 pp = &vsd->next;
2235 *pp = unicode_to_bin (vi->u.string.language, big_endian);
2236 length += (*pp)->length;
2237 vilen += (*pp)->length;
2238 vslen += (*pp)->length;
2239 pp = &(*pp)->next;
2241 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2243 struct bindata *vssd;
2244 unsigned long vsslen;
2246 hold = length;
2247 dword_align_bin (&pp, &length);
2248 vilen += length - hold;
2249 vslen += length - hold;
2251 vssd = (struct bindata *) reswr_alloc (sizeof *vssd);
2252 vssd->length = 6;
2253 vssd->data = (unsigned char *) reswr_alloc (6);
2255 length += 6;
2256 vilen += 6;
2257 vslen += 6;
2258 vsslen = 6;
2260 put_16 (big_endian, 1, vssd->data + 4);
2262 *pp = vssd;
2263 pp = &vssd->next;
2265 *pp = unicode_to_bin (vs->key, big_endian);
2266 length += (*pp)->length;
2267 vilen += (*pp)->length;
2268 vslen += (*pp)->length;
2269 vsslen += (*pp)->length;
2270 pp = &(*pp)->next;
2272 hold = length;
2273 dword_align_bin (&pp, &length);
2274 vilen += length - hold;
2275 vslen += length - hold;
2276 vsslen += length - hold;
2278 *pp = unicode_to_bin (vs->value, big_endian);
2279 put_16 (big_endian, (*pp)->length / 2, vssd->data + 2);
2280 length += (*pp)->length;
2281 vilen += (*pp)->length;
2282 vslen += (*pp)->length;
2283 vsslen += (*pp)->length;
2284 pp = &(*pp)->next;
2286 put_16 (big_endian, vsslen, vssd->data);
2289 put_16 (big_endian, vslen, vsd->data);
2291 break;
2294 case VERINFO_VAR:
2296 unsigned long hold, vvlen, vvvlen;
2297 struct bindata *vvd;
2298 const struct ver_varinfo *vv;
2300 *pp = string_to_unicode_bin ("VarFileInfo", big_endian);
2301 length += (*pp)->length;
2302 vilen += (*pp)->length;
2303 pp = &(*pp)->next;
2305 hold = length;
2306 dword_align_bin (&pp, &length);
2307 vilen += length - hold;
2309 vvd = (struct bindata *) reswr_alloc (sizeof *vvd);
2310 vvd->length = 6;
2311 vvd->data = (unsigned char *) reswr_alloc (6);
2313 length += 6;
2314 vilen += 6;
2315 vvlen = 6;
2317 put_16 (big_endian, 0, vvd->data + 4);
2319 *pp = vvd;
2320 pp = &vvd->next;
2322 *pp = unicode_to_bin (vi->u.var.key, big_endian);
2323 length += (*pp)->length;
2324 vilen += (*pp)->length;
2325 vvlen += (*pp)->length;
2326 pp = &(*pp)->next;
2328 hold = length;
2329 dword_align_bin (&pp, &length);
2330 vilen += length - hold;
2331 vvlen += length - hold;
2333 vvvlen = 0;
2335 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2337 struct bindata *vvsd;
2339 vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd);
2340 vvsd->length = 4;
2341 vvsd->data = (unsigned char *) reswr_alloc (4);
2343 length += 4;
2344 vilen += 4;
2345 vvlen += 4;
2346 vvvlen += 4;
2348 put_16 (big_endian, vv->language, vvsd->data);
2349 put_16 (big_endian, vv->charset, vvsd->data + 2);
2351 vvsd->next = NULL;
2352 *pp = vvsd;
2353 pp = &vvsd->next;
2356 put_16 (big_endian, vvlen, vvd->data);
2357 put_16 (big_endian, vvvlen, vvd->data + 2);
2359 break;
2363 put_16 (big_endian, vilen, vid->data);
2366 put_16 (big_endian, length, first->data);
2368 return first;
2371 /* Convert a generic resource to binary. */
2373 static struct bindata *
2374 res_to_bin_generic (length, data)
2375 unsigned long length;
2376 const unsigned char *data;
2378 struct bindata *d;
2380 d = (struct bindata *) reswr_alloc (sizeof *d);
2381 d->length = length;
2382 d->data = (unsigned char *) data;
2384 d->next = NULL;
2386 return d;