* Added the "c_gen.pl" perl script into this directory, so the current
[binutils-gdb.git] / binutils / resbin.c
blob7931dbf7a9ecc3f0645a60de4026d2f1e121d55f
1 /* resbin.c -- manipulate the Windows binary resource format.
2 Copyright 1997 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_ACCELERATORS:
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 < 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 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, stroff, slen, itemlen;
315 struct menuitem *mi;
317 if (length < 4)
318 toosmall ("menuitem header");
320 mi = (struct menuitem *) res_alloc (sizeof *mi);
321 mi->state = 0;
322 mi->help = 0;
324 flags = get_16 (big_endian, data);
325 mi->type = flags;
327 if ((flags & MENUITEM_POPUP) == 0)
328 stroff = 4;
329 else
330 stroff = 2;
332 if (length < stroff + 2)
333 toosmall ("menuitem header");
335 if (get_16 (big_endian, data + stroff) == 0)
337 slen = 0;
338 mi->text = NULL;
340 else
341 mi->text = get_unicode (data + stroff, length - stroff, big_endian,
342 &slen);
344 itemlen = stroff + slen * 2 + 2;
346 if ((flags & MENUITEM_POPUP) == 0)
348 mi->popup = NULL;
349 mi->id = get_16 (big_endian, data + 2);
351 else
353 int subread;
355 mi->id = 0;
356 mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen,
357 big_endian, &subread);
358 itemlen += subread;
361 mi->next = NULL;
362 *pp = mi;
363 pp = &mi->next;
365 data += itemlen;
366 length -= itemlen;
367 *read += itemlen;
369 if ((flags & MENUITEM_ENDMENU) != 0)
370 return first;
373 return first;
376 /* Convert menuex items from binary. */
378 static struct menuitem *
379 bin_to_res_menuexitems (data, length, big_endian, read)
380 const unsigned char *data;
381 unsigned long length;
382 int big_endian;
383 int *read;
385 struct menuitem *first, **pp;
387 first = NULL;
388 pp = &first;
390 *read = 0;
392 while (length > 0)
394 int flags, slen, itemlen;
395 struct menuitem *mi;
397 if (length < 14)
398 toosmall ("menuitem header");
400 mi = (struct menuitem *) res_alloc (sizeof *mi);
401 mi->type = get_32 (big_endian, data);
402 mi->state = get_32 (big_endian, data + 4);
403 mi->id = get_16 (big_endian, data + 8);
405 flags = get_16 (big_endian, data + 10);
407 if (get_16 (big_endian, data + 12) == 0)
409 slen = 0;
410 mi->text = NULL;
412 else
413 mi->text = get_unicode (data + 12, length - 12, big_endian, &slen);
415 itemlen = 12 + slen * 2 + 2;
416 itemlen = (itemlen + 3) &~ 3;
418 if ((flags & 1) == 0)
420 mi->popup = NULL;
421 mi->help = 0;
423 else
425 int subread;
427 if (length < itemlen + 4)
428 toosmall ("menuitem");
429 mi->help = get_32 (big_endian, data + itemlen);
430 itemlen += 4;
432 mi->popup = bin_to_res_menuexitems (data + itemlen,
433 length - itemlen,
434 big_endian, &subread);
435 itemlen += subread;
438 mi->next = NULL;
439 *pp = mi;
440 pp = &mi->next;
442 data += itemlen;
443 length -= itemlen;
444 *read += itemlen;
446 if ((flags & 0x80) != 0)
447 return first;
450 return first;
453 /* Convert a dialog resource from binary. */
455 static struct res_resource *
456 bin_to_res_dialog (data, length, big_endian)
457 const unsigned char *data;
458 unsigned long length;
459 int big_endian;
461 int version;
462 struct dialog *d;
463 int c, sublen, off, i;
464 struct dialog_control **pp;
465 struct res_resource *r;
467 if (length < 18)
468 toosmall ("dialog header");
470 d = (struct dialog *) res_alloc (sizeof *d);
472 version = get_16 (big_endian, data);
473 if (version != 0xffff)
475 d->ex = NULL;
476 d->style = get_32 (big_endian, data);
477 d->exstyle = get_32 (big_endian, data + 4);
478 off = 8;
480 else
482 int signature;
484 signature = get_16 (big_endian, data + 2);
485 if (signature != 1)
486 fatal ("unexpected dialog signature %d", signature);
488 d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex));
489 d->ex->help = get_32 (big_endian, data + 4);
490 d->exstyle = get_32 (big_endian, data + 8);
491 d->style = get_32 (big_endian, data + 12);
492 off = 16;
495 if (length < off + 10)
496 toosmall ("dialog header");
498 c = get_16 (big_endian, data + off);
499 d->x = get_16 (big_endian, data + off + 2);
500 d->y = get_16 (big_endian, data + off + 4);
501 d->width = get_16 (big_endian, data + off + 6);
502 d->height = get_16 (big_endian, data + off + 8);
504 off += 10;
506 sublen = get_resid (&d->menu, data + off, length - off, big_endian);
507 off += sublen;
509 sublen = get_resid (&d->class, data + off, length - off, big_endian);
510 off += sublen;
512 d->caption = get_unicode (data + off, length - off, big_endian, &sublen);
513 off += sublen * 2 + 2;
515 if ((d->style & DS_SETFONT) == 0)
517 d->pointsize = 0;
518 d->font = NULL;
519 if (d->ex != NULL)
521 d->ex->weight = 0;
522 d->ex->italic = 0;
525 else
527 if (length < off + 2)
528 toosmall ("dialog font point size");
530 d->pointsize = get_16 (big_endian, data + off);
531 off += 2;
533 if (d->ex != NULL)
535 if (length < off + 4)
536 toosmall ("dialogex font information");
537 d->ex->weight = get_16 (big_endian, data + off);
538 d->ex->italic = get_16 (big_endian, data + off + 2);
539 off += 4;
542 d->font = get_unicode (data + off, length - off, big_endian, &sublen);
543 off += sublen * 2 + 2;
546 d->controls = NULL;
547 pp = &d->controls;
549 for (i = 0; i < c; i++)
551 struct dialog_control *dc;
552 int datalen;
554 off = (off + 3) &~ 3;
556 dc = (struct dialog_control *) res_alloc (sizeof *dc);
558 if (d->ex == NULL)
560 if (length < off + 8)
561 toosmall ("dialog control");
563 dc->style = get_32 (big_endian, data + off);
564 dc->exstyle = get_32 (big_endian, data + off + 4);
565 dc->help = 0;
566 off += 8;
568 else
570 if (length < off + 12)
571 toosmall ("dialogex control");
572 dc->help = get_32 (big_endian, data + off);
573 dc->exstyle = get_32 (big_endian, data + off + 4);
574 dc->style = get_32 (big_endian, data + off + 18);
575 off += 12;
578 if (length < off + 10)
579 toosmall ("dialog control");
581 dc->x = get_16 (big_endian, data + off);
582 dc->y = get_16 (big_endian, data + off + 2);
583 dc->width = get_16 (big_endian, data + off + 4);
584 dc->height = get_16 (big_endian, data + off + 6);
585 dc->id = get_16 (big_endian, data + off + 8);
587 off += 10;
589 sublen = get_resid (&dc->class, data + off, length - off, big_endian);
590 off += sublen;
592 sublen = get_resid (&dc->text, data + off, length - off, big_endian);
593 off += sublen;
595 if (length < off + 2)
596 toosmall ("dialog control end");
598 datalen = get_16 (big_endian, data + off);
599 off += 2;
601 if (datalen == 0)
602 dc->data = NULL;
603 else
605 off = (off + 3) &~ 3;
607 if (length < off + datalen)
608 toosmall ("dialog control data");
610 dc->data = ((struct rcdata_item *)
611 res_alloc (sizeof (struct rcdata_item)));
612 dc->data->next = NULL;
613 dc->data->type = RCDATA_BUFFER;
614 dc->data->u.buffer.length = datalen;
615 dc->data->u.buffer.data = data + off;
617 off += datalen;
620 dc->next = NULL;
621 *pp = dc;
622 pp = &dc->next;
625 r = (struct res_resource *) res_alloc (sizeof *r);
626 r->type = RES_TYPE_DIALOG;
627 r->u.dialog = d;
629 return r;
632 /* Convert a stringtable resource from binary. */
634 static struct res_resource *
635 bin_to_res_string (data, length, big_endian)
636 const unsigned char *data;
637 unsigned long length;
638 int big_endian;
640 struct stringtable *st;
641 int i;
642 struct res_resource *r;
644 st = (struct stringtable *) res_alloc (sizeof *st);
646 for (i = 0; i < 16; i++)
648 int slen;
650 if (length < 2)
651 toosmall ("stringtable string length");
652 slen = get_16 (big_endian, data);
653 st->strings[i].length = slen;
655 if (slen > 0)
657 unichar *s;
658 int j;
660 if (length < 2 + 2 * slen)
661 toosmall ("stringtable string");
663 s = (unichar *) res_alloc (slen * sizeof (unichar));
664 st->strings[i].string = s;
666 for (j = 0; j < slen; j++)
667 s[j] = get_16 (big_endian, data + 2 + j * 2);
670 data += 2 + 2 * slen;
671 length -= 2 + 2 * slen;
674 r = (struct res_resource *) res_alloc (sizeof *r);
675 r->type = RES_TYPE_STRINGTABLE;
676 r->u.stringtable = st;
678 return r;
681 /* Convert a fontdir resource from binary. */
683 static struct res_resource *
684 bin_to_res_fontdir (data, length, big_endian)
685 const unsigned char *data;
686 unsigned long length;
687 int big_endian;
689 int c, i;
690 struct fontdir *first, **pp;
691 struct res_resource *r;
693 if (length < 2)
694 toosmall ("fontdir header");
696 c = get_16 (big_endian, data);
698 first = NULL;
699 pp = &first;
701 for (i = 0; i < c; i++)
703 struct fontdir *fd;
704 int off;
706 if (length < 56)
707 toosmall ("fontdir");
709 fd = (struct fontdir *) res_alloc (sizeof *fd);
710 fd->index = get_16 (big_endian, data);
712 /* To work out the length of the fontdir data, we must get the
713 length of the device name and face name strings, even though
714 we don't store them in the fontdir structure. The
715 documentation says that these are NULL terminated char
716 strings, not Unicode strings. */
718 off = 56;
720 while (off < length && data[off] != '\0')
721 ++off;
722 if (off >= length)
723 toosmall ("fontdir device name");
724 ++off;
726 while (off < length && data[off] != '\0')
727 ++off;
728 if (off >= length)
729 toosmall ("fontdir face name");
730 ++off;
732 fd->length = off;
733 fd->data = data;
735 fd->next = NULL;
736 *pp = fd;
737 pp = &fd->next;
739 /* The documentation does not indicate that any rounding is
740 required. */
742 data += off;
743 length -= off;
746 r = (struct res_resource *) res_alloc (sizeof *r);
747 r->type = RES_TYPE_FONTDIR;
748 r->u.fontdir = first;
750 return r;
753 /* Convert an accelerators resource from binary. */
755 static struct res_resource *
756 bin_to_res_accelerators (data, length, big_endian)
757 const unsigned char *data;
758 unsigned long length;
759 int big_endian;
761 struct accelerator *first, **pp;
762 struct res_resource *r;
764 first = NULL;
765 pp = &first;
767 while (1)
769 struct accelerator *a;
771 if (length < 8)
772 toosmall ("accelerator");
774 a->flags = get_16 (big_endian, data);
775 a->key = get_16 (big_endian, data + 2);
776 a->id = get_16 (big_endian, data + 4);
778 a->next = NULL;
779 *pp = a;
780 pp = &a->next;
782 if ((a->flags & ACC_LAST) != 0)
783 break;
785 data += 8;
786 length -= 8;
789 r = (struct res_resource *) res_alloc (sizeof *r);
790 r->type = RES_TYPE_ACCELERATOR;
791 r->u.acc = first;
793 return r;
796 /* Convert an rcdata resource from binary. */
798 static struct res_resource *
799 bin_to_res_rcdata (data, length, big_endian)
800 const unsigned char *data;
801 unsigned long length;
802 int big_endian;
804 struct rcdata_item *ri;
805 struct res_resource *r;
807 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
809 ri->next = NULL;
810 ri->type = RCDATA_BUFFER;
811 ri->u.buffer.length = length;
812 ri->u.buffer.data = data;
814 r = (struct res_resource *) res_alloc (sizeof *r);
815 r->type = RES_TYPE_RCDATA;
816 r->u.rcdata = ri;
818 return r;
821 /* Convert a group cursor resource from binary. */
823 static struct res_resource *
824 bin_to_res_group_cursor (data, length, big_endian)
825 const unsigned char *data;
826 unsigned long length;
827 int big_endian;
829 int type, c, i;
830 struct group_cursor *first, **pp;
831 struct res_resource *r;
833 if (length < 6)
834 toosmall ("group cursor header");
836 type = get_16 (big_endian, data + 2);
837 if (type != 2)
838 fatal ("unexpected group cursor type %d", type);
840 c = get_16 (big_endian, data + 4);
842 data += 6;
843 length -= 6;
845 first = NULL;
846 pp = &first;
848 for (i = 0; i < c; i++)
850 struct group_cursor *gc;
852 if (length < 14)
853 toosmall ("group cursor");
855 gc = (struct group_cursor *) res_alloc (sizeof *gc);
857 gc->width = get_16 (big_endian, data);
858 gc->height = get_16 (big_endian, data + 2);
859 gc->planes = get_16 (big_endian, data + 4);
860 gc->bits = get_16 (big_endian, data + 6);
861 gc->bytes = get_32 (big_endian, data + 8);
862 gc->index = get_16 (big_endian, data + 12);
864 gc->next = NULL;
865 *pp = gc;
866 pp = &gc->next;
868 data += 14;
869 length -= 14;
872 r = (struct res_resource *) res_alloc (sizeof *r);
873 r->type = RES_TYPE_GROUP_CURSOR;
874 r->u.group_cursor = first;
876 return r;
879 /* Convert a group icon resource from binary. */
881 static struct res_resource *
882 bin_to_res_group_icon (data, length, big_endian)
883 const unsigned char *data;
884 unsigned long length;
885 int big_endian;
887 int type, c, i;
888 struct group_icon *first, **pp;
889 struct res_resource *r;
891 if (length < 6)
892 toosmall ("group icon header");
894 type = get_16 (big_endian, data + 2);
895 if (type != 1)
896 fatal ("unexpected group icon type %d", type);
898 c = get_16 (big_endian, data + 4);
900 data += 6;
901 length -= 6;
903 first = NULL;
904 pp = &first;
906 for (i = 0; i < c; i++)
908 struct group_icon *gi;
910 if (length < 14)
911 toosmall ("group icon");
913 gi = (struct group_icon *) res_alloc (sizeof *gi);
915 gi->width = data[0];
916 gi->height = data[1];
917 gi->colors = data[2];
918 gi->planes = get_16 (big_endian, data + 4);
919 gi->bits = get_16 (big_endian, data + 6);
920 gi->bytes = get_32 (big_endian, data + 8);
921 gi->index = get_16 (big_endian, data + 12);
923 gi->next = NULL;
924 *pp = gi;
925 pp = &gi->next;
927 data += 14;
928 length -= 14;
931 r = (struct res_resource *) res_alloc (sizeof *r);
932 r->type = RES_TYPE_GROUP_ICON;
933 r->u.group_icon = first;
935 return r;
938 /* Extract data from a version header. If KEY is not NULL, then the
939 key must be KEY; otherwise, the key is returned in *PKEY. This
940 sets *LEN to the total length, *VALLEN to the value length, *TYPE
941 to the type, and *OFF to the offset to the children. */
943 static void
944 get_version_header (data, length, big_endian, key, pkey, len, vallen, type,
945 off)
946 const unsigned char *data;
947 unsigned long length;
948 int big_endian;
949 const char *key;
950 unichar **pkey;
951 int *len;
952 int *vallen;
953 int *type;
954 int *off;
956 if (length < 8)
957 toosmall (key);
959 *len = get_16 (big_endian, data);
960 *vallen = get_16 (big_endian, data + 2);
961 *type = get_16 (big_endian, data + 4);
963 *off = 6;
965 length -= 6;
966 data += 6;
968 if (key == NULL)
970 int sublen;
972 *pkey = get_unicode (data, length, big_endian, &sublen);
973 *off += sublen * 2 + 2;
975 else
977 while (1)
979 if (length < 2)
980 toosmall (key);
981 if (get_16 (big_endian, data) != *key)
982 fatal ("unexpected version string");
984 *off += 2;
985 length -= 2;
986 data += 2;
988 if (*key == '\0')
989 break;
991 ++key;
995 *off = (*off + 3) &~ 3;
998 /* Convert a version resource from binary. */
1000 static struct res_resource *
1001 bin_to_res_version (data, length, big_endian)
1002 const unsigned char *data;
1003 unsigned long length;
1004 int big_endian;
1006 int verlen, vallen, type, off;
1007 struct fixed_versioninfo *fi;
1008 struct ver_info *first, **pp;
1009 struct versioninfo *v;
1010 struct res_resource *r;
1012 get_version_header (data, length, big_endian, "VS_VERSION_INFO",
1013 (unichar *) NULL, &verlen, &vallen, &type, &off);
1015 if (verlen != length)
1016 fatal ("version length %d does not match resource length %lu",
1017 verlen, length);
1019 if (type != 0)
1020 fatal ("unexpected version type %d", type);
1022 data += off;
1023 length -= off;
1025 if (vallen == 0)
1026 fi = NULL;
1027 else
1029 unsigned long signature, fiv;
1031 if (vallen != 52)
1032 fatal ("unexpected fixed version information length %d", vallen);
1034 if (length < 52)
1035 toosmall ("fixed version info");
1037 signature = get_32 (big_endian, data);
1038 if (signature != 0xfeef04bd)
1039 fatal ("unexpected fixed version signature %lu", signature);
1041 fiv = get_32 (big_endian, data + 4);
1042 if (fiv != 0 && fiv != 0x10000)
1043 fatal ("unexpected fixed version info version %lu", fiv);
1045 fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi);
1047 fi->file_version_ms = get_32 (big_endian, data + 8);
1048 fi->file_version_ls = get_32 (big_endian, data + 12);
1049 fi->product_version_ms = get_32 (big_endian, data + 16);
1050 fi->product_version_ls = get_32 (big_endian, data + 20);
1051 fi->file_flags_mask = get_32 (big_endian, data + 24);
1052 fi->file_flags = get_32 (big_endian, data + 28);
1053 fi->file_os = get_32 (big_endian, data + 32);
1054 fi->file_type = get_32 (big_endian, data + 36);
1055 fi->file_subtype = get_32 (big_endian, data + 40);
1056 fi->file_date_ms = get_32 (big_endian, data + 44);
1057 fi->file_date_ls = get_32 (big_endian, data + 48);
1059 data += 52;
1060 length -= 52;
1063 first = NULL;
1064 pp = &first;
1066 while (length > 0)
1068 struct ver_info *vi;
1069 int ch;
1071 if (length < 8)
1072 toosmall ("version var info");
1074 vi = (struct ver_info *) res_alloc (sizeof *vi);
1076 ch = get_16 (big_endian, data + 6);
1078 if (ch == 'S')
1080 struct ver_stringinfo **ppvs;
1082 vi->type = VERINFO_STRING;
1084 get_version_header (data, length, big_endian, "StringFileInfo",
1085 (unichar *) NULL, &verlen, &vallen, &type,
1086 &off);
1088 if (vallen != 0)
1089 fatal ("unexpected stringfileinfo value length %d", vallen);
1091 data += off;
1092 length -= off;
1094 get_version_header (data, length, big_endian, (const char *) NULL,
1095 &vi->u.string.language, &verlen, &vallen,
1096 &type, &off);
1098 if (vallen != 0)
1099 fatal ("unexpected version stringtable value length %d", vallen);
1101 data += off;
1102 length -= off;
1103 verlen -= off;
1105 vi->u.string.strings = NULL;
1106 ppvs = &vi->u.string.strings;
1108 /* It's convenient to round verlen to a 4 byte alignment,
1109 since we round the subvariables in the loop. */
1110 verlen = (verlen + 3) &~ 3;
1112 while (verlen > 0)
1114 struct ver_stringinfo *vs;
1115 int subverlen, vslen, valoff;
1117 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1119 get_version_header (data, length, big_endian,
1120 (const char *) NULL, &vs->key, &subverlen,
1121 &vallen, &type, &off);
1123 subverlen = (subverlen + 3) &~ 3;
1125 data += off;
1126 length -= off;
1128 vs->value = get_unicode (data, length, big_endian, &vslen);
1129 valoff = vslen * 2 + 2;
1130 valoff = (valoff + 3) &~ 3;
1132 if (off + valoff != subverlen)
1133 fatal ("unexpected version string length %d != %d + %d",
1134 subverlen, off, valoff);
1136 vs->next = NULL;
1137 *ppvs = vs;
1138 ppvs = &vs->next;
1140 data += valoff;
1141 length -= valoff;
1143 if (verlen < subverlen)
1144 fatal ("unexpected version string length %d < %d",
1145 verlen, subverlen);
1147 verlen -= subverlen;
1150 else if (ch == 'V')
1152 struct ver_varinfo **ppvv;
1154 vi->type = VERINFO_VAR;
1156 get_version_header (data, length, big_endian, "VarFileInfo",
1157 (unichar *) NULL, &verlen, &vallen, &type,
1158 &off);
1160 if (vallen != 0)
1161 fatal ("unexpected varfileinfo value length %d", vallen);
1163 data += off;
1164 length -= off;
1166 get_version_header (data, length, big_endian, (const char *) NULL,
1167 &vi->u.var.key, &verlen, &vallen, &type, &off);
1169 data += off;
1170 length -= off;
1172 vi->u.var.var = NULL;
1173 ppvv = &vi->u.var.var;
1175 while (vallen > 0)
1177 struct ver_varinfo *vv;
1179 if (length < 4)
1180 toosmall ("version varfileinfo");
1182 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1184 vv->language = get_16 (big_endian, data);
1185 vv->charset = get_16 (big_endian, data + 2);
1187 vv->next = NULL;
1188 *ppvv = vv;
1189 ppvv = &vv->next;
1191 data += 4;
1192 length -= 4;
1194 if (vallen < 4)
1195 fatal ("unexpected version value length %d", vallen);
1197 vallen -= 4;
1200 else
1201 fatal ("unexpected version string");
1203 vi->next = NULL;
1204 *pp = vi;
1205 pp = &vi->next;
1208 v = (struct versioninfo *) res_alloc (sizeof *v);
1209 v->fixed = fi;
1210 v->var = first;
1212 r = (struct res_resource *) res_alloc (sizeof *r);
1213 r->type = RES_TYPE_VERSIONINFO;
1214 r->u.versioninfo = v;
1216 return r;
1219 /* Convert an arbitrary user defined resource from binary. */
1221 static struct res_resource *
1222 bin_to_res_userdata (data, length, big_endian)
1223 const unsigned char *data;
1224 unsigned long length;
1225 int big_endian;
1227 struct rcdata_item *ri;
1228 struct res_resource *r;
1230 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1232 ri->next = NULL;
1233 ri->type = RCDATA_BUFFER;
1234 ri->u.buffer.length = length;
1235 ri->u.buffer.data = data;
1237 r = (struct res_resource *) res_alloc (sizeof *r);
1238 r->type = RES_TYPE_USERDATA;
1239 r->u.rcdata = ri;
1241 return r;
1244 /* Macros to swap out values. */
1246 #define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
1247 #define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
1249 /* Local functions used to convert resources to binary format. */
1251 static void dword_align_bin PARAMS ((struct bindata ***, unsigned long *));
1252 static struct bindata *resid_to_bin PARAMS ((struct res_id, int));
1253 static struct bindata *unicode_to_bin PARAMS ((const unichar *, int));
1254 static struct bindata *res_to_bin_accelerator
1255 PARAMS ((const struct accelerator *, int));
1256 static struct bindata *res_to_bin_cursor
1257 PARAMS ((const struct cursor *, int));
1258 static struct bindata *res_to_bin_group_cursor
1259 PARAMS ((const struct group_cursor *, int));
1260 static struct bindata *res_to_bin_dialog
1261 PARAMS ((const struct dialog *, int));
1262 static struct bindata *res_to_bin_fontdir
1263 PARAMS ((const struct fontdir *, int));
1264 static struct bindata *res_to_bin_group_icon
1265 PARAMS ((const struct group_icon *, int));
1266 static struct bindata *res_to_bin_menu
1267 PARAMS ((const struct menu *, int));
1268 static struct bindata *res_to_bin_menuitems
1269 PARAMS ((const struct menuitem *, int));
1270 static struct bindata *res_to_bin_menuexitems
1271 PARAMS ((const struct menuitem *, int));
1272 static struct bindata *res_to_bin_rcdata
1273 PARAMS ((const struct rcdata_item *, int));
1274 static struct bindata *res_to_bin_stringtable
1275 PARAMS ((const struct stringtable *, int));
1276 static struct bindata *string_to_unicode_bin PARAMS ((const char *, int));
1277 static struct bindata *res_to_bin_versioninfo
1278 PARAMS ((const struct versioninfo *, int));
1279 static struct bindata *res_to_bin_generic
1280 PARAMS ((unsigned long, const unsigned char *));
1282 /* Convert a resource to binary. */
1284 struct bindata *
1285 res_to_bin (res, big_endian)
1286 const struct res_resource *res;
1287 int big_endian;
1289 switch (res->type)
1291 default:
1292 abort ();
1293 case RES_TYPE_BITMAP:
1294 case RES_TYPE_FONT:
1295 case RES_TYPE_ICON:
1296 case RES_TYPE_MESSAGETABLE:
1297 return res_to_bin_generic (res->u.data.length, res->u.data.data);
1298 case RES_TYPE_ACCELERATOR:
1299 return res_to_bin_accelerator (res->u.acc, big_endian);
1300 case RES_TYPE_CURSOR:
1301 return res_to_bin_cursor (res->u.cursor, big_endian);
1302 case RES_TYPE_GROUP_CURSOR:
1303 return res_to_bin_group_cursor (res->u.group_cursor, big_endian);
1304 case RES_TYPE_DIALOG:
1305 return res_to_bin_dialog (res->u.dialog, big_endian);
1306 case RES_TYPE_FONTDIR:
1307 return res_to_bin_fontdir (res->u.fontdir, big_endian);
1308 case RES_TYPE_GROUP_ICON:
1309 return res_to_bin_group_icon (res->u.group_icon, big_endian);
1310 case RES_TYPE_MENU:
1311 return res_to_bin_menu (res->u.menu, big_endian);
1312 case RES_TYPE_RCDATA:
1313 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1314 case RES_TYPE_STRINGTABLE:
1315 return res_to_bin_stringtable (res->u.stringtable, big_endian);
1316 case RES_TYPE_USERDATA:
1317 return res_to_bin_rcdata (res->u.rcdata, big_endian);
1318 case RES_TYPE_VERSIONINFO:
1319 return res_to_bin_versioninfo (res->u.versioninfo, big_endian);
1323 /* Align to a 32 bit boundary. PPP points to the of a list of bindata
1324 structures. LENGTH points to the length of the structures. If
1325 necessary, this adds a new bindata to bring length up to a 32 bit
1326 boundary. It updates *PPP and *LENGTH. */
1328 static void
1329 dword_align_bin (ppp, length)
1330 struct bindata ***ppp;
1331 unsigned long *length;
1333 int add;
1334 struct bindata *d;
1336 if ((*length & 3) == 0)
1337 return;
1339 add = 4 - (*length & 3);
1341 d = (struct bindata *) reswr_alloc (sizeof *d);
1342 d->length = add;
1343 d->data = (unsigned char *) reswr_alloc (add);
1344 memset (d->data, 0, add);
1346 d->next = NULL;
1347 **ppp = d;
1348 *ppp = &(**ppp)->next;
1350 *length += add;
1353 /* Convert a resource ID to binary. This always returns exactly one
1354 bindata structure. */
1356 static struct bindata *
1357 resid_to_bin (id, big_endian)
1358 struct res_id id;
1359 int big_endian;
1361 struct bindata *d;
1363 d = (struct bindata *) reswr_alloc (sizeof *d);
1365 if (! id.named)
1367 d->length = 4;
1368 d->data = (unsigned char *) reswr_alloc (4);
1369 put_16 (big_endian, 0xffff, d->data);
1370 put_16 (big_endian, id.u.id, d->data + 2);
1372 else
1374 int i;
1376 d->length = id.u.n.length * 2 + 2;
1377 d->data = (unsigned char *) reswr_alloc (d->length);
1378 for (i = 0; i < id.u.n.length; i++)
1379 put_16 (big_endian, id.u.n.name[i], d->data + i * 2);
1380 put_16 (big_endian, 0, d->data + i * 2);
1383 d->next = NULL;
1385 return d;
1388 /* Convert a null terminated unicode string to binary. This always
1389 returns exactly one bindata structure. */
1391 static struct bindata *
1392 unicode_to_bin (str, big_endian)
1393 const unichar *str;
1394 int big_endian;
1396 int len;
1397 struct bindata *d;
1399 len = 0;
1400 if (str != NULL)
1402 const unichar *s;
1404 for (s = str; *s != 0; s++)
1405 ++len;
1408 d = (struct bindata *) reswr_alloc (sizeof *d);
1409 d->length = len * 2 + 2;
1410 d->data = (unsigned char *) reswr_alloc (d->length);
1412 if (str == NULL)
1413 put_16 (big_endian, 0, d->data);
1414 else
1416 const unichar *s;
1417 int i;
1419 for (s = str, i = 0; *s != 0; s++, i++)
1420 put_16 (big_endian, *s, d->data + i * 2);
1421 put_16 (big_endian, 0, d->data + i * 2);
1424 d->next = NULL;
1426 return d;
1429 /* Convert an accelerator resource to binary. */
1431 static struct bindata *
1432 res_to_bin_accelerator (accelerators, big_endian)
1433 const struct accelerator *accelerators;
1434 int big_endian;
1436 struct bindata *first, **pp;
1437 const struct accelerator *a;
1439 first = NULL;
1440 pp = &first;
1442 for (a = accelerators; a != NULL; a = a->next)
1444 struct bindata *d;
1446 d = (struct bindata *) reswr_alloc (sizeof *d);
1447 d->length = 8;
1448 d->data = (unsigned char *) reswr_alloc (8);
1450 put_16 (big_endian,
1451 a->flags | (a->next == NULL ? 0 : ACC_LAST),
1452 d->data);
1453 put_16 (big_endian, a->key, d->data + 2);
1454 put_16 (big_endian, a->id, d->data + 4);
1455 put_16 (big_endian, 0, d->data + 8);
1457 d->next = NULL;
1458 *pp = d;
1459 pp = &d->next;
1462 return first;
1465 /* Convert a cursor resource to binary. */
1467 static struct bindata *
1468 res_to_bin_cursor (c, big_endian)
1469 const struct cursor *c;
1470 int big_endian;
1472 struct bindata *d;
1474 d = (struct bindata *) reswr_alloc (sizeof *d);
1475 d->length = 4;
1476 d->data = (unsigned char *) reswr_alloc (4);
1478 put_16 (big_endian, c->xhotspot, d->data);
1479 put_16 (big_endian, c->yhotspot, d->data + 2);
1481 d->next = (struct bindata *) reswr_alloc (sizeof *d);
1482 d->next->length = c->length;
1483 d->next->data = (unsigned char *) c->data;
1484 d->next->next = NULL;
1486 return d;
1489 /* Convert a group cursor resource to binary. */
1491 static struct bindata *
1492 res_to_bin_group_cursor (group_cursors, big_endian)
1493 const struct group_cursor *group_cursors;
1494 int big_endian;
1496 struct bindata *first, **pp;
1497 int c;
1498 const struct group_cursor *gc;
1500 first = (struct bindata *) reswr_alloc (sizeof *first);
1501 first->length = 6;
1502 first->data = (unsigned char *) reswr_alloc (6);
1504 put_16 (big_endian, 0, first->data);
1505 put_16 (big_endian, 2, first->data + 2);
1507 first->next = NULL;
1508 pp = &first->next;
1510 c = 0;
1511 for (gc = group_cursors; gc != NULL; gc = gc->next)
1513 struct bindata *d;
1515 ++c;
1517 d = (struct bindata *) reswr_alloc (sizeof *d);
1518 d->length = 14;
1519 d->data = (unsigned char *) reswr_alloc (14);
1521 put_16 (big_endian, gc->width, d->data);
1522 put_16 (big_endian, gc->height, d->data + 2);
1523 put_16 (big_endian, gc->planes, d->data + 4);
1524 put_16 (big_endian, gc->bits, d->data + 6);
1525 put_32 (big_endian, gc->bytes, d->data + 8);
1526 put_16 (big_endian, gc->index, d->data + 12);
1528 d->next = NULL;
1529 *pp = d;
1530 pp = &d->next;
1533 put_16 (big_endian, c, first->data + 4);
1535 return first;
1538 /* Convert a dialog resource to binary. */
1540 static struct bindata *
1541 res_to_bin_dialog (dialog, big_endian)
1542 const struct dialog *dialog;
1543 int big_endian;
1545 int dialogex;
1546 struct bindata *first, **pp;
1547 unsigned long length;
1548 int off, c;
1549 struct dialog_control *dc;
1551 dialogex = extended_dialog (dialog);
1553 first = (struct bindata *) reswr_alloc (sizeof *first);
1554 first->length = dialogex ? 26 : 18;
1555 first->data = (unsigned char *) reswr_alloc (first->length);
1557 length = first->length;
1559 if (! dialogex)
1561 put_32 (big_endian, dialog->style, first->data);
1562 put_32 (big_endian, dialog->style, first->data + 4);
1563 off = 8;
1565 else
1567 put_16 (big_endian, 0xffff, first->data);
1568 put_16 (big_endian, 1, first->data + 2);
1569 if (dialog->ex == NULL)
1570 put_32 (big_endian, 0, first->data + 4);
1571 else
1572 put_32 (big_endian, dialog->ex->help, first->data + 4);
1573 put_32 (big_endian, dialog->exstyle, first->data + 8);
1574 put_32 (big_endian, dialog->style, first->data + 12);
1575 off = 16;
1578 put_16 (big_endian, dialog->x, first->data + off + 2);
1579 put_16 (big_endian, dialog->y, first->data + off + 4);
1580 put_16 (big_endian, dialog->width, first->data + off + 6);
1581 put_16 (big_endian, dialog->height, first->data + off + 8);
1583 pp = &first->next;
1585 *pp = resid_to_bin (dialog->menu, big_endian);
1586 length += (*pp)->length;
1587 pp = &(*pp)->next;
1589 *pp = resid_to_bin (dialog->class, big_endian);
1590 length += (*pp)->length;
1591 pp = &(*pp)->next;
1593 *pp = unicode_to_bin (dialog->caption, big_endian);
1594 length += (*pp)->length;
1595 pp = &(*pp)->next;
1597 if ((dialog->style & DS_SETFONT) != 0)
1599 struct bindata *d;
1601 d = (struct bindata *) reswr_alloc (sizeof *d);
1602 d->length = dialogex ? 2 : 6;
1603 d->data = (unsigned char *) reswr_alloc (d->length);
1605 length += d->length;
1607 put_16 (big_endian, dialog->pointsize, d->data);
1609 if (dialogex)
1611 if (dialog->ex == NULL)
1613 put_16 (big_endian, 0, d->data + 2);
1614 put_16 (big_endian, 0, d->data + 4);
1616 else
1618 put_16 (big_endian, dialog->ex->weight, d->data + 2);
1619 put_16 (big_endian, dialog->ex->italic, d->data + 4);
1623 *pp = d;
1624 pp = &d->next;
1626 *pp = unicode_to_bin (dialog->font, big_endian);
1627 length += (*pp)->length;
1628 pp = &(*pp)->next;
1631 c = 0;
1632 for (dc = dialog->controls; dc != NULL; dc = dc->next)
1634 unsigned long length;
1635 struct bindata *d;
1636 int dcoff;
1638 ++c;
1640 dword_align_bin (&pp, &length);
1642 d = (struct bindata *) reswr_alloc (sizeof *d);
1643 d->length = dialogex ? 22 : 18;
1644 d->data = (unsigned char *) reswr_alloc (d->length);
1646 length += d->length;
1648 if (! dialogex)
1650 put_32 (big_endian, dc->style, d->data);
1651 put_32 (big_endian, dc->exstyle, d->data + 4);
1652 dcoff = 8;
1654 else
1656 put_32 (big_endian, dc->help, d->data);
1657 put_32 (big_endian, dc->exstyle, d->data + 4);
1658 put_32 (big_endian, dc->style, d->data + 8);
1659 dcoff = 12;
1662 put_16 (big_endian, dc->x, d->data + dcoff);
1663 put_16 (big_endian, dc->y, d->data + dcoff + 2);
1664 put_16 (big_endian, dc->width, d->data + dcoff + 4);
1665 put_16 (big_endian, dc->height, d->data + dcoff + 6);
1666 put_16 (big_endian, dc->id, d->data + dcoff + 8);
1668 *pp = d;
1669 pp = &d->next;
1671 *pp = resid_to_bin (dc->class, big_endian);
1672 length += (*pp)->length;
1673 pp = &(*pp)->next;
1675 *pp = resid_to_bin (dc->text, big_endian);
1676 length += (*pp)->length;
1677 pp = &(*pp)->next;
1679 d = (struct bindata *) reswr_alloc (sizeof *d);
1680 d->length = 2;
1681 d->data = (unsigned char *) reswr_alloc (2);
1683 length += 2;
1685 d->next = NULL;
1686 *pp = d;
1687 pp = &d->next;
1689 if (dc->data == NULL)
1690 put_16 (big_endian, 0, d->data);
1691 else
1693 dword_align_bin (&pp, &length);
1695 *pp = res_to_bin_rcdata (dc->data, big_endian);
1696 while (*pp != NULL)
1698 length += (*pp)->length;
1699 pp = &(*pp)->next;
1704 put_16 (big_endian, c, first->data + off);
1706 return first;
1709 /* Convert a fontdir resource to binary. */
1711 static struct bindata *
1712 res_to_bin_fontdir (fontdirs, big_endian)
1713 const struct fontdir *fontdirs;
1714 int big_endian;
1716 struct bindata *first, **pp;
1717 int c;
1718 const struct fontdir *fd;
1720 first = (struct bindata *) reswr_alloc (sizeof *first);
1721 first->length = 2;
1722 first->data = (unsigned char *) reswr_alloc (2);
1724 first->next = NULL;
1725 pp = &first->next;
1727 c = 0;
1728 for (fd = fontdirs; fd != NULL; fd = fd->next)
1730 struct bindata *d;
1732 ++c;
1734 d = (struct bindata *) reswr_alloc (sizeof *d);
1735 d->length = 2;
1736 d->data = (unsigned char *) reswr_alloc (2);
1738 put_16 (big_endian, fd->index, d->data);
1740 *pp = d;
1741 pp = &d->next;
1743 d = (struct bindata *) reswr_alloc (sizeof *d);
1744 d->length = fd->length;
1745 d->data = (unsigned char *) fd->data;
1747 d->next = NULL;
1748 *pp = d;
1749 pp = &d->next;
1752 put_16 (big_endian, c, first->data);
1754 return first;
1757 /* Convert a group icon resource to binary. */
1759 static struct bindata *
1760 res_to_bin_group_icon (group_icons, big_endian)
1761 const struct group_icon *group_icons;
1762 int big_endian;
1764 struct bindata *first, **pp;
1765 int c;
1766 const struct group_icon *gi;
1768 first = (struct bindata *) reswr_alloc (sizeof *first);
1769 first->length = 6;
1770 first->data = (unsigned char *) reswr_alloc (6);
1772 put_16 (big_endian, 0, first->data);
1773 put_16 (big_endian, 1, first->data + 2);
1775 first->next = NULL;
1776 pp = &first->next;
1778 c = 0;
1779 for (gi = group_icons; gi != NULL; gi = gi->next)
1781 struct bindata *d;
1783 ++c;
1785 d = (struct bindata *) reswr_alloc (sizeof *d);
1786 d->length = 14;
1787 d->data = (unsigned char *) reswr_alloc (14);
1789 d->data[0] = gi->width;
1790 d->data[1] = gi->height;
1791 d->data[2] = gi->colors;
1792 d->data[3] = 0;
1793 put_16 (big_endian, gi->planes, d->data + 4);
1794 put_16 (big_endian, gi->bits, d->data + 6);
1795 put_32 (big_endian, gi->bytes, d->data + 8);
1796 put_16 (big_endian, gi->index, d->data + 12);
1798 d->next = NULL;
1799 *pp = d;
1800 pp = &d->next;
1803 put_16 (big_endian, c, first->data + 4);
1805 return first;
1808 /* Convert a menu resource to binary. */
1810 static struct bindata *
1811 res_to_bin_menu (menu, big_endian)
1812 const struct menu *menu;
1813 int big_endian;
1815 int menuex;
1816 struct bindata *d;
1818 menuex = extended_menu (menu);
1820 d = (struct bindata *) reswr_alloc (sizeof *d);
1821 d->length = menuex ? 8 : 4;
1822 d->data = (unsigned char *) reswr_alloc (d->length);
1824 if (! menuex)
1826 put_16 (big_endian, 0, d->data);
1827 put_16 (big_endian, 0, d->data + 2);
1829 d->next = res_to_bin_menuitems (menu->items, big_endian);
1831 else
1833 put_16 (big_endian, 1, d->data);
1834 put_16 (big_endian, 4, d->data + 2);
1835 put_32 (big_endian, menu->help, d->data + 4);
1837 d->next = res_to_bin_menuexitems (menu->items, big_endian);
1840 return d;
1843 /* Convert menu items to binary. */
1845 static struct bindata *
1846 res_to_bin_menuitems (items, big_endian)
1847 const struct menuitem *items;
1848 int big_endian;
1850 struct bindata *first, **pp;
1851 const struct menuitem *mi;
1853 first = NULL;
1854 pp = &first;
1856 for (mi = items; mi != NULL; mi = mi->next)
1858 struct bindata *d;
1859 int flags;
1861 d = (struct bindata *) reswr_alloc (sizeof *d);
1862 d->length = mi->popup == NULL ? 4 : 2;
1863 d->data = (unsigned char *) reswr_alloc (d->length);
1865 flags = mi->type;
1866 if (mi->next == NULL)
1867 flags |= MENUITEM_ENDMENU;
1868 if (mi->popup != NULL)
1869 flags |= MENUITEM_POPUP;
1871 put_16 (big_endian, flags, d->data);
1873 if (mi->popup == NULL)
1874 put_16 (big_endian, mi->id, d->data + 2);
1876 *pp = d;
1877 pp = &d->next;
1879 *pp = unicode_to_bin (mi->text, big_endian);
1880 pp = &(*pp)->next;
1882 if (mi->popup != NULL)
1884 *pp = res_to_bin_menuitems (mi->popup, big_endian);
1885 while (*pp != NULL)
1886 pp = &(*pp)->next;
1890 return first;
1893 /* Convert menuex items to binary. */
1895 static struct bindata *
1896 res_to_bin_menuexitems (items, big_endian)
1897 const struct menuitem *items;
1898 int big_endian;
1900 struct bindata *first, **pp;
1901 unsigned long length;
1902 const struct menuitem *mi;
1904 first = NULL;
1905 pp = &first;
1907 length = 0;
1909 for (mi = items; mi != NULL; mi = mi->next)
1911 struct bindata *d;
1912 int flags;
1914 dword_align_bin (&pp, &length);
1916 d = (struct bindata *) reswr_alloc (sizeof *d);
1917 d->length = 12;
1918 d->data = (unsigned char *) reswr_alloc (12);
1920 length += 12;
1922 put_32 (big_endian, mi->type, d->data);
1923 put_32 (big_endian, mi->state, d->data + 4);
1924 put_16 (big_endian, mi->id, d->data + 8);
1926 flags = 0;
1927 if (mi->next == NULL)
1928 flags |= 0x80;
1929 if (mi->popup != NULL)
1930 flags |= 1;
1931 put_16 (big_endian, flags, d->data + 10);
1933 *pp = d;
1934 pp = &d->next;
1936 *pp = unicode_to_bin (mi->text, big_endian);
1937 length += (*pp)->length;
1938 pp = &(*pp)->next;
1940 if (mi->popup != NULL)
1942 dword_align_bin (&pp, &length);
1944 d = (struct bindata *) reswr_alloc (sizeof *d);
1945 d->length = 4;
1946 d->data = (unsigned char *) reswr_alloc (4);
1948 put_32 (big_endian, mi->help, d->data);
1950 *pp = d;
1951 pp = &d->next;
1953 *pp = res_to_bin_menuexitems (mi->popup, big_endian);
1954 while (*pp != NULL)
1956 length += (*pp)->length;
1957 pp = &(*pp)->next;
1962 return first;
1965 /* Convert an rcdata resource to binary. This is also used to convert
1966 other information which happens to be stored in rcdata_item lists
1967 to binary. */
1969 static struct bindata *
1970 res_to_bin_rcdata (items, big_endian)
1971 const struct rcdata_item *items;
1972 int big_endian;
1974 struct bindata *first, **pp;
1975 const struct rcdata_item *ri;
1977 first = NULL;
1978 pp = &first;
1980 for (ri = items; ri != NULL; ri = ri->next)
1982 struct bindata *d;
1984 d = (struct bindata *) reswr_alloc (sizeof *d);
1986 switch (ri->type)
1988 default:
1989 abort ();
1991 case RCDATA_WORD:
1992 d->length = 2;
1993 d->data = (unsigned char *) reswr_alloc (2);
1994 put_16 (big_endian, ri->u.word, d->data);
1995 break;
1997 case RCDATA_DWORD:
1998 d->length = 4;
1999 d->data = (unsigned char *) reswr_alloc (4);
2000 put_32 (big_endian, ri->u.dword, d->data);
2001 break;
2003 case RCDATA_STRING:
2004 d->length = ri->u.string.length;
2005 d->data = (unsigned char *) ri->u.string.s;
2006 break;
2008 case RCDATA_WSTRING:
2010 unsigned long i;
2012 d->length = ri->u.wstring.length * 2;
2013 d->data = (unsigned char *) reswr_alloc (d->length);
2014 for (i = 0; i < ri->u.wstring.length; i++)
2015 put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2);
2016 break;
2019 case RCDATA_BUFFER:
2020 d->length = ri->u.buffer.length;
2021 d->data = (unsigned char *) ri->u.buffer.data;
2022 break;
2025 d->next = NULL;
2026 *pp = d;
2027 pp = &d->next;
2030 return first;
2033 /* Convert a stringtable resource to binary. */
2035 static struct bindata *
2036 res_to_bin_stringtable (st, big_endian)
2037 const struct stringtable *st;
2038 int big_endian;
2040 struct bindata *first, **pp;
2041 int i;
2043 first = NULL;
2044 pp = &first;
2046 for (i = 0; i < 16; i++)
2048 int slen, j;
2049 struct bindata *d;
2050 unichar *s;
2052 slen = st->strings[i].length;
2053 s = st->strings[i].string;
2055 d = (struct bindata *) reswr_alloc (sizeof *d);
2056 d->length = 2 + slen * 2;
2057 d->data = (unsigned char *) reswr_alloc (d->length);
2059 put_16 (big_endian, slen, d->data);
2061 for (j = 0; j < slen; j++)
2062 put_16 (big_endian, s[j], d->data + 2 + j * 2);
2064 d->next = NULL;
2065 *pp = d;
2066 pp = &d->next;
2069 return first;
2072 /* Convert an ASCII string to a unicode binary string. This always
2073 returns exactly one bindata structure. */
2075 static struct bindata *
2076 string_to_unicode_bin (s, big_endian)
2077 const char *s;
2078 int big_endian;
2080 size_t len, i;
2081 struct bindata *d;
2083 len = strlen (s);
2085 d = (struct bindata *) reswr_alloc (sizeof *d);
2086 d->length = len * 2 + 2;
2087 d->data = (unsigned char *) reswr_alloc (d->length);
2089 for (i = 0; i < len; i++)
2090 put_16 (big_endian, s[i], d->data + i * 2);
2091 put_16 (big_endian, 0, d->data + i * 2);
2093 d->next = NULL;
2095 return d;
2098 /* Convert a versioninfo resource to binary. */
2100 static struct bindata *
2101 res_to_bin_versioninfo (versioninfo, big_endian)
2102 const struct versioninfo *versioninfo;
2103 int big_endian;
2105 struct bindata *first, **pp;
2106 unsigned long length;
2107 struct ver_info *vi;
2109 first = (struct bindata *) reswr_alloc (sizeof *first);
2110 first->length = 6;
2111 first->data = (unsigned char *) reswr_alloc (6);
2113 length = 6;
2115 if (versioninfo->fixed == NULL)
2116 put_16 (big_endian, 0, first->data + 2);
2117 else
2118 put_16 (big_endian, 52, first->data + 2);
2120 put_16 (big_endian, 0, first->data + 4);
2122 pp = &first->next;
2124 *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian);
2125 length += (*pp)->length;
2126 pp = &(*pp)->next;
2128 dword_align_bin (&pp, &length);
2130 if (versioninfo->fixed != NULL)
2132 const struct fixed_versioninfo *fi;
2133 struct bindata *d;
2135 d = (struct bindata *) reswr_alloc (sizeof *d);
2136 d->length = 52;
2137 d->data = (unsigned char *) reswr_alloc (52);
2139 length += 52;
2141 fi = versioninfo->fixed;
2143 put_32 (big_endian, 0xfeef04bd, d->data);
2144 put_32 (big_endian, 0x10000, d->data + 4);
2145 put_32 (big_endian, fi->file_version_ms, d->data + 8);
2146 put_32 (big_endian, fi->file_version_ls, d->data + 12);
2147 put_32 (big_endian, fi->product_version_ms, d->data + 16);
2148 put_32 (big_endian, fi->product_version_ls, d->data + 20);
2149 put_32 (big_endian, fi->file_flags_mask, d->data + 24);
2150 put_32 (big_endian, fi->file_flags, d->data + 28);
2151 put_32 (big_endian, fi->file_os, d->data + 32);
2152 put_32 (big_endian, fi->file_type, d->data + 36);
2153 put_32 (big_endian, fi->file_subtype, d->data + 40);
2154 put_32 (big_endian, fi->file_date_ms, d->data + 44);
2155 put_32 (big_endian, fi->file_date_ls, d->data + 48);
2157 d->next = NULL;
2158 *pp = d;
2159 pp = &d->next;
2162 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2164 struct bindata *vid;
2165 unsigned long vilen;
2167 dword_align_bin (&pp, &length);
2169 vid = (struct bindata *) reswr_alloc (sizeof *vid);
2170 vid->length = 6;
2171 vid->data = (unsigned char *) reswr_alloc (6);
2173 length += 6;
2174 vilen = 6;
2176 put_16 (big_endian, 0, vid->data + 2);
2177 put_16 (big_endian, 0, vid->data + 4);
2179 *pp = vid;
2180 pp = &vid->next;
2182 switch (vi->type)
2184 default:
2185 abort ();
2187 case VERINFO_STRING:
2189 unsigned long hold, vslen;
2190 struct bindata *vsd;
2191 const struct ver_stringinfo *vs;
2193 *pp = string_to_unicode_bin ("StringFileInfo", big_endian);
2194 length += (*pp)->length;
2195 vilen += (*pp)->length;
2196 pp = &(*pp)->next;
2198 hold = length;
2199 dword_align_bin (&pp, &length);
2200 vilen += length - hold;
2202 vsd = (struct bindata *) reswr_alloc (sizeof *vsd);
2203 vsd->length = 6;
2204 vsd->data = (unsigned char *) reswr_alloc (6);
2206 length += 6;
2207 vilen += 6;
2208 vslen = 6;
2210 put_16 (big_endian, 0, vsd->data + 2);
2211 put_16 (big_endian, 0, vsd->data + 4);
2213 *pp = vsd;
2214 pp = &vsd->next;
2216 *pp = unicode_to_bin (vi->u.string.language, big_endian);
2217 length += (*pp)->length;
2218 vilen += (*pp)->length;
2219 vslen += (*pp)->length;
2220 pp = &(*pp)->next;
2222 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2224 struct bindata *vssd;
2225 unsigned long vsslen;
2227 hold = length;
2228 dword_align_bin (&pp, &length);
2229 vilen += length - hold;
2230 vslen += length - hold;
2232 vssd = (struct bindata *) reswr_alloc (sizeof *vssd);
2233 vssd->length = 6;
2234 vssd->data = (unsigned char *) reswr_alloc (6);
2236 length += 6;
2237 vilen += 6;
2238 vslen += 6;
2239 vsslen = 6;
2241 put_16 (big_endian, 0, vssd->data + 2);
2242 put_16 (big_endian, 1, vssd->data + 4);
2244 *pp = vssd;
2245 pp = &vssd->next;
2247 *pp = unicode_to_bin (vs->key, big_endian);
2248 length += (*pp)->length;
2249 vilen += (*pp)->length;
2250 vslen += (*pp)->length;
2251 vsslen += (*pp)->length;
2252 pp = &(*pp)->next;
2254 hold = length;
2255 dword_align_bin (&pp, &length);
2256 vilen += length - hold;
2257 vslen += length - hold;
2258 vsslen += length - hold;
2260 *pp = unicode_to_bin (vs->value, big_endian);
2261 length += (*pp)->length;
2262 vilen += (*pp)->length;
2263 vslen += (*pp)->length;
2264 vsslen += (*pp)->length;
2265 pp = &(*pp)->next;
2267 put_16 (big_endian, vsslen, vssd->data);
2270 put_16 (big_endian, vslen, vsd->data);
2272 break;
2275 case VERINFO_VAR:
2277 unsigned long hold, vvlen, vvvlen;
2278 struct bindata *vvd;
2279 const struct ver_varinfo *vv;
2281 *pp = string_to_unicode_bin ("VarFileInfo", big_endian);
2282 length += (*pp)->length;
2283 vilen += (*pp)->length;
2284 pp = &(*pp)->next;
2286 hold = length;
2287 dword_align_bin (&pp, &length);
2288 vilen += length - hold;
2290 vvd = (struct bindata *) reswr_alloc (sizeof *vvd);
2291 vvd->length = 6;
2292 vvd->data = (unsigned char *) reswr_alloc (6);
2294 length += 6;
2295 vilen += 6;
2296 vvlen = 6;
2298 put_16 (big_endian, 0, vvd->data + 4);
2300 *pp = vvd;
2301 pp = &vvd->next;
2303 *pp = unicode_to_bin (vi->u.var.key, big_endian);
2304 length += (*pp)->length;
2305 vilen += (*pp)->length;
2306 vvlen += (*pp)->length;
2307 pp = &(*pp)->next;
2309 hold = length;
2310 dword_align_bin (&pp, &length);
2311 vilen += length - hold;
2312 vvlen += length - hold;
2314 vvvlen = 0;
2316 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2318 struct bindata *vvsd;
2320 vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd);
2321 vvsd->length = 4;
2322 vvsd->data = (unsigned char *) reswr_alloc (4);
2324 length += 4;
2325 vilen += 4;
2326 vvlen += 4;
2327 vvvlen += 4;
2329 put_16 (big_endian, vv->language, vvsd->data);
2330 put_16 (big_endian, vv->charset, vvsd->data + 2);
2332 vvsd->next = NULL;
2333 *pp = vvsd;
2334 pp = &vvsd->next;
2337 put_16 (big_endian, vvlen, vvd->data);
2338 put_16 (big_endian, vvvlen, vvd->data + 2);
2340 break;
2344 put_16 (big_endian, vilen, vid->data);
2347 put_16 (big_endian, length, first->data);
2349 return first;
2352 /* Convert a generic resource to binary. */
2354 static struct bindata *
2355 res_to_bin_generic (length, data)
2356 unsigned long length;
2357 const unsigned char *data;
2359 struct bindata *d;
2361 d = (struct bindata *) reswr_alloc (sizeof *d);
2362 d->length = length;
2363 d->data = (unsigned char *) data;
2365 d->next = NULL;
2367 return d;