merge from gcc
[binutils.git] / binutils / resbin.c
blob5d8b53be196ad3fdb70a9515b47a90545349cb74
1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright 1997, 1998, 1999, 2002, 2003, 2007
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
6 This file is part of GNU Binutils.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
23 /* This file contains functions to convert between the binary resource
24 format and the internal structures that we want to use. The same
25 binary resource format is used in both res and COFF files. */
27 #include "sysdep.h"
28 #include "bfd.h"
29 #include "libiberty.h"
30 #include "bucomm.h"
31 #include "windres.h"
33 /* Macros to swap in values. */
35 #define get_8(s) (*((unsigned char *)(s)))
36 #define get_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s))
37 #define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s))
39 /* Local functions. */
41 static void toosmall (const char *);
43 static unichar *get_unicode
44 (const unsigned char *, unsigned long, int, int *);
45 static int get_resid
46 (struct res_id *, const unsigned char *, unsigned long, int);
47 static struct res_resource *bin_to_res_generic
48 (enum res_type, const unsigned char *, unsigned long);
49 static struct res_resource *bin_to_res_cursor
50 (const unsigned char *, unsigned long, int);
51 static struct res_resource *bin_to_res_menu
52 (const unsigned char *, unsigned long, int);
53 static struct menuitem *bin_to_res_menuitems
54 (const unsigned char *, unsigned long, int, int *);
55 static struct menuitem *bin_to_res_menuexitems
56 (const unsigned char *, unsigned long, int, int *);
57 static struct res_resource *bin_to_res_dialog
58 (const unsigned char *, unsigned long, int);
59 static struct res_resource *bin_to_res_string
60 (const unsigned char *, unsigned long, int);
61 static struct res_resource *bin_to_res_fontdir
62 (const unsigned char *, unsigned long, int);
63 static struct res_resource *bin_to_res_accelerators
64 (const unsigned char *, unsigned long, int);
65 static struct res_resource *bin_to_res_rcdata
66 (const unsigned char *, unsigned long, int);
67 static struct res_resource *bin_to_res_group_cursor
68 (const unsigned char *, unsigned long, int);
69 static struct res_resource *bin_to_res_group_icon
70 (const unsigned char *, unsigned long, int);
71 static struct res_resource *bin_to_res_version
72 (const unsigned char *, unsigned long, int);
73 static struct res_resource *bin_to_res_userdata
74 (const unsigned char *, unsigned long, int);
75 static void get_version_header
76 (const unsigned char *, unsigned long, int, const char *,
77 unichar **, int *, int *, int *, int *);
79 /* Given a resource type ID, a pointer to data, a length, return a
80 res_resource structure which represents that resource. The caller
81 is responsible for initializing the res_info and coff_info fields
82 of the returned structure. */
84 struct res_resource *
85 bin_to_res (struct res_id type, const unsigned char *data,
86 unsigned long length, 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 (const char *msg)
133 fatal (_("%s: not enough binary data"), msg);
136 /* Swap in a NULL terminated unicode string. */
138 static unichar *
139 get_unicode (const unsigned char *data, unsigned long length,
140 int big_endian, 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 (struct res_id *id, const unsigned char *data,
171 unsigned long length, int big_endian)
173 int first;
175 if (length < 2)
176 toosmall (_("resource ID"));
178 first = get_16 (big_endian, data);
179 if (first == 0xffff)
181 if (length < 4)
182 toosmall (_("resource ID"));
183 id->named = 0;
184 id->u.id = get_16 (big_endian, data + 2);
185 return 4;
187 else
189 id->named = 1;
190 id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length);
191 return id->u.n.length * 2 + 2;
195 /* Convert a resource which just stores uninterpreted data from
196 binary. */
198 struct res_resource *
199 bin_to_res_generic (enum res_type type, const unsigned char *data,
200 unsigned long length)
202 struct res_resource *r;
204 r = (struct res_resource *) res_alloc (sizeof *r);
205 r->type = type;
206 r->u.data.data = data;
207 r->u.data.length = length;
209 return r;
212 /* Convert a cursor resource from binary. */
214 struct res_resource *
215 bin_to_res_cursor (const unsigned char *data, unsigned long length,
216 int big_endian)
218 struct cursor *c;
219 struct res_resource *r;
221 if (length < 4)
222 toosmall (_("cursor"));
224 c = (struct cursor *) res_alloc (sizeof *c);
225 c->xhotspot = get_16 (big_endian, data);
226 c->yhotspot = get_16 (big_endian, data + 2);
227 c->length = length - 4;
228 c->data = data + 4;
230 r = (struct res_resource *) res_alloc (sizeof *r);
231 r->type = RES_TYPE_CURSOR;
232 r->u.cursor = c;
234 return r;
237 /* Convert a menu resource from binary. */
239 struct res_resource *
240 bin_to_res_menu (const unsigned char *data, unsigned long length,
241 int big_endian)
243 struct res_resource *r;
244 struct menu *m;
245 int version, read;
247 r = (struct res_resource *) res_alloc (sizeof *r);
248 r->type = RES_TYPE_MENU;
250 m = (struct menu *) res_alloc (sizeof *m);
251 r->u.menu = m;
253 if (length < 2)
254 toosmall (_("menu header"));
256 version = get_16 (big_endian, data);
258 if (version == 0)
260 if (length < 4)
261 toosmall (_("menu header"));
262 m->help = 0;
263 m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian,
264 &read);
266 else if (version == 1)
268 unsigned int offset;
270 if (length < 8)
271 toosmall (_("menuex header"));
272 m->help = get_32 (big_endian, data + 4);
273 offset = get_16 (big_endian, data + 2);
274 if (offset + 4 >= length)
275 toosmall (_("menuex offset"));
276 m->items = bin_to_res_menuexitems (data + 4 + offset,
277 length - (4 + offset),
278 big_endian,
279 &read);
281 else
282 fatal (_("unsupported menu version %d"), version);
284 return r;
287 /* Convert menu items from binary. */
289 static struct menuitem *
290 bin_to_res_menuitems (const unsigned char *data, unsigned long length,
291 int big_endian, int *read)
293 struct menuitem *first, **pp;
295 first = NULL;
296 pp = &first;
298 *read = 0;
300 while (length > 0)
302 int flags, slen, itemlen;
303 unsigned int stroff;
304 struct menuitem *mi;
306 if (length < 4)
307 toosmall (_("menuitem header"));
309 mi = (struct menuitem *) res_alloc (sizeof *mi);
310 mi->state = 0;
311 mi->help = 0;
313 flags = get_16 (big_endian, data);
314 mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
316 if ((flags & MENUITEM_POPUP) == 0)
317 stroff = 4;
318 else
319 stroff = 2;
321 if (length < stroff + 2)
322 toosmall (_("menuitem header"));
324 if (get_16 (big_endian, data + stroff) == 0)
326 slen = 0;
327 mi->text = NULL;
329 else
330 mi->text = get_unicode (data + stroff, length - stroff, big_endian,
331 &slen);
333 itemlen = stroff + slen * 2 + 2;
335 if ((flags & MENUITEM_POPUP) == 0)
337 mi->popup = NULL;
338 mi->id = get_16 (big_endian, data + 2);
340 else
342 int subread;
344 mi->id = 0;
345 mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen,
346 big_endian, &subread);
347 itemlen += subread;
350 mi->next = NULL;
351 *pp = mi;
352 pp = &mi->next;
354 data += itemlen;
355 length -= itemlen;
356 *read += itemlen;
358 if ((flags & MENUITEM_ENDMENU) != 0)
359 return first;
362 return first;
365 /* Convert menuex items from binary. */
367 static struct menuitem *
368 bin_to_res_menuexitems (const unsigned char *data, unsigned long length,
369 int big_endian, int *read)
371 struct menuitem *first, **pp;
373 first = NULL;
374 pp = &first;
376 *read = 0;
378 while (length > 0)
380 int flags, slen;
381 unsigned int itemlen;
382 struct menuitem *mi;
384 if (length < 14)
385 toosmall (_("menuitem header"));
387 mi = (struct menuitem *) res_alloc (sizeof *mi);
388 mi->type = get_32 (big_endian, data);
389 mi->state = get_32 (big_endian, data + 4);
390 mi->id = get_16 (big_endian, data + 8);
392 flags = get_16 (big_endian, data + 10);
394 if (get_16 (big_endian, data + 12) == 0)
396 slen = 0;
397 mi->text = NULL;
399 else
400 mi->text = get_unicode (data + 12, length - 12, big_endian, &slen);
402 itemlen = 12 + slen * 2 + 2;
403 itemlen = (itemlen + 3) &~ 3;
405 if ((flags & 1) == 0)
407 mi->popup = NULL;
408 mi->help = 0;
410 else
412 int subread;
414 if (length < itemlen + 4)
415 toosmall (_("menuitem"));
416 mi->help = get_32 (big_endian, data + itemlen);
417 itemlen += 4;
419 mi->popup = bin_to_res_menuexitems (data + itemlen,
420 length - itemlen,
421 big_endian, &subread);
422 itemlen += subread;
425 mi->next = NULL;
426 *pp = mi;
427 pp = &mi->next;
429 data += itemlen;
430 length -= itemlen;
431 *read += itemlen;
433 if ((flags & 0x80) != 0)
434 return first;
437 return first;
440 /* Convert a dialog resource from binary. */
442 static struct res_resource *
443 bin_to_res_dialog (const unsigned char *data, unsigned long length,
444 int big_endian)
446 int signature;
447 struct dialog *d;
448 int c, sublen, i;
449 unsigned int off;
450 struct dialog_control **pp;
451 struct res_resource *r;
453 if (length < 18)
454 toosmall (_("dialog header"));
456 d = (struct dialog *) res_alloc (sizeof *d);
458 signature = get_16 (big_endian, data + 2);
459 if (signature != 0xffff)
461 d->ex = NULL;
462 d->style = get_32 (big_endian, data);
463 d->exstyle = get_32 (big_endian, data + 4);
464 off = 8;
466 else
468 int version;
470 version = get_16 (big_endian, data);
471 if (version != 1)
472 fatal (_("unexpected DIALOGEX version %d"), version);
474 d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex));
475 d->ex->help = get_32 (big_endian, data + 4);
476 d->exstyle = get_32 (big_endian, data + 8);
477 d->style = get_32 (big_endian, data + 12);
478 off = 16;
481 if (length < off + 10)
482 toosmall (_("dialog header"));
484 c = get_16 (big_endian, data + off);
485 d->x = get_16 (big_endian, data + off + 2);
486 d->y = get_16 (big_endian, data + off + 4);
487 d->width = get_16 (big_endian, data + off + 6);
488 d->height = get_16 (big_endian, data + off + 8);
490 off += 10;
492 sublen = get_resid (&d->menu, data + off, length - off, big_endian);
493 off += sublen;
495 sublen = get_resid (&d->class, data + off, length - off, big_endian);
496 off += sublen;
498 d->caption = get_unicode (data + off, length - off, big_endian, &sublen);
499 off += sublen * 2 + 2;
500 if (sublen == 0)
501 d->caption = NULL;
503 if ((d->style & DS_SETFONT) == 0)
505 d->pointsize = 0;
506 d->font = NULL;
507 if (d->ex != NULL)
509 d->ex->weight = 0;
510 d->ex->italic = 0;
511 d->ex->charset = 1; /* Default charset. */
514 else
516 if (length < off + 2)
517 toosmall (_("dialog font point size"));
519 d->pointsize = get_16 (big_endian, data + off);
520 off += 2;
522 if (d->ex != NULL)
524 if (length < off + 4)
525 toosmall (_("dialogex font information"));
526 d->ex->weight = get_16 (big_endian, data + off);
527 d->ex->italic = get_8 (data + off + 2);
528 d->ex->charset = get_8 (data + off + 3);
529 off += 4;
532 d->font = get_unicode (data + off, length - off, big_endian, &sublen);
533 off += sublen * 2 + 2;
536 d->controls = NULL;
537 pp = &d->controls;
539 for (i = 0; i < c; i++)
541 struct dialog_control *dc;
542 int datalen;
544 off = (off + 3) &~ 3;
546 dc = (struct dialog_control *) res_alloc (sizeof *dc);
548 if (d->ex == NULL)
550 if (length < off + 8)
551 toosmall (_("dialog control"));
553 dc->style = get_32 (big_endian, data + off);
554 dc->exstyle = get_32 (big_endian, data + off + 4);
555 dc->help = 0;
556 off += 8;
558 else
560 if (length < off + 12)
561 toosmall (_("dialogex control"));
562 dc->help = get_32 (big_endian, data + off);
563 dc->exstyle = get_32 (big_endian, data + off + 4);
564 dc->style = get_32 (big_endian, data + off + 8);
565 off += 12;
568 if (length < off + 10)
569 toosmall (_("dialog control"));
571 dc->x = get_16 (big_endian, data + off);
572 dc->y = get_16 (big_endian, data + off + 2);
573 dc->width = get_16 (big_endian, data + off + 4);
574 dc->height = get_16 (big_endian, data + off + 6);
576 if (d->ex != NULL)
577 dc->id = get_32 (big_endian, data + off + 8);
578 else
579 dc->id = get_16 (big_endian, data + off + 8);
581 off += 10 + (d->ex != NULL ? 2 : 0);
583 sublen = get_resid (&dc->class, data + off, length - off, big_endian);
584 off += sublen;
586 sublen = get_resid (&dc->text, data + off, length - off, big_endian);
587 off += sublen;
589 if (length < off + 2)
590 toosmall (_("dialog control end"));
592 datalen = get_16 (big_endian, data + off);
593 off += 2;
595 if (datalen == 0)
596 dc->data = NULL;
597 else
599 off = (off + 3) &~ 3;
601 if (length < off + datalen)
602 toosmall (_("dialog control data"));
604 dc->data = ((struct rcdata_item *)
605 res_alloc (sizeof (struct rcdata_item)));
606 dc->data->next = NULL;
607 dc->data->type = RCDATA_BUFFER;
608 dc->data->u.buffer.length = datalen;
609 dc->data->u.buffer.data = data + off;
611 off += datalen;
614 dc->next = NULL;
615 *pp = dc;
616 pp = &dc->next;
619 r = (struct res_resource *) res_alloc (sizeof *r);
620 r->type = RES_TYPE_DIALOG;
621 r->u.dialog = d;
623 return r;
626 /* Convert a stringtable resource from binary. */
628 static struct res_resource *
629 bin_to_res_string (const unsigned char *data, unsigned long length,
630 int big_endian)
632 struct stringtable *st;
633 int i;
634 struct res_resource *r;
636 st = (struct stringtable *) res_alloc (sizeof *st);
638 for (i = 0; i < 16; i++)
640 unsigned int slen;
642 if (length < 2)
643 toosmall (_("stringtable string length"));
644 slen = get_16 (big_endian, data);
645 st->strings[i].length = slen;
647 if (slen > 0)
649 unichar *s;
650 unsigned int j;
652 if (length < 2 + 2 * slen)
653 toosmall (_("stringtable string"));
655 s = (unichar *) res_alloc (slen * sizeof (unichar));
656 st->strings[i].string = s;
658 for (j = 0; j < slen; j++)
659 s[j] = get_16 (big_endian, data + 2 + j * 2);
662 data += 2 + 2 * slen;
663 length -= 2 + 2 * slen;
666 r = (struct res_resource *) res_alloc (sizeof *r);
667 r->type = RES_TYPE_STRINGTABLE;
668 r->u.stringtable = st;
670 return r;
673 /* Convert a fontdir resource from binary. */
675 static struct res_resource *
676 bin_to_res_fontdir (const unsigned char *data, unsigned long length,
677 int big_endian)
679 int c, i;
680 struct fontdir *first, **pp;
681 struct res_resource *r;
683 if (length < 2)
684 toosmall (_("fontdir header"));
686 c = get_16 (big_endian, data);
688 first = NULL;
689 pp = &first;
691 for (i = 0; i < c; i++)
693 struct fontdir *fd;
694 unsigned int off;
696 if (length < 56)
697 toosmall (_("fontdir"));
699 fd = (struct fontdir *) res_alloc (sizeof *fd);
700 fd->index = get_16 (big_endian, data);
702 /* To work out the length of the fontdir data, we must get the
703 length of the device name and face name strings, even though
704 we don't store them in the fontdir structure. The
705 documentation says that these are NULL terminated char
706 strings, not Unicode strings. */
708 off = 56;
710 while (off < length && data[off] != '\0')
711 ++off;
712 if (off >= length)
713 toosmall (_("fontdir device name"));
714 ++off;
716 while (off < length && data[off] != '\0')
717 ++off;
718 if (off >= length)
719 toosmall (_("fontdir face name"));
720 ++off;
722 fd->length = off;
723 fd->data = data;
725 fd->next = NULL;
726 *pp = fd;
727 pp = &fd->next;
729 /* The documentation does not indicate that any rounding is
730 required. */
732 data += off;
733 length -= off;
736 r = (struct res_resource *) res_alloc (sizeof *r);
737 r->type = RES_TYPE_FONTDIR;
738 r->u.fontdir = first;
740 return r;
743 /* Convert an accelerators resource from binary. */
745 static struct res_resource *
746 bin_to_res_accelerators (const unsigned char *data, unsigned long length,
747 int big_endian)
749 struct accelerator *first, **pp;
750 struct res_resource *r;
752 first = NULL;
753 pp = &first;
755 while (1)
757 struct accelerator *a;
759 if (length < 8)
760 toosmall (_("accelerator"));
762 a = (struct accelerator *) res_alloc (sizeof *a);
764 a->flags = get_16 (big_endian, data);
765 a->key = get_16 (big_endian, data + 2);
766 a->id = get_16 (big_endian, data + 4);
768 a->next = NULL;
769 *pp = a;
770 pp = &a->next;
772 if ((a->flags & ACC_LAST) != 0)
773 break;
775 data += 8;
776 length -= 8;
779 r = (struct res_resource *) res_alloc (sizeof *r);
780 r->type = RES_TYPE_ACCELERATOR;
781 r->u.acc = first;
783 return r;
786 /* Convert an rcdata resource from binary. */
788 static struct res_resource *
789 bin_to_res_rcdata (const unsigned char *data, unsigned long length,
790 int big_endian ATTRIBUTE_UNUSED)
792 struct rcdata_item *ri;
793 struct res_resource *r;
795 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
797 ri->next = NULL;
798 ri->type = RCDATA_BUFFER;
799 ri->u.buffer.length = length;
800 ri->u.buffer.data = data;
802 r = (struct res_resource *) res_alloc (sizeof *r);
803 r->type = RES_TYPE_RCDATA;
804 r->u.rcdata = ri;
806 return r;
809 /* Convert a group cursor resource from binary. */
811 static struct res_resource *
812 bin_to_res_group_cursor (const unsigned char *data, unsigned long length,
813 int big_endian)
815 int type, c, i;
816 struct group_cursor *first, **pp;
817 struct res_resource *r;
819 if (length < 6)
820 toosmall (_("group cursor header"));
822 type = get_16 (big_endian, data + 2);
823 if (type != 2)
824 fatal (_("unexpected group cursor type %d"), type);
826 c = get_16 (big_endian, data + 4);
828 data += 6;
829 length -= 6;
831 first = NULL;
832 pp = &first;
834 for (i = 0; i < c; i++)
836 struct group_cursor *gc;
838 if (length < 14)
839 toosmall (_("group cursor"));
841 gc = (struct group_cursor *) res_alloc (sizeof *gc);
843 gc->width = get_16 (big_endian, data);
844 gc->height = get_16 (big_endian, data + 2);
845 gc->planes = get_16 (big_endian, data + 4);
846 gc->bits = get_16 (big_endian, data + 6);
847 gc->bytes = get_32 (big_endian, data + 8);
848 gc->index = get_16 (big_endian, data + 12);
850 gc->next = NULL;
851 *pp = gc;
852 pp = &gc->next;
854 data += 14;
855 length -= 14;
858 r = (struct res_resource *) res_alloc (sizeof *r);
859 r->type = RES_TYPE_GROUP_CURSOR;
860 r->u.group_cursor = first;
862 return r;
865 /* Convert a group icon resource from binary. */
867 static struct res_resource *
868 bin_to_res_group_icon (const unsigned char *data, unsigned long length,
869 int big_endian)
871 int type, c, i;
872 struct group_icon *first, **pp;
873 struct res_resource *r;
875 if (length < 6)
876 toosmall (_("group icon header"));
878 type = get_16 (big_endian, data + 2);
879 if (type != 1)
880 fatal (_("unexpected group icon type %d"), type);
882 c = get_16 (big_endian, data + 4);
884 data += 6;
885 length -= 6;
887 first = NULL;
888 pp = &first;
890 for (i = 0; i < c; i++)
892 struct group_icon *gi;
894 if (length < 14)
895 toosmall (_("group icon"));
897 gi = (struct group_icon *) res_alloc (sizeof *gi);
899 gi->width = data[0];
900 gi->height = data[1];
901 gi->colors = data[2];
902 gi->planes = get_16 (big_endian, data + 4);
903 gi->bits = get_16 (big_endian, data + 6);
904 gi->bytes = get_32 (big_endian, data + 8);
905 gi->index = get_16 (big_endian, data + 12);
907 gi->next = NULL;
908 *pp = gi;
909 pp = &gi->next;
911 data += 14;
912 length -= 14;
915 r = (struct res_resource *) res_alloc (sizeof *r);
916 r->type = RES_TYPE_GROUP_ICON;
917 r->u.group_icon = first;
919 return r;
922 /* Extract data from a version header. If KEY is not NULL, then the
923 key must be KEY; otherwise, the key is returned in *PKEY. This
924 sets *LEN to the total length, *VALLEN to the value length, *TYPE
925 to the type, and *OFF to the offset to the children. */
927 static void
928 get_version_header (const unsigned char *data, unsigned long length,
929 int big_endian, const char *key, unichar **pkey,
930 int *len, int *vallen, int *type, int *off)
932 if (length < 8)
933 toosmall (key);
935 *len = get_16 (big_endian, data);
936 *vallen = get_16 (big_endian, data + 2);
937 *type = get_16 (big_endian, data + 4);
939 *off = 6;
941 length -= 6;
942 data += 6;
944 if (key == NULL)
946 int sublen;
948 *pkey = get_unicode (data, length, big_endian, &sublen);
949 *off += sublen * 2 + 2;
951 else
953 while (1)
955 if (length < 2)
956 toosmall (key);
957 if (get_16 (big_endian, data) != (unsigned char) *key)
958 fatal (_("unexpected version string"));
960 *off += 2;
961 length -= 2;
962 data += 2;
964 if (*key == '\0')
965 break;
967 ++key;
971 *off = (*off + 3) &~ 3;
974 /* Convert a version resource from binary. */
976 static struct res_resource *
977 bin_to_res_version (const unsigned char *data, unsigned long length,
978 int big_endian)
980 int verlen, vallen, type, off;
981 struct fixed_versioninfo *fi;
982 struct ver_info *first, **pp;
983 struct versioninfo *v;
984 struct res_resource *r;
986 get_version_header (data, length, big_endian, "VS_VERSION_INFO",
987 (unichar **) NULL, &verlen, &vallen, &type, &off);
989 if ((unsigned int) verlen != length)
990 fatal (_("version length %d does not match resource length %lu"),
991 verlen, length);
993 if (type != 0)
994 fatal (_("unexpected version type %d"), type);
996 data += off;
997 length -= off;
999 if (vallen == 0)
1000 fi = NULL;
1001 else
1003 unsigned long signature, fiv;
1005 if (vallen != 52)
1006 fatal (_("unexpected fixed version information length %d"), vallen);
1008 if (length < 52)
1009 toosmall (_("fixed version info"));
1011 signature = get_32 (big_endian, data);
1012 if (signature != 0xfeef04bd)
1013 fatal (_("unexpected fixed version signature %lu"), signature);
1015 fiv = get_32 (big_endian, data + 4);
1016 if (fiv != 0 && fiv != 0x10000)
1017 fatal (_("unexpected fixed version info version %lu"), fiv);
1019 fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi);
1021 fi->file_version_ms = get_32 (big_endian, data + 8);
1022 fi->file_version_ls = get_32 (big_endian, data + 12);
1023 fi->product_version_ms = get_32 (big_endian, data + 16);
1024 fi->product_version_ls = get_32 (big_endian, data + 20);
1025 fi->file_flags_mask = get_32 (big_endian, data + 24);
1026 fi->file_flags = get_32 (big_endian, data + 28);
1027 fi->file_os = get_32 (big_endian, data + 32);
1028 fi->file_type = get_32 (big_endian, data + 36);
1029 fi->file_subtype = get_32 (big_endian, data + 40);
1030 fi->file_date_ms = get_32 (big_endian, data + 44);
1031 fi->file_date_ls = get_32 (big_endian, data + 48);
1033 data += 52;
1034 length -= 52;
1037 first = NULL;
1038 pp = &first;
1040 while (length > 0)
1042 struct ver_info *vi;
1043 int ch;
1045 if (length < 8)
1046 toosmall (_("version var info"));
1048 vi = (struct ver_info *) res_alloc (sizeof *vi);
1050 ch = get_16 (big_endian, data + 6);
1052 if (ch == 'S')
1054 struct ver_stringinfo **ppvs;
1056 vi->type = VERINFO_STRING;
1058 get_version_header (data, length, big_endian, "StringFileInfo",
1059 (unichar **) NULL, &verlen, &vallen, &type,
1060 &off);
1062 if (vallen != 0)
1063 fatal (_("unexpected stringfileinfo value length %d"), vallen);
1065 data += off;
1066 length -= off;
1068 get_version_header (data, length, big_endian, (const char *) NULL,
1069 &vi->u.string.language, &verlen, &vallen,
1070 &type, &off);
1072 if (vallen != 0)
1073 fatal (_("unexpected version stringtable value length %d"), vallen);
1075 data += off;
1076 length -= off;
1077 verlen -= off;
1079 vi->u.string.strings = NULL;
1080 ppvs = &vi->u.string.strings;
1082 /* It's convenient to round verlen to a 4 byte alignment,
1083 since we round the subvariables in the loop. */
1084 verlen = (verlen + 3) &~ 3;
1086 while (verlen > 0)
1088 struct ver_stringinfo *vs;
1089 int subverlen, vslen, valoff;
1091 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1093 get_version_header (data, length, big_endian,
1094 (const char *) NULL, &vs->key, &subverlen,
1095 &vallen, &type, &off);
1097 subverlen = (subverlen + 3) &~ 3;
1099 data += off;
1100 length -= off;
1102 vs->value = get_unicode (data, length, big_endian, &vslen);
1103 valoff = vslen * 2 + 2;
1104 valoff = (valoff + 3) &~ 3;
1106 if (off + valoff != subverlen)
1107 fatal (_("unexpected version string length %d != %d + %d"),
1108 subverlen, off, valoff);
1110 vs->next = NULL;
1111 *ppvs = vs;
1112 ppvs = &vs->next;
1114 data += valoff;
1115 length -= valoff;
1117 if (verlen < subverlen)
1118 fatal (_("unexpected version string length %d < %d"),
1119 verlen, subverlen);
1121 verlen -= subverlen;
1124 else if (ch == 'V')
1126 struct ver_varinfo **ppvv;
1128 vi->type = VERINFO_VAR;
1130 get_version_header (data, length, big_endian, "VarFileInfo",
1131 (unichar **) NULL, &verlen, &vallen, &type,
1132 &off);
1134 if (vallen != 0)
1135 fatal (_("unexpected varfileinfo value length %d"), vallen);
1137 data += off;
1138 length -= off;
1140 get_version_header (data, length, big_endian, (const char *) NULL,
1141 &vi->u.var.key, &verlen, &vallen, &type, &off);
1143 data += off;
1144 length -= off;
1146 vi->u.var.var = NULL;
1147 ppvv = &vi->u.var.var;
1149 while (vallen > 0)
1151 struct ver_varinfo *vv;
1153 if (length < 4)
1154 toosmall (_("version varfileinfo"));
1156 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1158 vv->language = get_16 (big_endian, data);
1159 vv->charset = get_16 (big_endian, data + 2);
1161 vv->next = NULL;
1162 *ppvv = vv;
1163 ppvv = &vv->next;
1165 data += 4;
1166 length -= 4;
1168 if (vallen < 4)
1169 fatal (_("unexpected version value length %d"), vallen);
1171 vallen -= 4;
1174 else
1175 fatal (_("unexpected version string"));
1177 vi->next = NULL;
1178 *pp = vi;
1179 pp = &vi->next;
1182 v = (struct versioninfo *) res_alloc (sizeof *v);
1183 v->fixed = fi;
1184 v->var = first;
1186 r = (struct res_resource *) res_alloc (sizeof *r);
1187 r->type = RES_TYPE_VERSIONINFO;
1188 r->u.versioninfo = v;
1190 return r;
1193 /* Convert an arbitrary user defined resource from binary. */
1195 static struct res_resource *
1196 bin_to_res_userdata (const unsigned char *data, unsigned long length,
1197 int big_endian ATTRIBUTE_UNUSED)
1199 struct rcdata_item *ri;
1200 struct res_resource *r;
1202 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1204 ri->next = NULL;
1205 ri->type = RCDATA_BUFFER;
1206 ri->u.buffer.length = length;
1207 ri->u.buffer.data = data;
1209 r = (struct res_resource *) res_alloc (sizeof *r);
1210 r->type = RES_TYPE_USERDATA;
1211 r->u.rcdata = ri;
1213 return r;
1216 /* Macros to swap out values. */
1218 #define put_8(v, s) (*((unsigned char *) (s)) = (unsigned char) (v))
1219 #define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
1220 #define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
1222 /* Local functions used to convert resources to binary format. */
1224 static void dword_align_bin (struct bindata ***, unsigned long *);
1225 static struct bindata *resid_to_bin (struct res_id, int);
1226 static struct bindata *unicode_to_bin (const unichar *, int);
1227 static struct bindata *res_to_bin_accelerator
1228 (const struct accelerator *, int);
1229 static struct bindata *res_to_bin_cursor
1230 (const struct cursor *, int);
1231 static struct bindata *res_to_bin_group_cursor
1232 (const struct group_cursor *, int);
1233 static struct bindata *res_to_bin_dialog
1234 (const struct dialog *, int);
1235 static struct bindata *res_to_bin_fontdir
1236 (const struct fontdir *, int);
1237 static struct bindata *res_to_bin_group_icon
1238 (const struct group_icon *, int);
1239 static struct bindata *res_to_bin_menu
1240 (const struct menu *, int);
1241 static struct bindata *res_to_bin_menuitems
1242 (const struct menuitem *, int);
1243 static struct bindata *res_to_bin_menuexitems
1244 (const struct menuitem *, int);
1245 static struct bindata *res_to_bin_rcdata
1246 (const struct rcdata_item *, int);
1247 static struct bindata *res_to_bin_stringtable
1248 (const struct stringtable *, int);
1249 static struct bindata *string_to_unicode_bin (const char *, int);
1250 static struct bindata *res_to_bin_versioninfo
1251 (const struct versioninfo *, int);
1252 static struct bindata *res_to_bin_generic
1253 (unsigned long, const unsigned char *);
1255 /* Convert a resource to binary. */
1257 struct bindata *
1258 res_to_bin (const struct res_resource *res, int big_endian)
1260 switch (res->type)
1262 default:
1263 abort ();
1264 case RES_TYPE_BITMAP:
1265 case RES_TYPE_FONT:
1266 case RES_TYPE_ICON:
1267 case RES_TYPE_MESSAGETABLE:
1268 return res_to_bin_generic (res->u.data.length, res->u.data.data);
1269 case RES_TYPE_ACCELERATOR:
1270 return res_to_bin_accelerator (res->u.acc, big_endian);
1271 case RES_TYPE_CURSOR:
1272 return res_to_bin_cursor (res->u.cursor, big_endian);
1273 case RES_TYPE_GROUP_CURSOR:
1274 return res_to_bin_group_cursor (res->u.group_cursor, big_endian);
1275 case RES_TYPE_DIALOG:
1276 return res_to_bin_dialog (res->u.dialog, big_endian);
1277 case RES_TYPE_FONTDIR:
1278 return res_to_bin_fontdir (res->u.fontdir, big_endian);
1279 case RES_TYPE_GROUP_ICON:
1280 return res_to_bin_group_icon (res->u.group_icon, big_endian);
1281 case RES_TYPE_MENU:
1282 return res_to_bin_menu (res->u.menu, big_endian);
1283 case RES_TYPE_RCDATA:
1284 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1285 case RES_TYPE_STRINGTABLE:
1286 return res_to_bin_stringtable (res->u.stringtable, big_endian);
1287 case RES_TYPE_USERDATA:
1288 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1289 case RES_TYPE_VERSIONINFO:
1290 return res_to_bin_versioninfo (res->u.versioninfo, big_endian);
1294 /* Align to a 32 bit boundary. PPP points to the of a list of bindata
1295 structures. LENGTH points to the length of the structures. If
1296 necessary, this adds a new bindata to bring length up to a 32 bit
1297 boundary. It updates *PPP and *LENGTH. */
1299 static void
1300 dword_align_bin (struct bindata ***ppp, unsigned long *length)
1302 int add;
1303 struct bindata *d;
1305 if ((*length & 3) == 0)
1306 return;
1308 add = 4 - (*length & 3);
1310 d = (struct bindata *) reswr_alloc (sizeof *d);
1311 d->length = add;
1312 d->data = (unsigned char *) reswr_alloc (add);
1313 memset (d->data, 0, add);
1315 d->next = NULL;
1316 **ppp = d;
1317 *ppp = &(**ppp)->next;
1319 *length += add;
1322 /* Convert a resource ID to binary. This always returns exactly one
1323 bindata structure. */
1325 static struct bindata *
1326 resid_to_bin (struct res_id id, int big_endian)
1328 struct bindata *d;
1330 d = (struct bindata *) reswr_alloc (sizeof *d);
1332 if (! id.named)
1334 d->length = 4;
1335 d->data = (unsigned char *) reswr_alloc (d->length);
1336 put_16 (big_endian, 0xffff, d->data);
1337 put_16 (big_endian, id.u.id, d->data + 2);
1339 else
1341 int i;
1343 d->length = id.u.n.length * 2 + 2;
1344 d->data = (unsigned char *) reswr_alloc (d->length);
1345 for (i = 0; i < id.u.n.length; i++)
1346 put_16 (big_endian, id.u.n.name[i], d->data + i * 2);
1347 put_16 (big_endian, 0, d->data + i * 2);
1350 d->next = NULL;
1352 return d;
1355 /* Convert a null terminated unicode string to binary. This always
1356 returns exactly one bindata structure. */
1358 static struct bindata *
1359 unicode_to_bin (const unichar *str, int big_endian)
1361 int len;
1362 struct bindata *d;
1364 len = 0;
1365 if (str != NULL)
1367 const unichar *s;
1369 for (s = str; *s != 0; s++)
1370 ++len;
1373 d = (struct bindata *) reswr_alloc (sizeof *d);
1374 d->length = len * 2 + 2;
1375 d->data = (unsigned char *) reswr_alloc (d->length);
1377 if (str == NULL)
1378 put_16 (big_endian, 0, d->data);
1379 else
1381 const unichar *s;
1382 int i;
1384 for (s = str, i = 0; *s != 0; s++, i++)
1385 put_16 (big_endian, *s, d->data + i * 2);
1386 put_16 (big_endian, 0, d->data + i * 2);
1389 d->next = NULL;
1391 return d;
1394 /* Convert an accelerator resource to binary. */
1396 static struct bindata *
1397 res_to_bin_accelerator (const struct accelerator *accelerators,
1398 int big_endian)
1400 struct bindata *first, **pp;
1401 const struct accelerator *a;
1403 first = NULL;
1404 pp = &first;
1406 for (a = accelerators; a != NULL; a = a->next)
1408 struct bindata *d;
1410 d = (struct bindata *) reswr_alloc (sizeof *d);
1411 d->length = 8;
1412 d->data = (unsigned char *) reswr_alloc (d->length);
1414 put_16 (big_endian,
1415 a->flags | (a->next != NULL ? 0 : ACC_LAST),
1416 d->data);
1417 put_16 (big_endian, a->key, d->data + 2);
1418 put_16 (big_endian, a->id, d->data + 4);
1419 put_16 (big_endian, 0, d->data + 6);
1421 d->next = NULL;
1422 *pp = d;
1423 pp = &d->next;
1426 return first;
1429 /* Convert a cursor resource to binary. */
1431 static struct bindata *
1432 res_to_bin_cursor (const struct cursor *c, int big_endian)
1434 struct bindata *d;
1436 d = (struct bindata *) reswr_alloc (sizeof *d);
1437 d->length = 4;
1438 d->data = (unsigned char *) reswr_alloc (d->length);
1440 put_16 (big_endian, c->xhotspot, d->data);
1441 put_16 (big_endian, c->yhotspot, d->data + 2);
1443 d->next = (struct bindata *) reswr_alloc (sizeof *d);
1444 d->next->length = c->length;
1445 d->next->data = (unsigned char *) c->data;
1446 d->next->next = NULL;
1448 return d;
1451 /* Convert a group cursor resource to binary. */
1453 static struct bindata *
1454 res_to_bin_group_cursor (const struct group_cursor *group_cursors,
1455 int big_endian)
1457 struct bindata *first, **pp;
1458 int c;
1459 const struct group_cursor *gc;
1461 first = (struct bindata *) reswr_alloc (sizeof *first);
1462 first->length = 6;
1463 first->data = (unsigned char *) reswr_alloc (first->length);
1465 put_16 (big_endian, 0, first->data);
1466 put_16 (big_endian, 2, first->data + 2);
1468 first->next = NULL;
1469 pp = &first->next;
1471 c = 0;
1472 for (gc = group_cursors; gc != NULL; gc = gc->next)
1474 struct bindata *d;
1476 ++c;
1478 d = (struct bindata *) reswr_alloc (sizeof *d);
1479 d->length = 14;
1480 d->data = (unsigned char *) reswr_alloc (d->length);
1482 put_16 (big_endian, gc->width, d->data);
1483 put_16 (big_endian, gc->height, d->data + 2);
1484 put_16 (big_endian, gc->planes, d->data + 4);
1485 put_16 (big_endian, gc->bits, d->data + 6);
1486 put_32 (big_endian, gc->bytes, d->data + 8);
1487 put_16 (big_endian, gc->index, d->data + 12);
1489 d->next = NULL;
1490 *pp = d;
1491 pp = &d->next;
1494 put_16 (big_endian, c, first->data + 4);
1496 return first;
1499 /* Convert a dialog resource to binary. */
1501 static struct bindata *
1502 res_to_bin_dialog (const struct dialog *dialog, int big_endian)
1504 int dialogex;
1505 struct bindata *first, **pp;
1506 unsigned long length;
1507 int off, c;
1508 struct dialog_control *dc;
1510 dialogex = extended_dialog (dialog);
1512 first = (struct bindata *) reswr_alloc (sizeof *first);
1513 first->length = dialogex ? 26 : 18;
1514 first->data = (unsigned char *) reswr_alloc (first->length);
1516 length = first->length;
1518 if (! dialogex)
1520 put_32 (big_endian, dialog->style, first->data);
1521 put_32 (big_endian, dialog->exstyle, first->data + 4);
1522 off = 8;
1524 else
1526 put_16 (big_endian, 1, first->data);
1527 put_16 (big_endian, 0xffff, first->data + 2);
1529 if (dialog->ex == NULL)
1530 put_32 (big_endian, 0, first->data + 4);
1531 else
1532 put_32 (big_endian, dialog->ex->help, first->data + 4);
1533 put_32 (big_endian, dialog->exstyle, first->data + 8);
1534 put_32 (big_endian, dialog->style, first->data + 12);
1535 off = 16;
1538 put_16 (big_endian, dialog->x, first->data + off + 2);
1539 put_16 (big_endian, dialog->y, first->data + off + 4);
1540 put_16 (big_endian, dialog->width, first->data + off + 6);
1541 put_16 (big_endian, dialog->height, first->data + off + 8);
1543 pp = &first->next;
1545 *pp = resid_to_bin (dialog->menu, big_endian);
1546 length += (*pp)->length;
1547 pp = &(*pp)->next;
1549 *pp = resid_to_bin (dialog->class, big_endian);
1550 length += (*pp)->length;
1551 pp = &(*pp)->next;
1553 *pp = unicode_to_bin (dialog->caption, big_endian);
1554 length += (*pp)->length;
1555 pp = &(*pp)->next;
1557 if ((dialog->style & DS_SETFONT) != 0)
1559 struct bindata *d;
1561 d = (struct bindata *) reswr_alloc (sizeof *d);
1562 d->length = dialogex ? 6 : 2;
1563 d->data = (unsigned char *) reswr_alloc (d->length);
1565 length += d->length;
1567 put_16 (big_endian, dialog->pointsize, d->data);
1569 if (dialogex)
1571 if (dialog->ex == NULL)
1573 put_16 (big_endian, 0, d->data + 2);
1574 put_8 (0, d->data + 4);
1575 put_8 (1, d->data + 5);
1577 else
1579 put_16 (big_endian, dialog->ex->weight, d->data + 2);
1580 put_8 (dialog->ex->italic, d->data + 4);
1581 put_8 (dialog->ex->charset, d->data + 5);
1585 *pp = d;
1586 pp = &d->next;
1588 *pp = unicode_to_bin (dialog->font, big_endian);
1589 length += (*pp)->length;
1590 pp = &(*pp)->next;
1593 c = 0;
1594 for (dc = dialog->controls; dc != NULL; dc = dc->next)
1596 struct bindata *d;
1597 int dcoff;
1599 ++c;
1601 dword_align_bin (&pp, &length);
1603 d = (struct bindata *) reswr_alloc (sizeof *d);
1604 d->length = dialogex ? 24 : 18;
1605 d->data = (unsigned char *) reswr_alloc (d->length);
1607 length += d->length;
1609 if (! dialogex)
1611 put_32 (big_endian, dc->style, d->data);
1612 put_32 (big_endian, dc->exstyle, d->data + 4);
1613 dcoff = 8;
1615 else
1617 put_32 (big_endian, dc->help, d->data);
1618 put_32 (big_endian, dc->exstyle, d->data + 4);
1619 put_32 (big_endian, dc->style, d->data + 8);
1620 dcoff = 12;
1623 put_16 (big_endian, dc->x, d->data + dcoff);
1624 put_16 (big_endian, dc->y, d->data + dcoff + 2);
1625 put_16 (big_endian, dc->width, d->data + dcoff + 4);
1626 put_16 (big_endian, dc->height, d->data + dcoff + 6);
1628 if (dialogex)
1629 put_32 (big_endian, dc->id, d->data + dcoff + 8);
1630 else
1631 put_16 (big_endian, dc->id, d->data + dcoff + 8);
1633 *pp = d;
1634 pp = &d->next;
1636 *pp = resid_to_bin (dc->class, big_endian);
1637 length += (*pp)->length;
1638 pp = &(*pp)->next;
1640 *pp = resid_to_bin (dc->text, big_endian);
1641 length += (*pp)->length;
1642 pp = &(*pp)->next;
1644 d = (struct bindata *) reswr_alloc (sizeof *d);
1645 d->length = 2;
1646 d->data = (unsigned char *) reswr_alloc (d->length);
1648 length += 2;
1650 d->next = NULL;
1651 *pp = d;
1652 pp = &d->next;
1654 if (dc->data == NULL)
1655 put_16 (big_endian, 0, d->data);
1656 else
1658 unsigned long sublen;
1660 dword_align_bin (&pp, &length);
1662 *pp = res_to_bin_rcdata (dc->data, big_endian);
1663 sublen = 0;
1664 while (*pp != NULL)
1666 sublen += (*pp)->length;
1667 pp = &(*pp)->next;
1670 put_16 (big_endian, sublen, d->data);
1672 length += sublen;
1675 put_16 (big_endian, c, first->data + off);
1677 return first;
1680 /* Convert a fontdir resource to binary. */
1682 static struct bindata *
1683 res_to_bin_fontdir (const struct fontdir *fontdirs, int big_endian)
1685 struct bindata *first, **pp;
1686 int c;
1687 const struct fontdir *fd;
1689 first = (struct bindata *) reswr_alloc (sizeof *first);
1690 first->length = 2;
1691 first->data = (unsigned char *) reswr_alloc (first->length);
1693 first->next = NULL;
1694 pp = &first->next;
1696 c = 0;
1697 for (fd = fontdirs; fd != NULL; fd = fd->next)
1699 struct bindata *d;
1701 ++c;
1703 d = (struct bindata *) reswr_alloc (sizeof *d);
1704 d->length = 2;
1705 d->data = (unsigned char *) reswr_alloc (d->length);
1707 put_16 (big_endian, fd->index, d->data);
1709 *pp = d;
1710 pp = &d->next;
1712 d = (struct bindata *) reswr_alloc (sizeof *d);
1713 d->length = fd->length;
1714 d->data = (unsigned char *) fd->data;
1716 d->next = NULL;
1717 *pp = d;
1718 pp = &d->next;
1721 put_16 (big_endian, c, first->data);
1723 return first;
1726 /* Convert a group icon resource to binary. */
1728 static struct bindata *
1729 res_to_bin_group_icon (const struct group_icon *group_icons, int big_endian)
1731 struct bindata *first, **pp;
1732 int c;
1733 const struct group_icon *gi;
1735 first = (struct bindata *) reswr_alloc (sizeof *first);
1736 first->length = 6;
1737 first->data = (unsigned char *) reswr_alloc (first->length);
1739 put_16 (big_endian, 0, first->data);
1740 put_16 (big_endian, 1, first->data + 2);
1742 first->next = NULL;
1743 pp = &first->next;
1745 c = 0;
1746 for (gi = group_icons; gi != NULL; gi = gi->next)
1748 struct bindata *d;
1750 ++c;
1752 d = (struct bindata *) reswr_alloc (sizeof *d);
1753 d->length = 14;
1754 d->data = (unsigned char *) reswr_alloc (d->length);
1756 d->data[0] = gi->width;
1757 d->data[1] = gi->height;
1758 d->data[2] = gi->colors;
1759 d->data[3] = 0;
1760 put_16 (big_endian, gi->planes, d->data + 4);
1761 put_16 (big_endian, gi->bits, d->data + 6);
1762 put_32 (big_endian, gi->bytes, d->data + 8);
1763 put_16 (big_endian, gi->index, d->data + 12);
1765 d->next = NULL;
1766 *pp = d;
1767 pp = &d->next;
1770 put_16 (big_endian, c, first->data + 4);
1772 return first;
1775 /* Convert a menu resource to binary. */
1777 static struct bindata *
1778 res_to_bin_menu (const struct menu *menu, int big_endian)
1780 int menuex;
1781 struct bindata *d;
1783 menuex = extended_menu (menu);
1785 d = (struct bindata *) reswr_alloc (sizeof *d);
1786 d->length = menuex ? 8 : 4;
1787 d->data = (unsigned char *) reswr_alloc (d->length);
1789 if (! menuex)
1791 put_16 (big_endian, 0, d->data);
1792 put_16 (big_endian, 0, d->data + 2);
1794 d->next = res_to_bin_menuitems (menu->items, big_endian);
1796 else
1798 put_16 (big_endian, 1, d->data);
1799 put_16 (big_endian, 4, d->data + 2);
1800 put_32 (big_endian, menu->help, d->data + 4);
1802 d->next = res_to_bin_menuexitems (menu->items, big_endian);
1805 return d;
1808 /* Convert menu items to binary. */
1810 static struct bindata *
1811 res_to_bin_menuitems (const struct menuitem *items, int big_endian)
1813 struct bindata *first, **pp;
1814 const struct menuitem *mi;
1816 first = NULL;
1817 pp = &first;
1819 for (mi = items; mi != NULL; mi = mi->next)
1821 struct bindata *d;
1822 int flags;
1824 d = (struct bindata *) reswr_alloc (sizeof *d);
1825 d->length = mi->popup == NULL ? 4 : 2;
1826 d->data = (unsigned char *) reswr_alloc (d->length);
1828 flags = mi->type;
1829 if (mi->next == NULL)
1830 flags |= MENUITEM_ENDMENU;
1831 if (mi->popup != NULL)
1832 flags |= MENUITEM_POPUP;
1834 put_16 (big_endian, flags, d->data);
1836 if (mi->popup == NULL)
1837 put_16 (big_endian, mi->id, d->data + 2);
1839 *pp = d;
1840 pp = &d->next;
1842 *pp = unicode_to_bin (mi->text, big_endian);
1843 pp = &(*pp)->next;
1845 if (mi->popup != NULL)
1847 *pp = res_to_bin_menuitems (mi->popup, big_endian);
1848 while (*pp != NULL)
1849 pp = &(*pp)->next;
1853 return first;
1856 /* Convert menuex items to binary. */
1858 static struct bindata *
1859 res_to_bin_menuexitems (const struct menuitem *items, int big_endian)
1861 struct bindata *first, **pp;
1862 unsigned long length;
1863 const struct menuitem *mi;
1865 first = NULL;
1866 pp = &first;
1868 length = 0;
1870 for (mi = items; mi != NULL; mi = mi->next)
1872 struct bindata *d;
1873 int flags;
1875 dword_align_bin (&pp, &length);
1877 d = (struct bindata *) reswr_alloc (sizeof *d);
1878 d->length = 12;
1879 d->data = (unsigned char *) reswr_alloc (d->length);
1881 length += 12;
1883 put_32 (big_endian, mi->type, d->data);
1884 put_32 (big_endian, mi->state, d->data + 4);
1885 put_16 (big_endian, mi->id, d->data + 8);
1887 flags = 0;
1888 if (mi->next == NULL)
1889 flags |= 0x80;
1890 if (mi->popup != NULL)
1891 flags |= 1;
1892 put_16 (big_endian, flags, d->data + 10);
1894 *pp = d;
1895 pp = &d->next;
1897 *pp = unicode_to_bin (mi->text, big_endian);
1898 length += (*pp)->length;
1899 pp = &(*pp)->next;
1901 if (mi->popup != NULL)
1903 dword_align_bin (&pp, &length);
1905 d = (struct bindata *) reswr_alloc (sizeof *d);
1906 d->length = 4;
1907 d->data = (unsigned char *) reswr_alloc (d->length);
1909 put_32 (big_endian, mi->help, d->data);
1911 *pp = d;
1912 pp = &d->next;
1914 *pp = res_to_bin_menuexitems (mi->popup, big_endian);
1915 while (*pp != NULL)
1917 length += (*pp)->length;
1918 pp = &(*pp)->next;
1923 return first;
1926 /* Convert an rcdata resource to binary. This is also used to convert
1927 other information which happens to be stored in rcdata_item lists
1928 to binary. */
1930 static struct bindata *
1931 res_to_bin_rcdata (const struct rcdata_item *items, int big_endian)
1933 struct bindata *first, **pp;
1934 const struct rcdata_item *ri;
1936 first = NULL;
1937 pp = &first;
1939 for (ri = items; ri != NULL; ri = ri->next)
1941 struct bindata *d;
1943 d = (struct bindata *) reswr_alloc (sizeof *d);
1945 switch (ri->type)
1947 default:
1948 abort ();
1950 case RCDATA_WORD:
1951 d->length = 2;
1952 d->data = (unsigned char *) reswr_alloc (d->length);
1953 put_16 (big_endian, ri->u.word, d->data);
1954 break;
1956 case RCDATA_DWORD:
1957 d->length = 4;
1958 d->data = (unsigned char *) reswr_alloc (d->length);
1959 put_32 (big_endian, ri->u.dword, d->data);
1960 break;
1962 case RCDATA_STRING:
1963 d->length = ri->u.string.length;
1964 d->data = (unsigned char *) ri->u.string.s;
1965 break;
1967 case RCDATA_WSTRING:
1969 unsigned long i;
1971 d->length = ri->u.wstring.length * 2;
1972 d->data = (unsigned char *) reswr_alloc (d->length);
1973 for (i = 0; i < ri->u.wstring.length; i++)
1974 put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2);
1975 break;
1978 case RCDATA_BUFFER:
1979 d->length = ri->u.buffer.length;
1980 d->data = (unsigned char *) ri->u.buffer.data;
1981 break;
1984 d->next = NULL;
1985 *pp = d;
1986 pp = &d->next;
1989 return first;
1992 /* Convert a stringtable resource to binary. */
1994 static struct bindata *
1995 res_to_bin_stringtable (const struct stringtable *st, int big_endian)
1997 struct bindata *first, **pp;
1998 int i;
2000 first = NULL;
2001 pp = &first;
2003 for (i = 0; i < 16; i++)
2005 int slen, j;
2006 struct bindata *d;
2007 unichar *s;
2009 slen = st->strings[i].length;
2010 s = st->strings[i].string;
2012 d = (struct bindata *) reswr_alloc (sizeof *d);
2013 d->length = 2 + slen * 2;
2014 d->data = (unsigned char *) reswr_alloc (d->length);
2016 put_16 (big_endian, slen, d->data);
2018 for (j = 0; j < slen; j++)
2019 put_16 (big_endian, s[j], d->data + 2 + j * 2);
2021 d->next = NULL;
2022 *pp = d;
2023 pp = &d->next;
2026 return first;
2029 /* Convert an ASCII string to a unicode binary string. This always
2030 returns exactly one bindata structure. */
2032 static struct bindata *
2033 string_to_unicode_bin (const char *s, int big_endian)
2035 size_t len, i;
2036 struct bindata *d;
2038 len = strlen (s);
2040 d = (struct bindata *) reswr_alloc (sizeof *d);
2041 d->length = len * 2 + 2;
2042 d->data = (unsigned char *) reswr_alloc (d->length);
2044 for (i = 0; i < len; i++)
2045 put_16 (big_endian, s[i], d->data + i * 2);
2046 put_16 (big_endian, 0, d->data + i * 2);
2048 d->next = NULL;
2050 return d;
2053 /* Convert a versioninfo resource to binary. */
2055 static struct bindata *
2056 res_to_bin_versioninfo (const struct versioninfo *versioninfo, int big_endian)
2058 struct bindata *first, **pp;
2059 unsigned long length;
2060 struct ver_info *vi;
2062 first = (struct bindata *) reswr_alloc (sizeof *first);
2063 first->length = 6;
2064 first->data = (unsigned char *) reswr_alloc (first->length);
2066 length = 6;
2068 if (versioninfo->fixed == NULL)
2069 put_16 (big_endian, 0, first->data + 2);
2070 else
2071 put_16 (big_endian, 52, first->data + 2);
2073 put_16 (big_endian, 0, first->data + 4);
2075 pp = &first->next;
2077 *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian);
2078 length += (*pp)->length;
2079 pp = &(*pp)->next;
2081 dword_align_bin (&pp, &length);
2083 if (versioninfo->fixed != NULL)
2085 const struct fixed_versioninfo *fi;
2086 struct bindata *d;
2088 d = (struct bindata *) reswr_alloc (sizeof *d);
2089 d->length = 52;
2090 d->data = (unsigned char *) reswr_alloc (d->length);
2092 length += 52;
2094 fi = versioninfo->fixed;
2096 put_32 (big_endian, 0xfeef04bd, d->data);
2097 put_32 (big_endian, 0x10000, d->data + 4);
2098 put_32 (big_endian, fi->file_version_ms, d->data + 8);
2099 put_32 (big_endian, fi->file_version_ls, d->data + 12);
2100 put_32 (big_endian, fi->product_version_ms, d->data + 16);
2101 put_32 (big_endian, fi->product_version_ls, d->data + 20);
2102 put_32 (big_endian, fi->file_flags_mask, d->data + 24);
2103 put_32 (big_endian, fi->file_flags, d->data + 28);
2104 put_32 (big_endian, fi->file_os, d->data + 32);
2105 put_32 (big_endian, fi->file_type, d->data + 36);
2106 put_32 (big_endian, fi->file_subtype, d->data + 40);
2107 put_32 (big_endian, fi->file_date_ms, d->data + 44);
2108 put_32 (big_endian, fi->file_date_ls, d->data + 48);
2110 d->next = NULL;
2111 *pp = d;
2112 pp = &d->next;
2115 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2117 struct bindata *vid;
2118 unsigned long vilen;
2120 dword_align_bin (&pp, &length);
2122 vid = (struct bindata *) reswr_alloc (sizeof *vid);
2123 vid->length = 6;
2124 vid->data = (unsigned char *) reswr_alloc (vid->length);
2126 length += 6;
2127 vilen = 6;
2129 put_16 (big_endian, 0, vid->data + 2);
2130 put_16 (big_endian, 0, vid->data + 4);
2132 *pp = vid;
2133 pp = &vid->next;
2135 switch (vi->type)
2137 default:
2138 abort ();
2140 case VERINFO_STRING:
2142 unsigned long hold, vslen;
2143 struct bindata *vsd;
2144 const struct ver_stringinfo *vs;
2146 *pp = string_to_unicode_bin ("StringFileInfo", big_endian);
2147 length += (*pp)->length;
2148 vilen += (*pp)->length;
2149 pp = &(*pp)->next;
2151 hold = length;
2152 dword_align_bin (&pp, &length);
2153 vilen += length - hold;
2155 vsd = (struct bindata *) reswr_alloc (sizeof *vsd);
2156 vsd->length = 6;
2157 vsd->data = (unsigned char *) reswr_alloc (vsd->length);
2159 length += 6;
2160 vilen += 6;
2161 vslen = 6;
2163 put_16 (big_endian, 0, vsd->data + 2);
2164 put_16 (big_endian, 0, vsd->data + 4);
2166 *pp = vsd;
2167 pp = &vsd->next;
2169 *pp = unicode_to_bin (vi->u.string.language, big_endian);
2170 length += (*pp)->length;
2171 vilen += (*pp)->length;
2172 vslen += (*pp)->length;
2173 pp = &(*pp)->next;
2175 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2177 struct bindata *vssd;
2178 unsigned long vsslen;
2180 hold = length;
2181 dword_align_bin (&pp, &length);
2182 vilen += length - hold;
2183 vslen += length - hold;
2185 vssd = (struct bindata *) reswr_alloc (sizeof *vssd);
2186 vssd->length = 6;
2187 vssd->data = (unsigned char *) reswr_alloc (vssd->length);
2189 length += 6;
2190 vilen += 6;
2191 vslen += 6;
2192 vsslen = 6;
2194 put_16 (big_endian, 1, vssd->data + 4);
2196 *pp = vssd;
2197 pp = &vssd->next;
2199 *pp = unicode_to_bin (vs->key, big_endian);
2200 length += (*pp)->length;
2201 vilen += (*pp)->length;
2202 vslen += (*pp)->length;
2203 vsslen += (*pp)->length;
2204 pp = &(*pp)->next;
2206 hold = length;
2207 dword_align_bin (&pp, &length);
2208 vilen += length - hold;
2209 vslen += length - hold;
2210 vsslen += length - hold;
2212 *pp = unicode_to_bin (vs->value, big_endian);
2213 put_16 (big_endian, (*pp)->length / 2, vssd->data + 2);
2214 length += (*pp)->length;
2215 vilen += (*pp)->length;
2216 vslen += (*pp)->length;
2217 vsslen += (*pp)->length;
2218 pp = &(*pp)->next;
2220 put_16 (big_endian, vsslen, vssd->data);
2223 put_16 (big_endian, vslen, vsd->data);
2225 break;
2228 case VERINFO_VAR:
2230 unsigned long hold, vvlen, vvvlen;
2231 struct bindata *vvd;
2232 const struct ver_varinfo *vv;
2234 *pp = string_to_unicode_bin ("VarFileInfo", big_endian);
2235 length += (*pp)->length;
2236 vilen += (*pp)->length;
2237 pp = &(*pp)->next;
2239 hold = length;
2240 dword_align_bin (&pp, &length);
2241 vilen += length - hold;
2243 vvd = (struct bindata *) reswr_alloc (sizeof *vvd);
2244 vvd->length = 6;
2245 vvd->data = (unsigned char *) reswr_alloc (vvd->length);
2247 length += 6;
2248 vilen += 6;
2249 vvlen = 6;
2251 put_16 (big_endian, 0, vvd->data + 4);
2253 *pp = vvd;
2254 pp = &vvd->next;
2256 *pp = unicode_to_bin (vi->u.var.key, big_endian);
2257 length += (*pp)->length;
2258 vilen += (*pp)->length;
2259 vvlen += (*pp)->length;
2260 pp = &(*pp)->next;
2262 hold = length;
2263 dword_align_bin (&pp, &length);
2264 vilen += length - hold;
2265 vvlen += length - hold;
2267 vvvlen = 0;
2269 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2271 struct bindata *vvsd;
2273 vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd);
2274 vvsd->length = 4;
2275 vvsd->data = (unsigned char *) reswr_alloc (vvsd->length);
2277 length += 4;
2278 vilen += 4;
2279 vvlen += 4;
2280 vvvlen += 4;
2282 put_16 (big_endian, vv->language, vvsd->data);
2283 put_16 (big_endian, vv->charset, vvsd->data + 2);
2285 vvsd->next = NULL;
2286 *pp = vvsd;
2287 pp = &vvsd->next;
2290 put_16 (big_endian, vvlen, vvd->data);
2291 put_16 (big_endian, vvvlen, vvd->data + 2);
2293 break;
2297 put_16 (big_endian, vilen, vid->data);
2300 put_16 (big_endian, length, first->data);
2302 return first;
2305 /* Convert a generic resource to binary. */
2307 static struct bindata *
2308 res_to_bin_generic (unsigned long length, const unsigned char *data)
2310 struct bindata *d;
2312 d = (struct bindata *) reswr_alloc (sizeof *d);
2313 d->length = length;
2314 d->data = (unsigned char *) data;
2316 d->next = NULL;
2318 return d;