Update FSF address
[external/binutils.git] / binutils / resbin.c
1 /* resbin.c -- manipulate the Windows binary resource format.
2    Copyright 1997, 1998, 1999, 2002, 2003
3    Free Software Foundation, Inc.
4    Written by Ian Lance Taylor, Cygnus Support.
5
6    This file is part of GNU Binutils.
7
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.
12
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.
17
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.  */
22
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.  */
26
27 #include "bfd.h"
28 #include "bucomm.h"
29 #include "libiberty.h"
30 #include "windres.h"
31
32 /* Macros to swap in values.  */
33
34 #define get_8(s)      (*((unsigned char *)(s)))
35 #define get_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s))
36 #define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s))
37
38 /* Local functions.  */
39
40 static void toosmall (const char *);
41
42 static unichar *get_unicode
43   (const unsigned char *, unsigned long, int, int *);
44 static int get_resid
45   (struct res_id *, const unsigned char *, unsigned long, int);
46 static struct res_resource *bin_to_res_generic
47   (enum res_type, const unsigned char *, unsigned long);
48 static struct res_resource *bin_to_res_cursor
49   (const unsigned char *, unsigned long, int);
50 static struct res_resource *bin_to_res_menu
51   (const unsigned char *, unsigned long, int);
52 static struct menuitem *bin_to_res_menuitems
53   (const unsigned char *, unsigned long, int, int *);
54 static struct menuitem *bin_to_res_menuexitems
55   (const unsigned char *, unsigned long, int, int *);
56 static struct res_resource *bin_to_res_dialog
57   (const unsigned char *, unsigned long, int);
58 static struct res_resource *bin_to_res_string
59   (const unsigned char *, unsigned long, int);
60 static struct res_resource *bin_to_res_fontdir
61   (const unsigned char *, unsigned long, int);
62 static struct res_resource *bin_to_res_accelerators
63   (const unsigned char *, unsigned long, int);
64 static struct res_resource *bin_to_res_rcdata
65   (const unsigned char *, unsigned long, int);
66 static struct res_resource *bin_to_res_group_cursor
67   (const unsigned char *, unsigned long, int);
68 static struct res_resource *bin_to_res_group_icon
69   (const unsigned char *, unsigned long, int);
70 static struct res_resource *bin_to_res_version
71   (const unsigned char *, unsigned long, int);
72 static struct res_resource *bin_to_res_userdata
73   (const unsigned char *, unsigned long, int);
74 static void get_version_header
75   (const unsigned char *, unsigned long, int, const char *,
76    unichar **, int *, int *, int *, int *);
77
78 /* Given a resource type ID, a pointer to data, a length, return a
79    res_resource structure which represents that resource.  The caller
80    is responsible for initializing the res_info and coff_info fields
81    of the returned structure.  */
82
83 struct res_resource *
84 bin_to_res (struct res_id type, const unsigned char *data,
85             unsigned long length, int big_endian)
86 {
87   if (type.named)
88     return bin_to_res_userdata (data, length, big_endian);
89   else
90     {
91       switch (type.u.id)
92         {
93         default:
94           return bin_to_res_userdata (data, length, big_endian);
95         case RT_CURSOR:
96           return bin_to_res_cursor (data, length, big_endian);
97         case RT_BITMAP:
98           return bin_to_res_generic (RES_TYPE_BITMAP, data, length);
99         case RT_ICON:
100           return bin_to_res_generic (RES_TYPE_ICON, data, length);
101         case RT_MENU:
102           return bin_to_res_menu (data, length, big_endian);
103         case RT_DIALOG:
104           return bin_to_res_dialog (data, length, big_endian);
105         case RT_STRING:
106           return bin_to_res_string (data, length, big_endian);
107         case RT_FONTDIR:
108           return bin_to_res_fontdir (data, length, big_endian);
109         case RT_FONT:
110           return bin_to_res_generic (RES_TYPE_FONT, data, length);
111         case RT_ACCELERATOR:
112           return bin_to_res_accelerators (data, length, big_endian);
113         case RT_RCDATA:
114           return bin_to_res_rcdata (data, length, big_endian);
115         case RT_MESSAGETABLE:
116           return bin_to_res_generic (RES_TYPE_MESSAGETABLE, data, length);
117         case RT_GROUP_CURSOR:
118           return bin_to_res_group_cursor (data, length, big_endian);
119         case RT_GROUP_ICON:
120           return bin_to_res_group_icon (data, length, big_endian);
121         case RT_VERSION:
122           return bin_to_res_version (data, length, big_endian);
123         }
124     }
125 }
126
127 /* Give an error if the binary data is too small.  */
128
129 static void
130 toosmall (const char *msg)
131 {
132   fatal (_("%s: not enough binary data"), msg);
133 }
134
135 /* Swap in a NULL terminated unicode string.  */
136
137 static unichar *
138 get_unicode (const unsigned char *data, unsigned long length,
139              int big_endian, int *retlen)
140 {
141   int c, i;
142   unichar *ret;
143
144   c = 0;
145   while (1)
146     {
147       if (length < (unsigned long) c * 2 + 2)
148         toosmall (_("null terminated unicode string"));
149       if (get_16 (big_endian, data + c * 2) == 0)
150         break;
151       ++c;
152     }
153
154   ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
155
156   for (i = 0; i < c; i++)
157     ret[i] = get_16 (big_endian, data + i * 2);
158   ret[i] = 0;
159
160   if (retlen != NULL)
161     *retlen = c;
162
163   return ret;
164 }
165
166 /* Get a resource identifier.  This returns the number of bytes used.  */
167
168 static int
169 get_resid (struct res_id *id, const unsigned char *data,
170            unsigned long length, int big_endian)
171 {
172   int first;
173
174   if (length < 2)
175     toosmall (_("resource ID"));
176
177   first = get_16 (big_endian, data);
178   if (first == 0xffff)
179     {
180       if (length < 4)
181         toosmall (_("resource ID"));
182       id->named = 0;
183       id->u.id = get_16 (big_endian, data + 2);
184       return 4;
185     }
186   else
187     {
188       id->named = 1;
189       id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length);
190       return id->u.n.length * 2 + 2;
191     }
192 }
193
194 /* Convert a resource which just stores uninterpreted data from
195    binary.  */
196
197 struct res_resource *
198 bin_to_res_generic (enum res_type type, const unsigned char *data,
199                     unsigned long length)
200 {
201   struct res_resource *r;
202
203   r = (struct res_resource *) res_alloc (sizeof *r);
204   r->type = type;
205   r->u.data.data = data;
206   r->u.data.length = length;
207
208   return r;
209 }
210
211 /* Convert a cursor resource from binary.  */
212
213 struct res_resource *
214 bin_to_res_cursor (const unsigned char *data, unsigned long length,
215                    int big_endian)
216 {
217   struct cursor *c;
218   struct res_resource *r;
219
220   if (length < 4)
221     toosmall (_("cursor"));
222
223   c = (struct cursor *) res_alloc (sizeof *c);
224   c->xhotspot = get_16 (big_endian, data);
225   c->yhotspot = get_16 (big_endian, data + 2);
226   c->length = length - 4;
227   c->data = data + 4;
228
229   r = (struct res_resource *) res_alloc (sizeof *r);
230   r->type = RES_TYPE_CURSOR;
231   r->u.cursor = c;
232
233   return r;
234 }
235
236 /* Convert a menu resource from binary.  */
237
238 struct res_resource *
239 bin_to_res_menu (const unsigned char *data, unsigned long length,
240                  int big_endian)
241 {
242   struct res_resource *r;
243   struct menu *m;
244   int version, read;
245
246   r = (struct res_resource *) res_alloc (sizeof *r);
247   r->type = RES_TYPE_MENU;
248
249   m = (struct menu *) res_alloc (sizeof *m);
250   r->u.menu = m;
251
252   if (length < 2)
253     toosmall (_("menu header"));
254
255   version = get_16 (big_endian, data);
256
257   if (version == 0)
258     {
259       if (length < 4)
260         toosmall (_("menu header"));
261       m->help = 0;
262       m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian,
263                                        &read);
264     }
265   else if (version == 1)
266     {
267       unsigned int offset;
268
269       if (length < 8)
270         toosmall (_("menuex header"));
271       m->help = get_32 (big_endian, data + 4);
272       offset = get_16 (big_endian, data + 2);
273       if (offset + 4 >= length)
274         toosmall (_("menuex offset"));
275       m->items = bin_to_res_menuexitems (data + 4 + offset,
276                                          length - (4 + offset),
277                                          big_endian,
278                                          &read);
279     }
280   else
281     fatal (_("unsupported menu version %d"), version);
282
283   return r;
284 }
285
286 /* Convert menu items from binary.  */
287
288 static struct menuitem *
289 bin_to_res_menuitems (const unsigned char *data, unsigned long length,
290                       int big_endian, int *read)
291 {
292   struct menuitem *first, **pp;
293
294   first = NULL;
295   pp = &first;
296
297   *read = 0;
298
299   while (length > 0)
300     {
301       int flags, slen, itemlen;
302       unsigned int stroff;
303       struct menuitem *mi;
304
305       if (length < 4)
306         toosmall (_("menuitem header"));
307
308       mi = (struct menuitem *) res_alloc (sizeof *mi);
309       mi->state = 0;
310       mi->help = 0;
311
312       flags = get_16 (big_endian, data);
313       mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
314
315       if ((flags & MENUITEM_POPUP) == 0)
316         stroff = 4;
317       else
318         stroff = 2;
319
320       if (length < stroff + 2)
321         toosmall (_("menuitem header"));
322
323       if (get_16 (big_endian, data + stroff) == 0)
324         {
325           slen = 0;
326           mi->text = NULL;
327         }
328       else
329         mi->text = get_unicode (data + stroff, length - stroff, big_endian,
330                                 &slen);
331
332       itemlen = stroff + slen * 2 + 2;
333
334       if ((flags & MENUITEM_POPUP) == 0)
335         {
336           mi->popup = NULL;
337           mi->id = get_16 (big_endian, data + 2);
338         }
339       else
340         {
341           int subread;
342
343           mi->id = 0;
344           mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen,
345                                             big_endian, &subread);
346           itemlen += subread;
347         }
348
349       mi->next = NULL;
350       *pp = mi;
351       pp = &mi->next;
352
353       data += itemlen;
354       length -= itemlen;
355       *read += itemlen;
356
357       if ((flags & MENUITEM_ENDMENU) != 0)
358         return first;
359     }
360
361   return first;
362 }
363
364 /* Convert menuex items from binary.  */
365
366 static struct menuitem *
367 bin_to_res_menuexitems (const unsigned char *data, unsigned long length,
368                         int big_endian, int *read)
369 {
370   struct menuitem *first, **pp;
371
372   first = NULL;
373   pp = &first;
374
375   *read = 0;
376
377   while (length > 0)
378     {
379       int flags, slen;
380       unsigned int itemlen;
381       struct menuitem *mi;
382
383       if (length < 14)
384         toosmall (_("menuitem header"));
385
386       mi = (struct menuitem *) res_alloc (sizeof *mi);
387       mi->type = get_32 (big_endian, data);
388       mi->state = get_32 (big_endian, data + 4);
389       mi->id = get_16 (big_endian, data + 8);
390
391       flags = get_16 (big_endian, data + 10);
392
393       if (get_16 (big_endian, data + 12) == 0)
394         {
395           slen = 0;
396           mi->text = NULL;
397         }
398       else
399         mi->text = get_unicode (data + 12, length - 12, big_endian, &slen);
400
401       itemlen = 12 + slen * 2 + 2;
402       itemlen = (itemlen + 3) &~ 3;
403
404       if ((flags & 1) == 0)
405         {
406           mi->popup = NULL;
407           mi->help = 0;
408         }
409       else
410         {
411           int subread;
412
413           if (length < itemlen + 4)
414             toosmall (_("menuitem"));
415           mi->help = get_32 (big_endian, data + itemlen);
416           itemlen += 4;
417
418           mi->popup = bin_to_res_menuexitems (data + itemlen,
419                                               length - itemlen,
420                                               big_endian, &subread);
421           itemlen += subread;
422         }
423
424       mi->next = NULL;
425       *pp = mi;
426       pp = &mi->next;
427
428       data += itemlen;
429       length -= itemlen;
430       *read += itemlen;
431
432       if ((flags & 0x80) != 0)
433         return first;
434     }
435
436   return first;
437 }
438
439 /* Convert a dialog resource from binary.  */
440
441 static struct res_resource *
442 bin_to_res_dialog (const unsigned char *data, unsigned long length,
443                    int big_endian)
444 {
445   int signature;
446   struct dialog *d;
447   int c, sublen, i;
448   unsigned int off;
449   struct dialog_control **pp;
450   struct res_resource *r;
451
452   if (length < 18)
453     toosmall (_("dialog header"));
454
455   d = (struct dialog *) res_alloc (sizeof *d);
456
457   signature = get_16 (big_endian, data + 2);
458   if (signature != 0xffff)
459     {
460       d->ex = NULL;
461       d->style = get_32 (big_endian, data);
462       d->exstyle = get_32 (big_endian, data + 4);
463       off = 8;
464     }
465   else
466     {
467       int version;
468
469       version = get_16 (big_endian, data);
470       if (version != 1)
471         fatal (_("unexpected DIALOGEX version %d"), version);
472
473       d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex));
474       d->ex->help = get_32 (big_endian, data + 4);
475       d->exstyle = get_32 (big_endian, data + 8);
476       d->style = get_32 (big_endian, data + 12);
477       off = 16;
478     }
479
480   if (length < off + 10)
481     toosmall (_("dialog header"));
482
483   c = get_16 (big_endian, data + off);
484   d->x = get_16  (big_endian, data + off + 2);
485   d->y = get_16 (big_endian, data + off + 4);
486   d->width = get_16 (big_endian, data + off + 6);
487   d->height = get_16 (big_endian, data + off + 8);
488
489   off += 10;
490
491   sublen = get_resid (&d->menu, data + off, length - off, big_endian);
492   off += sublen;
493
494   sublen = get_resid (&d->class, data + off, length - off, big_endian);
495   off += sublen;
496
497   d->caption = get_unicode (data + off, length - off, big_endian, &sublen);
498   off += sublen * 2 + 2;
499   if (sublen == 0)
500     d->caption = NULL;
501
502   if ((d->style & DS_SETFONT) == 0)
503     {
504       d->pointsize = 0;
505       d->font = NULL;
506       if (d->ex != NULL)
507         {
508           d->ex->weight = 0;
509           d->ex->italic = 0;
510           d->ex->charset = 1; /* Default charset.  */
511         }
512     }
513   else
514     {
515       if (length < off + 2)
516         toosmall (_("dialog font point size"));
517
518       d->pointsize = get_16 (big_endian, data + off);
519       off += 2;
520
521       if (d->ex != NULL)
522         {
523           if (length < off + 4)
524             toosmall (_("dialogex font information"));
525           d->ex->weight = get_16 (big_endian, data + off);
526           d->ex->italic = get_8 (data + off + 2);
527           d->ex->charset = get_8 (data + off + 3);
528           off += 4;
529         }
530
531       d->font = get_unicode (data + off, length - off, big_endian, &sublen);
532       off += sublen * 2 + 2;
533     }
534
535   d->controls = NULL;
536   pp = &d->controls;
537
538   for (i = 0; i < c; i++)
539     {
540       struct dialog_control *dc;
541       int datalen;
542
543       off = (off + 3) &~ 3;
544
545       dc = (struct dialog_control *) res_alloc (sizeof *dc);
546
547       if (d->ex == NULL)
548         {
549           if (length < off + 8)
550             toosmall (_("dialog control"));
551
552           dc->style = get_32 (big_endian, data + off);
553           dc->exstyle = get_32 (big_endian, data + off + 4);
554           dc->help = 0;
555           off += 8;
556         }
557       else
558         {
559           if (length < off + 12)
560             toosmall (_("dialogex control"));
561           dc->help = get_32 (big_endian, data + off);
562           dc->exstyle = get_32 (big_endian, data + off + 4);
563           dc->style = get_32 (big_endian, data + off + 8);
564           off += 12;
565         }
566
567       if (length < off + 10)
568         toosmall (_("dialog control"));
569
570       dc->x = get_16 (big_endian, data + off);
571       dc->y = get_16 (big_endian, data + off + 2);
572       dc->width = get_16 (big_endian, data + off + 4);
573       dc->height = get_16 (big_endian, data + off + 6);
574
575       if (d->ex != NULL)
576         dc->id = get_32 (big_endian, data + off + 8);
577       else
578         dc->id = get_16 (big_endian, data + off + 8);
579
580       off += 10 + (d->ex != NULL ? 2 : 0);
581
582       sublen = get_resid (&dc->class, data + off, length - off, big_endian);
583       off += sublen;
584
585       sublen = get_resid (&dc->text, data + off, length - off, big_endian);
586       off += sublen;
587
588       if (length < off + 2)
589         toosmall (_("dialog control end"));
590
591       datalen = get_16 (big_endian, data + off);
592       off += 2;
593
594       if (datalen == 0)
595         dc->data = NULL;
596       else
597         {
598           off = (off + 3) &~ 3;
599
600           if (length < off + datalen)
601             toosmall (_("dialog control data"));
602
603           dc->data = ((struct rcdata_item *)
604                       res_alloc (sizeof (struct rcdata_item)));
605           dc->data->next = NULL;
606           dc->data->type = RCDATA_BUFFER;
607           dc->data->u.buffer.length = datalen;
608           dc->data->u.buffer.data = data + off;
609
610           off += datalen;
611         }
612
613       dc->next = NULL;
614       *pp = dc;
615       pp = &dc->next;
616     }
617
618   r = (struct res_resource *) res_alloc (sizeof *r);
619   r->type = RES_TYPE_DIALOG;
620   r->u.dialog = d;
621
622   return r;
623 }
624
625 /* Convert a stringtable resource from binary.  */
626
627 static struct res_resource *
628 bin_to_res_string (const unsigned char *data, unsigned long length,
629                    int big_endian)
630 {
631   struct stringtable *st;
632   int i;
633   struct res_resource *r;
634
635   st = (struct stringtable *) res_alloc (sizeof *st);
636
637   for (i = 0; i < 16; i++)
638     {
639       unsigned int slen;
640
641       if (length < 2)
642         toosmall (_("stringtable string length"));
643       slen = get_16 (big_endian, data);
644       st->strings[i].length = slen;
645
646       if (slen > 0)
647         {
648           unichar *s;
649           unsigned int j;
650
651           if (length < 2 + 2 * slen)
652             toosmall (_("stringtable string"));
653
654           s = (unichar *) res_alloc (slen * sizeof (unichar));
655           st->strings[i].string = s;
656
657           for (j = 0; j < slen; j++)
658             s[j] = get_16 (big_endian, data + 2 + j * 2);
659         }
660
661       data += 2 + 2 * slen;
662       length -= 2 + 2 * slen;
663     }
664
665   r = (struct res_resource *) res_alloc (sizeof *r);
666   r->type = RES_TYPE_STRINGTABLE;
667   r->u.stringtable = st;
668
669   return r;
670 }
671
672 /* Convert a fontdir resource from binary.  */
673
674 static struct res_resource *
675 bin_to_res_fontdir (const unsigned char *data, unsigned long length,
676                     int big_endian)
677 {
678   int c, i;
679   struct fontdir *first, **pp;
680   struct res_resource *r;
681
682   if (length < 2)
683     toosmall (_("fontdir header"));
684
685   c = get_16 (big_endian, data);
686
687   first = NULL;
688   pp = &first;
689
690   for (i = 0; i < c; i++)
691     {
692       struct fontdir *fd;
693       unsigned int off;
694
695       if (length < 56)
696         toosmall (_("fontdir"));
697
698       fd = (struct fontdir *) res_alloc (sizeof *fd);
699       fd->index = get_16 (big_endian, data);
700
701       /* To work out the length of the fontdir data, we must get the
702          length of the device name and face name strings, even though
703          we don't store them in the fontdir structure.  The
704          documentation says that these are NULL terminated char
705          strings, not Unicode strings.  */
706
707       off = 56;
708
709       while (off < length && data[off] != '\0')
710         ++off;
711       if (off >= length)
712         toosmall (_("fontdir device name"));
713       ++off;
714
715       while (off < length && data[off] != '\0')
716         ++off;
717       if (off >= length)
718         toosmall (_("fontdir face name"));
719       ++off;
720
721       fd->length = off;
722       fd->data = data;
723
724       fd->next = NULL;
725       *pp = fd;
726       pp = &fd->next;
727
728       /* The documentation does not indicate that any rounding is
729          required.  */
730
731       data += off;
732       length -= off;
733     }
734
735   r = (struct res_resource *) res_alloc (sizeof *r);
736   r->type = RES_TYPE_FONTDIR;
737   r->u.fontdir = first;
738
739   return r;
740 }
741
742 /* Convert an accelerators resource from binary.  */
743
744 static struct res_resource *
745 bin_to_res_accelerators (const unsigned char *data, unsigned long length,
746                          int big_endian)
747 {
748   struct accelerator *first, **pp;
749   struct res_resource *r;
750
751   first = NULL;
752   pp = &first;
753
754   while (1)
755     {
756       struct accelerator *a;
757
758       if (length < 8)
759         toosmall (_("accelerator"));
760
761       a = (struct accelerator *) res_alloc (sizeof *a);
762
763       a->flags = get_16 (big_endian, data);
764       a->key = get_16 (big_endian, data + 2);
765       a->id = get_16 (big_endian, data + 4);
766
767       a->next = NULL;
768       *pp = a;
769       pp = &a->next;
770
771       if ((a->flags & ACC_LAST) != 0)
772         break;
773
774       data += 8;
775       length -= 8;
776     }
777
778   r = (struct res_resource *) res_alloc (sizeof *r);
779   r->type = RES_TYPE_ACCELERATOR;
780   r->u.acc = first;
781
782   return r;
783 }
784
785 /* Convert an rcdata resource from binary.  */
786
787 static struct res_resource *
788 bin_to_res_rcdata (const unsigned char *data, unsigned long length,
789                    int big_endian ATTRIBUTE_UNUSED)
790 {
791   struct rcdata_item *ri;
792   struct res_resource *r;
793
794   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
795
796   ri->next = NULL;
797   ri->type = RCDATA_BUFFER;
798   ri->u.buffer.length = length;
799   ri->u.buffer.data = data;
800
801   r = (struct res_resource *) res_alloc (sizeof *r);
802   r->type = RES_TYPE_RCDATA;
803   r->u.rcdata = ri;
804
805   return r;
806 }
807
808 /* Convert a group cursor resource from binary.  */
809
810 static struct res_resource *
811 bin_to_res_group_cursor (const unsigned char *data, unsigned long length,
812                          int big_endian)
813 {
814   int type, c, i;
815   struct group_cursor *first, **pp;
816   struct res_resource *r;
817
818   if (length < 6)
819     toosmall (_("group cursor header"));
820
821   type = get_16 (big_endian, data + 2);
822   if (type != 2)
823     fatal (_("unexpected group cursor type %d"), type);
824
825   c = get_16 (big_endian, data + 4);
826
827   data += 6;
828   length -= 6;
829
830   first = NULL;
831   pp = &first;
832
833   for (i = 0; i < c; i++)
834     {
835       struct group_cursor *gc;
836
837       if (length < 14)
838         toosmall (_("group cursor"));
839
840       gc = (struct group_cursor *) res_alloc (sizeof *gc);
841
842       gc->width = get_16 (big_endian, data);
843       gc->height = get_16 (big_endian, data + 2);
844       gc->planes = get_16 (big_endian, data + 4);
845       gc->bits = get_16 (big_endian, data + 6);
846       gc->bytes = get_32 (big_endian, data + 8);
847       gc->index = get_16 (big_endian, data + 12);
848
849       gc->next = NULL;
850       *pp = gc;
851       pp = &gc->next;
852
853       data += 14;
854       length -= 14;
855     }
856
857   r = (struct res_resource *) res_alloc (sizeof *r);
858   r->type = RES_TYPE_GROUP_CURSOR;
859   r->u.group_cursor = first;
860
861   return r;
862 }
863
864 /* Convert a group icon resource from binary.  */
865
866 static struct res_resource *
867 bin_to_res_group_icon (const unsigned char *data, unsigned long length,
868                        int big_endian)
869 {
870   int type, c, i;
871   struct group_icon *first, **pp;
872   struct res_resource *r;
873
874   if (length < 6)
875     toosmall (_("group icon header"));
876
877   type = get_16 (big_endian, data + 2);
878   if (type != 1)
879     fatal (_("unexpected group icon type %d"), type);
880
881   c = get_16 (big_endian, data + 4);
882
883   data += 6;
884   length -= 6;
885
886   first = NULL;
887   pp = &first;
888
889   for (i = 0; i < c; i++)
890     {
891       struct group_icon *gi;
892
893       if (length < 14)
894         toosmall (_("group icon"));
895
896       gi = (struct group_icon *) res_alloc (sizeof *gi);
897
898       gi->width = data[0];
899       gi->height = data[1];
900       gi->colors = data[2];
901       gi->planes = get_16 (big_endian, data + 4);
902       gi->bits = get_16 (big_endian, data + 6);
903       gi->bytes = get_32 (big_endian, data + 8);
904       gi->index = get_16 (big_endian, data + 12);
905
906       gi->next = NULL;
907       *pp = gi;
908       pp = &gi->next;
909
910       data += 14;
911       length -= 14;
912     }
913
914   r = (struct res_resource *) res_alloc (sizeof *r);
915   r->type = RES_TYPE_GROUP_ICON;
916   r->u.group_icon = first;
917
918   return r;
919 }
920
921 /* Extract data from a version header.  If KEY is not NULL, then the
922    key must be KEY; otherwise, the key is returned in *PKEY.  This
923    sets *LEN to the total length, *VALLEN to the value length, *TYPE
924    to the type, and *OFF to the offset to the children.  */
925
926 static void
927 get_version_header (const unsigned char *data, unsigned long length,
928                     int big_endian, const char *key, unichar **pkey,
929                     int *len, int *vallen, int *type, int *off)
930 {
931   if (length < 8)
932     toosmall (key);
933
934   *len = get_16 (big_endian, data);
935   *vallen = get_16 (big_endian, data + 2);
936   *type = get_16 (big_endian, data + 4);
937
938   *off = 6;
939
940   length -= 6;
941   data += 6;
942
943   if (key == NULL)
944     {
945       int sublen;
946
947       *pkey = get_unicode (data, length, big_endian, &sublen);
948       *off += sublen * 2 + 2;
949     }
950   else
951     {
952       while (1)
953         {
954           if (length < 2)
955             toosmall (key);
956           if (get_16 (big_endian, data) != (unsigned char) *key)
957             fatal (_("unexpected version string"));
958
959           *off += 2;
960           length -= 2;
961           data += 2;
962
963           if (*key == '\0')
964             break;
965
966           ++key;
967         }
968     }
969
970   *off = (*off + 3) &~ 3;
971 }
972
973 /* Convert a version resource from binary.  */
974
975 static struct res_resource *
976 bin_to_res_version (const unsigned char *data, unsigned long length,
977                     int big_endian)
978 {
979   int verlen, vallen, type, off;
980   struct fixed_versioninfo *fi;
981   struct ver_info *first, **pp;
982   struct versioninfo *v;
983   struct res_resource *r;
984
985   get_version_header (data, length, big_endian, "VS_VERSION_INFO",
986                       (unichar **) NULL, &verlen, &vallen, &type, &off);
987
988   if ((unsigned int) verlen != length)
989     fatal (_("version length %d does not match resource length %lu"),
990            verlen, length);
991
992   if (type != 0)
993     fatal (_("unexpected version type %d"), type);
994
995   data += off;
996   length -= off;
997
998   if (vallen == 0)
999     fi = NULL;
1000   else
1001     {
1002       unsigned long signature, fiv;
1003
1004       if (vallen != 52)
1005         fatal (_("unexpected fixed version information length %d"), vallen);
1006
1007       if (length < 52)
1008         toosmall (_("fixed version info"));
1009
1010       signature = get_32 (big_endian, data);
1011       if (signature != 0xfeef04bd)
1012         fatal (_("unexpected fixed version signature %lu"), signature);
1013
1014       fiv = get_32 (big_endian, data + 4);
1015       if (fiv != 0 && fiv != 0x10000)
1016         fatal (_("unexpected fixed version info version %lu"), fiv);
1017
1018       fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi);
1019
1020       fi->file_version_ms = get_32 (big_endian, data + 8);
1021       fi->file_version_ls = get_32 (big_endian, data + 12);
1022       fi->product_version_ms = get_32 (big_endian, data + 16);
1023       fi->product_version_ls = get_32 (big_endian, data + 20);
1024       fi->file_flags_mask = get_32 (big_endian, data + 24);
1025       fi->file_flags = get_32 (big_endian, data + 28);
1026       fi->file_os = get_32 (big_endian, data + 32);
1027       fi->file_type = get_32 (big_endian, data + 36);
1028       fi->file_subtype = get_32 (big_endian, data + 40);
1029       fi->file_date_ms = get_32 (big_endian, data + 44);
1030       fi->file_date_ls = get_32 (big_endian, data + 48);
1031
1032       data += 52;
1033       length -= 52;
1034     }
1035
1036   first = NULL;
1037   pp = &first;
1038
1039   while (length > 0)
1040     {
1041       struct ver_info *vi;
1042       int ch;
1043
1044       if (length < 8)
1045         toosmall (_("version var info"));
1046
1047       vi = (struct ver_info *) res_alloc (sizeof *vi);
1048
1049       ch = get_16 (big_endian, data + 6);
1050
1051       if (ch == 'S')
1052         {
1053           struct ver_stringinfo **ppvs;
1054
1055           vi->type = VERINFO_STRING;
1056
1057           get_version_header (data, length, big_endian, "StringFileInfo",
1058                               (unichar **) NULL, &verlen, &vallen, &type,
1059                               &off);
1060
1061           if (vallen != 0)
1062             fatal (_("unexpected stringfileinfo value length %d"), vallen);
1063
1064           data += off;
1065           length -= off;
1066
1067           get_version_header (data, length, big_endian, (const char *) NULL,
1068                               &vi->u.string.language, &verlen, &vallen,
1069                               &type, &off);
1070
1071           if (vallen != 0)
1072             fatal (_("unexpected version stringtable value length %d"), vallen);
1073
1074           data += off;
1075           length -= off;
1076           verlen -= off;
1077
1078           vi->u.string.strings = NULL;
1079           ppvs = &vi->u.string.strings;
1080
1081           /* It's convenient to round verlen to a 4 byte alignment,
1082              since we round the subvariables in the loop.  */
1083           verlen = (verlen + 3) &~ 3;
1084
1085           while (verlen > 0)
1086             {
1087               struct ver_stringinfo *vs;
1088               int subverlen, vslen, valoff;
1089
1090               vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1091
1092               get_version_header (data, length, big_endian,
1093                                   (const char *) NULL, &vs->key, &subverlen,
1094                                   &vallen, &type, &off);
1095
1096               subverlen = (subverlen + 3) &~ 3;
1097
1098               data += off;
1099               length -= off;
1100
1101               vs->value = get_unicode (data, length, big_endian, &vslen);
1102               valoff = vslen * 2 + 2;
1103               valoff = (valoff + 3) &~ 3;
1104
1105               if (off + valoff != subverlen)
1106                 fatal (_("unexpected version string length %d != %d + %d"),
1107                        subverlen, off, valoff);
1108
1109               vs->next = NULL;
1110               *ppvs = vs;
1111               ppvs = &vs->next;
1112
1113               data += valoff;
1114               length -= valoff;
1115
1116               if (verlen < subverlen)
1117                 fatal (_("unexpected version string length %d < %d"),
1118                        verlen, subverlen);
1119
1120               verlen -= subverlen;
1121             }
1122         }
1123       else if (ch == 'V')
1124         {
1125           struct ver_varinfo **ppvv;
1126
1127           vi->type = VERINFO_VAR;
1128
1129           get_version_header (data, length, big_endian, "VarFileInfo",
1130                               (unichar **) NULL, &verlen, &vallen, &type,
1131                               &off);
1132
1133           if (vallen != 0)
1134             fatal (_("unexpected varfileinfo value length %d"), vallen);
1135
1136           data += off;
1137           length -= off;
1138
1139           get_version_header (data, length, big_endian, (const char *) NULL,
1140                               &vi->u.var.key, &verlen, &vallen, &type, &off);
1141
1142           data += off;
1143           length -= off;
1144
1145           vi->u.var.var = NULL;
1146           ppvv = &vi->u.var.var;
1147
1148           while (vallen > 0)
1149             {
1150               struct ver_varinfo *vv;
1151
1152               if (length < 4)
1153                 toosmall (_("version varfileinfo"));
1154
1155               vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1156
1157               vv->language = get_16 (big_endian, data);
1158               vv->charset = get_16 (big_endian, data + 2);
1159
1160               vv->next = NULL;
1161               *ppvv = vv;
1162               ppvv = &vv->next;
1163
1164               data += 4;
1165               length -= 4;
1166
1167               if (vallen < 4)
1168                 fatal (_("unexpected version value length %d"), vallen);
1169
1170               vallen -= 4;
1171             }
1172         }
1173       else
1174         fatal (_("unexpected version string"));
1175
1176       vi->next = NULL;
1177       *pp = vi;
1178       pp = &vi->next;
1179     }
1180
1181   v = (struct versioninfo *) res_alloc (sizeof *v);
1182   v->fixed = fi;
1183   v->var = first;
1184
1185   r = (struct res_resource *) res_alloc (sizeof *r);
1186   r->type = RES_TYPE_VERSIONINFO;
1187   r->u.versioninfo = v;
1188
1189   return r;
1190 }
1191
1192 /* Convert an arbitrary user defined resource from binary.  */
1193
1194 static struct res_resource *
1195 bin_to_res_userdata (const unsigned char *data, unsigned long length,
1196                      int big_endian ATTRIBUTE_UNUSED)
1197 {
1198   struct rcdata_item *ri;
1199   struct res_resource *r;
1200
1201   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1202
1203   ri->next = NULL;
1204   ri->type = RCDATA_BUFFER;
1205   ri->u.buffer.length = length;
1206   ri->u.buffer.data = data;
1207
1208   r = (struct res_resource *) res_alloc (sizeof *r);
1209   r->type = RES_TYPE_USERDATA;
1210   r->u.rcdata = ri;
1211
1212   return r;
1213 }
1214 \f
1215 /* Macros to swap out values.  */
1216
1217 #define put_8(v, s)      (*((unsigned char *) (s)) = (unsigned char) (v))
1218 #define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
1219 #define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
1220
1221 /* Local functions used to convert resources to binary format.  */
1222
1223 static void dword_align_bin (struct bindata ***, unsigned long *);
1224 static struct bindata *resid_to_bin (struct res_id, int);
1225 static struct bindata *unicode_to_bin (const unichar *, int);
1226 static struct bindata *res_to_bin_accelerator
1227   (const struct accelerator *, int);
1228 static struct bindata *res_to_bin_cursor
1229   (const struct cursor *, int);
1230 static struct bindata *res_to_bin_group_cursor
1231   (const struct group_cursor *, int);
1232 static struct bindata *res_to_bin_dialog
1233   (const struct dialog *, int);
1234 static struct bindata *res_to_bin_fontdir
1235   (const struct fontdir *, int);
1236 static struct bindata *res_to_bin_group_icon
1237   (const struct group_icon *, int);
1238 static struct bindata *res_to_bin_menu
1239   (const struct menu *, int);
1240 static struct bindata *res_to_bin_menuitems
1241   (const struct menuitem *, int);
1242 static struct bindata *res_to_bin_menuexitems
1243   (const struct menuitem *, int);
1244 static struct bindata *res_to_bin_rcdata
1245   (const struct rcdata_item *, int);
1246 static struct bindata *res_to_bin_stringtable
1247   (const struct stringtable *, int);
1248 static struct bindata *string_to_unicode_bin (const char *, int);
1249 static struct bindata *res_to_bin_versioninfo
1250   (const struct versioninfo *, int);
1251 static struct bindata *res_to_bin_generic
1252   (unsigned long, const unsigned char *);
1253
1254 /* Convert a resource to binary.  */
1255
1256 struct bindata *
1257 res_to_bin (const struct res_resource *res, int big_endian)
1258 {
1259   switch (res->type)
1260     {
1261     default:
1262       abort ();
1263     case RES_TYPE_BITMAP:
1264     case RES_TYPE_FONT:
1265     case RES_TYPE_ICON:
1266     case RES_TYPE_MESSAGETABLE:
1267       return res_to_bin_generic (res->u.data.length, res->u.data.data);
1268     case RES_TYPE_ACCELERATOR:
1269       return res_to_bin_accelerator (res->u.acc, big_endian);
1270     case RES_TYPE_CURSOR:
1271       return res_to_bin_cursor (res->u.cursor, big_endian);
1272     case RES_TYPE_GROUP_CURSOR:
1273       return res_to_bin_group_cursor (res->u.group_cursor, big_endian);
1274     case RES_TYPE_DIALOG:
1275       return res_to_bin_dialog (res->u.dialog, big_endian);
1276     case RES_TYPE_FONTDIR:
1277       return res_to_bin_fontdir (res->u.fontdir, big_endian);
1278     case RES_TYPE_GROUP_ICON:
1279       return res_to_bin_group_icon (res->u.group_icon, big_endian);
1280     case RES_TYPE_MENU:
1281       return res_to_bin_menu (res->u.menu, big_endian);
1282     case RES_TYPE_RCDATA:
1283       return res_to_bin_rcdata (res->u.rcdata, big_endian);
1284     case RES_TYPE_STRINGTABLE:
1285       return res_to_bin_stringtable (res->u.stringtable, big_endian);
1286     case RES_TYPE_USERDATA:
1287       return res_to_bin_rcdata (res->u.rcdata, big_endian);
1288     case RES_TYPE_VERSIONINFO:
1289       return res_to_bin_versioninfo (res->u.versioninfo, big_endian);
1290     }
1291 }
1292
1293 /* Align to a 32 bit boundary.  PPP points to the of a list of bindata
1294    structures.  LENGTH points to the length of the structures.  If
1295    necessary, this adds a new bindata to bring length up to a 32 bit
1296    boundary.  It updates *PPP and *LENGTH.  */
1297
1298 static void
1299 dword_align_bin (struct bindata ***ppp, unsigned long *length)
1300 {
1301   int add;
1302   struct bindata *d;
1303
1304   if ((*length & 3) == 0)
1305     return;
1306
1307   add = 4 - (*length & 3);
1308
1309   d = (struct bindata *) reswr_alloc (sizeof *d);
1310   d->length = add;
1311   d->data = (unsigned char *) reswr_alloc (add);
1312   memset (d->data, 0, add);
1313
1314   d->next = NULL;
1315   **ppp = d;
1316   *ppp = &(**ppp)->next;
1317
1318   *length += add;
1319 }
1320
1321 /* Convert a resource ID to binary.  This always returns exactly one
1322    bindata structure.  */
1323
1324 static struct bindata *
1325 resid_to_bin (struct res_id id, int big_endian)
1326 {
1327   struct bindata *d;
1328
1329   d = (struct bindata *) reswr_alloc (sizeof *d);
1330
1331   if (! id.named)
1332     {
1333       d->length = 4;
1334       d->data = (unsigned char *) reswr_alloc (4);
1335       put_16 (big_endian, 0xffff, d->data);
1336       put_16 (big_endian, id.u.id, d->data + 2);
1337     }
1338   else
1339     {
1340       int i;
1341
1342       d->length = id.u.n.length * 2 + 2;
1343       d->data = (unsigned char *) reswr_alloc (d->length);
1344       for (i = 0; i < id.u.n.length; i++)
1345         put_16 (big_endian, id.u.n.name[i], d->data + i * 2);
1346       put_16 (big_endian, 0, d->data + i * 2);
1347     }
1348
1349   d->next = NULL;
1350
1351   return d;
1352 }
1353
1354 /* Convert a null terminated unicode string to binary.  This always
1355    returns exactly one bindata structure.  */
1356
1357 static struct bindata *
1358 unicode_to_bin (const unichar *str, int big_endian)
1359 {
1360   int len;
1361   struct bindata *d;
1362
1363   len = 0;
1364   if (str != NULL)
1365     {
1366       const unichar *s;
1367
1368       for (s = str; *s != 0; s++)
1369         ++len;
1370     }
1371
1372   d = (struct bindata *) reswr_alloc (sizeof *d);
1373   d->length = len * 2 + 2;
1374   d->data = (unsigned char *) reswr_alloc (d->length);
1375
1376   if (str == NULL)
1377     put_16 (big_endian, 0, d->data);
1378   else
1379     {
1380       const unichar *s;
1381       int i;
1382
1383       for (s = str, i = 0; *s != 0; s++, i++)
1384         put_16 (big_endian, *s, d->data + i * 2);
1385       put_16 (big_endian, 0, d->data + i * 2);
1386     }
1387
1388   d->next = NULL;
1389
1390   return d;
1391 }
1392
1393 /* Convert an accelerator resource to binary.  */
1394
1395 static struct bindata *
1396 res_to_bin_accelerator (const struct accelerator *accelerators,
1397                         int big_endian)
1398 {
1399   struct bindata *first, **pp;
1400   const struct accelerator *a;
1401
1402   first = NULL;
1403   pp = &first;
1404
1405   for (a = accelerators; a != NULL; a = a->next)
1406     {
1407       struct bindata *d;
1408
1409       d = (struct bindata *) reswr_alloc (sizeof *d);
1410       d->length = 8;
1411       d->data = (unsigned char *) reswr_alloc (8);
1412
1413       put_16 (big_endian,
1414               a->flags | (a->next != NULL ? 0 : ACC_LAST),
1415               d->data);
1416       put_16 (big_endian, a->key, d->data + 2);
1417       put_16 (big_endian, a->id, d->data + 4);
1418       put_16 (big_endian, 0, d->data + 8);
1419
1420       d->next = NULL;
1421       *pp = d;
1422       pp = &d->next;
1423     }
1424
1425   return first;
1426 }
1427
1428 /* Convert a cursor resource to binary.  */
1429
1430 static struct bindata *
1431 res_to_bin_cursor (const struct cursor *c, int big_endian)
1432 {
1433   struct bindata *d;
1434
1435   d = (struct bindata *) reswr_alloc (sizeof *d);
1436   d->length = 4;
1437   d->data = (unsigned char *) reswr_alloc (4);
1438
1439   put_16 (big_endian, c->xhotspot, d->data);
1440   put_16 (big_endian, c->yhotspot, d->data + 2);
1441
1442   d->next = (struct bindata *) reswr_alloc (sizeof *d);
1443   d->next->length = c->length;
1444   d->next->data = (unsigned char *) c->data;
1445   d->next->next = NULL;
1446
1447   return d;
1448 }
1449
1450 /* Convert a group cursor resource to binary.  */
1451
1452 static struct bindata *
1453 res_to_bin_group_cursor (const struct group_cursor *group_cursors,
1454                          int big_endian)
1455 {
1456   struct bindata *first, **pp;
1457   int c;
1458   const struct group_cursor *gc;
1459
1460   first = (struct bindata *) reswr_alloc (sizeof *first);
1461   first->length = 6;
1462   first->data = (unsigned char *) reswr_alloc (6);
1463
1464   put_16 (big_endian, 0, first->data);
1465   put_16 (big_endian, 2, first->data + 2);
1466
1467   first->next = NULL;
1468   pp = &first->next;
1469
1470   c = 0;
1471   for (gc = group_cursors; gc != NULL; gc = gc->next)
1472     {
1473       struct bindata *d;
1474
1475       ++c;
1476
1477       d = (struct bindata *) reswr_alloc (sizeof *d);
1478       d->length = 14;
1479       d->data = (unsigned char *) reswr_alloc (14);
1480
1481       put_16 (big_endian, gc->width, d->data);
1482       put_16 (big_endian, gc->height, d->data + 2);
1483       put_16 (big_endian, gc->planes, d->data + 4);
1484       put_16 (big_endian, gc->bits, d->data + 6);
1485       put_32 (big_endian, gc->bytes, d->data + 8);
1486       put_16 (big_endian, gc->index, d->data + 12);
1487
1488       d->next = NULL;
1489       *pp = d;
1490       pp = &d->next;
1491     }
1492
1493   put_16 (big_endian, c, first->data + 4);
1494
1495   return first;
1496 }
1497
1498 /* Convert a dialog resource to binary.  */
1499
1500 static struct bindata *
1501 res_to_bin_dialog (const struct dialog *dialog, int big_endian)
1502 {
1503   int dialogex;
1504   struct bindata *first, **pp;
1505   unsigned long length;
1506   int off, c;
1507   struct dialog_control *dc;
1508
1509   dialogex = extended_dialog (dialog);
1510
1511   first = (struct bindata *) reswr_alloc (sizeof *first);
1512   first->length = dialogex ? 26 : 18;
1513   first->data = (unsigned char *) reswr_alloc (first->length);
1514
1515   length = first->length;
1516
1517   if (! dialogex)
1518     {
1519       put_32 (big_endian, dialog->style, first->data);
1520       put_32 (big_endian, dialog->exstyle, first->data + 4);
1521       off = 8;
1522     }
1523   else
1524     {
1525       put_16 (big_endian, 1, first->data);
1526       put_16 (big_endian, 0xffff, first->data + 2);
1527
1528       if (dialog->ex == NULL)
1529         put_32 (big_endian, 0, first->data + 4);
1530       else
1531         put_32 (big_endian, dialog->ex->help, first->data + 4);
1532       put_32 (big_endian, dialog->exstyle, first->data + 8);
1533       put_32 (big_endian, dialog->style, first->data + 12);
1534       off = 16;
1535     }
1536
1537   put_16 (big_endian, dialog->x, first->data + off + 2);
1538   put_16 (big_endian, dialog->y, first->data + off + 4);
1539   put_16 (big_endian, dialog->width, first->data + off + 6);
1540   put_16 (big_endian, dialog->height, first->data + off + 8);
1541
1542   pp = &first->next;
1543
1544   *pp = resid_to_bin (dialog->menu, big_endian);
1545   length += (*pp)->length;
1546   pp = &(*pp)->next;
1547
1548   *pp = resid_to_bin (dialog->class, big_endian);
1549   length += (*pp)->length;
1550   pp = &(*pp)->next;
1551
1552   *pp = unicode_to_bin (dialog->caption, big_endian);
1553   length += (*pp)->length;
1554   pp = &(*pp)->next;
1555
1556   if ((dialog->style & DS_SETFONT) != 0)
1557     {
1558       struct bindata *d;
1559
1560       d = (struct bindata *) reswr_alloc (sizeof *d);
1561       d->length = dialogex ? 6 : 2;
1562       d->data = (unsigned char *) reswr_alloc (d->length);
1563
1564       length += d->length;
1565
1566       put_16 (big_endian, dialog->pointsize, d->data);
1567
1568       if (dialogex)
1569         {
1570           if (dialog->ex == NULL)
1571             {
1572               put_16 (big_endian, 0, d->data + 2);
1573               put_8 (0, d->data + 4);
1574               put_8 (1, d->data + 5);
1575             }
1576           else
1577             {
1578               put_16 (big_endian, dialog->ex->weight, d->data + 2);
1579               put_8 (dialog->ex->italic, d->data + 4);
1580               put_8 (dialog->ex->charset, d->data + 5);
1581             }
1582         }
1583
1584       *pp = d;
1585       pp = &d->next;
1586
1587       *pp = unicode_to_bin (dialog->font, big_endian);
1588       length += (*pp)->length;
1589       pp = &(*pp)->next;
1590     }
1591
1592   c = 0;
1593   for (dc = dialog->controls; dc != NULL; dc = dc->next)
1594     {
1595       struct bindata *d;
1596       int dcoff;
1597
1598       ++c;
1599
1600       dword_align_bin (&pp, &length);
1601
1602       d = (struct bindata *) reswr_alloc (sizeof *d);
1603       d->length = dialogex ? 24 : 18;
1604       d->data = (unsigned char *) reswr_alloc (d->length);
1605
1606       length += d->length;
1607
1608       if (! dialogex)
1609         {
1610           put_32 (big_endian, dc->style, d->data);
1611           put_32 (big_endian, dc->exstyle, d->data + 4);
1612           dcoff = 8;
1613         }
1614       else
1615         {
1616           put_32 (big_endian, dc->help, d->data);
1617           put_32 (big_endian, dc->exstyle, d->data + 4);
1618           put_32 (big_endian, dc->style, d->data + 8);
1619           dcoff = 12;
1620         }
1621
1622       put_16 (big_endian, dc->x, d->data + dcoff);
1623       put_16 (big_endian, dc->y, d->data + dcoff + 2);
1624       put_16 (big_endian, dc->width, d->data + dcoff + 4);
1625       put_16 (big_endian, dc->height, d->data + dcoff + 6);
1626
1627       if (dialogex)
1628         put_32 (big_endian, dc->id, d->data + dcoff + 8);
1629       else
1630         put_16 (big_endian, dc->id, d->data + dcoff + 8);
1631
1632       *pp = d;
1633       pp = &d->next;
1634
1635       *pp = resid_to_bin (dc->class, big_endian);
1636       length += (*pp)->length;
1637       pp = &(*pp)->next;
1638
1639       *pp = resid_to_bin (dc->text, big_endian);
1640       length += (*pp)->length;
1641       pp = &(*pp)->next;
1642
1643       d = (struct bindata *) reswr_alloc (sizeof *d);
1644       d->length = 2;
1645       d->data = (unsigned char *) reswr_alloc (2);
1646
1647       length += 2;
1648
1649       d->next = NULL;
1650       *pp = d;
1651       pp = &d->next;
1652
1653       if (dc->data == NULL)
1654         put_16 (big_endian, 0, d->data);
1655       else
1656         {
1657           unsigned long sublen;
1658
1659           dword_align_bin (&pp, &length);
1660
1661           *pp = res_to_bin_rcdata (dc->data, big_endian);
1662           sublen = 0;
1663           while (*pp != NULL)
1664             {
1665               sublen += (*pp)->length;
1666               pp = &(*pp)->next;
1667             }
1668
1669           put_16 (big_endian, sublen, d->data);
1670
1671           length += sublen;
1672         }
1673     }
1674   put_16 (big_endian, c, first->data + off);
1675
1676   return first;
1677 }
1678
1679 /* Convert a fontdir resource to binary.  */
1680
1681 static struct bindata *
1682 res_to_bin_fontdir (const struct fontdir *fontdirs, int big_endian)
1683 {
1684   struct bindata *first, **pp;
1685   int c;
1686   const struct fontdir *fd;
1687
1688   first = (struct bindata *) reswr_alloc (sizeof *first);
1689   first->length = 2;
1690   first->data = (unsigned char *) reswr_alloc (2);
1691
1692   first->next = NULL;
1693   pp = &first->next;
1694
1695   c = 0;
1696   for (fd = fontdirs; fd != NULL; fd = fd->next)
1697     {
1698       struct bindata *d;
1699
1700       ++c;
1701
1702       d = (struct bindata *) reswr_alloc (sizeof *d);
1703       d->length = 2;
1704       d->data = (unsigned char *) reswr_alloc (2);
1705
1706       put_16 (big_endian, fd->index, d->data);
1707
1708       *pp = d;
1709       pp = &d->next;
1710
1711       d = (struct bindata *) reswr_alloc (sizeof *d);
1712       d->length = fd->length;
1713       d->data = (unsigned char *) fd->data;
1714
1715       d->next = NULL;
1716       *pp = d;
1717       pp = &d->next;
1718     }
1719
1720   put_16 (big_endian, c, first->data);
1721
1722   return first;
1723 }
1724
1725 /* Convert a group icon resource to binary.  */
1726
1727 static struct bindata *
1728 res_to_bin_group_icon (const struct group_icon *group_icons, int big_endian)
1729 {
1730   struct bindata *first, **pp;
1731   int c;
1732   const struct group_icon *gi;
1733
1734   first = (struct bindata *) reswr_alloc (sizeof *first);
1735   first->length = 6;
1736   first->data = (unsigned char *) reswr_alloc (6);
1737
1738   put_16 (big_endian, 0, first->data);
1739   put_16 (big_endian, 1, first->data + 2);
1740
1741   first->next = NULL;
1742   pp = &first->next;
1743
1744   c = 0;
1745   for (gi = group_icons; gi != NULL; gi = gi->next)
1746     {
1747       struct bindata *d;
1748
1749       ++c;
1750
1751       d = (struct bindata *) reswr_alloc (sizeof *d);
1752       d->length = 14;
1753       d->data = (unsigned char *) reswr_alloc (14);
1754
1755       d->data[0] = gi->width;
1756       d->data[1] = gi->height;
1757       d->data[2] = gi->colors;
1758       d->data[3] = 0;
1759       put_16 (big_endian, gi->planes, d->data + 4);
1760       put_16 (big_endian, gi->bits, d->data + 6);
1761       put_32 (big_endian, gi->bytes, d->data + 8);
1762       put_16 (big_endian, gi->index, d->data + 12);
1763
1764       d->next = NULL;
1765       *pp = d;
1766       pp = &d->next;
1767     }
1768
1769   put_16 (big_endian, c, first->data + 4);
1770
1771   return first;
1772 }
1773
1774 /* Convert a menu resource to binary.  */
1775
1776 static struct bindata *
1777 res_to_bin_menu (const struct menu *menu, int big_endian)
1778 {
1779   int menuex;
1780   struct bindata *d;
1781
1782   menuex = extended_menu (menu);
1783
1784   d = (struct bindata *) reswr_alloc (sizeof *d);
1785   d->length = menuex ? 8 : 4;
1786   d->data = (unsigned char *) reswr_alloc (d->length);
1787
1788   if (! menuex)
1789     {
1790       put_16 (big_endian, 0, d->data);
1791       put_16 (big_endian, 0, d->data + 2);
1792
1793       d->next = res_to_bin_menuitems (menu->items, big_endian);
1794     }
1795   else
1796     {
1797       put_16 (big_endian, 1, d->data);
1798       put_16 (big_endian, 4, d->data + 2);
1799       put_32 (big_endian, menu->help, d->data + 4);
1800
1801       d->next = res_to_bin_menuexitems (menu->items, big_endian);
1802     }
1803
1804   return d;
1805 }
1806
1807 /* Convert menu items to binary.  */
1808
1809 static struct bindata *
1810 res_to_bin_menuitems (const struct menuitem *items, int big_endian)
1811 {
1812   struct bindata *first, **pp;
1813   const struct menuitem *mi;
1814
1815   first = NULL;
1816   pp = &first;
1817
1818   for (mi = items; mi != NULL; mi = mi->next)
1819     {
1820       struct bindata *d;
1821       int flags;
1822
1823       d = (struct bindata *) reswr_alloc (sizeof *d);
1824       d->length = mi->popup == NULL ? 4 : 2;
1825       d->data = (unsigned char *) reswr_alloc (d->length);
1826
1827       flags = mi->type;
1828       if (mi->next == NULL)
1829         flags |= MENUITEM_ENDMENU;
1830       if (mi->popup != NULL)
1831         flags |= MENUITEM_POPUP;
1832
1833       put_16 (big_endian, flags, d->data);
1834
1835       if (mi->popup == NULL)
1836         put_16 (big_endian, mi->id, d->data + 2);
1837
1838       *pp = d;
1839       pp = &d->next;
1840
1841       *pp = unicode_to_bin (mi->text, big_endian);
1842       pp = &(*pp)->next;
1843
1844       if (mi->popup != NULL)
1845         {
1846           *pp = res_to_bin_menuitems (mi->popup, big_endian);
1847           while (*pp != NULL)
1848             pp = &(*pp)->next;
1849         }
1850     }
1851
1852   return first;
1853 }
1854
1855 /* Convert menuex items to binary.  */
1856
1857 static struct bindata *
1858 res_to_bin_menuexitems (const struct menuitem *items, int big_endian)
1859 {
1860   struct bindata *first, **pp;
1861   unsigned long length;
1862   const struct menuitem *mi;
1863
1864   first = NULL;
1865   pp = &first;
1866
1867   length = 0;
1868
1869   for (mi = items; mi != NULL; mi = mi->next)
1870     {
1871       struct bindata *d;
1872       int flags;
1873
1874       dword_align_bin (&pp, &length);
1875
1876       d = (struct bindata *) reswr_alloc (sizeof *d);
1877       d->length = 12;
1878       d->data = (unsigned char *) reswr_alloc (12);
1879
1880       length += 12;
1881
1882       put_32 (big_endian, mi->type, d->data);
1883       put_32 (big_endian, mi->state, d->data + 4);
1884       put_16 (big_endian, mi->id, d->data + 8);
1885
1886       flags = 0;
1887       if (mi->next == NULL)
1888         flags |= 0x80;
1889       if (mi->popup != NULL)
1890         flags |= 1;
1891       put_16 (big_endian, flags, d->data + 10);
1892
1893       *pp = d;
1894       pp = &d->next;
1895
1896       *pp = unicode_to_bin (mi->text, big_endian);
1897       length += (*pp)->length;
1898       pp = &(*pp)->next;
1899
1900       if (mi->popup != NULL)
1901         {
1902           dword_align_bin (&pp, &length);
1903
1904           d = (struct bindata *) reswr_alloc (sizeof *d);
1905           d->length = 4;
1906           d->data = (unsigned char *) reswr_alloc (4);
1907
1908           put_32 (big_endian, mi->help, d->data);
1909
1910           *pp = d;
1911           pp = &d->next;
1912
1913           *pp = res_to_bin_menuexitems (mi->popup, big_endian);
1914           while (*pp != NULL)
1915             {
1916               length += (*pp)->length;
1917               pp = &(*pp)->next;
1918             }
1919         }
1920     }
1921
1922   return first;
1923 }
1924
1925 /* Convert an rcdata resource to binary.  This is also used to convert
1926    other information which happens to be stored in rcdata_item lists
1927    to binary.  */
1928
1929 static struct bindata *
1930 res_to_bin_rcdata (const struct rcdata_item *items, int big_endian)
1931 {
1932   struct bindata *first, **pp;
1933   const struct rcdata_item *ri;
1934
1935   first = NULL;
1936   pp = &first;
1937
1938   for (ri = items; ri != NULL; ri = ri->next)
1939     {
1940       struct bindata *d;
1941
1942       d = (struct bindata *) reswr_alloc (sizeof *d);
1943
1944       switch (ri->type)
1945         {
1946         default:
1947           abort ();
1948
1949         case RCDATA_WORD:
1950           d->length = 2;
1951           d->data = (unsigned char *) reswr_alloc (2);
1952           put_16 (big_endian, ri->u.word, d->data);
1953           break;
1954
1955         case RCDATA_DWORD:
1956           d->length = 4;
1957           d->data = (unsigned char *) reswr_alloc (4);
1958           put_32 (big_endian, ri->u.dword, d->data);
1959           break;
1960
1961         case RCDATA_STRING:
1962           d->length = ri->u.string.length;
1963           d->data = (unsigned char *) ri->u.string.s;
1964           break;
1965
1966         case RCDATA_WSTRING:
1967           {
1968             unsigned long i;
1969
1970             d->length = ri->u.wstring.length * 2;
1971             d->data = (unsigned char *) reswr_alloc (d->length);
1972             for (i = 0; i < ri->u.wstring.length; i++)
1973               put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2);
1974             break;
1975           }
1976
1977         case RCDATA_BUFFER:
1978           d->length = ri->u.buffer.length;
1979           d->data = (unsigned char *) ri->u.buffer.data;
1980           break;
1981         }
1982
1983       d->next = NULL;
1984       *pp = d;
1985       pp = &d->next;
1986     }
1987
1988   return first;
1989 }
1990
1991 /* Convert a stringtable resource to binary.  */
1992
1993 static struct bindata *
1994 res_to_bin_stringtable (const struct stringtable *st, int big_endian)
1995 {
1996   struct bindata *first, **pp;
1997   int i;
1998
1999   first = NULL;
2000   pp = &first;
2001
2002   for (i = 0; i < 16; i++)
2003     {
2004       int slen, j;
2005       struct bindata *d;
2006       unichar *s;
2007
2008       slen = st->strings[i].length;
2009       s = st->strings[i].string;
2010
2011       d = (struct bindata *) reswr_alloc (sizeof *d);
2012       d->length = 2 + slen * 2;
2013       d->data = (unsigned char *) reswr_alloc (d->length);
2014
2015       put_16 (big_endian, slen, d->data);
2016
2017       for (j = 0; j < slen; j++)
2018         put_16 (big_endian, s[j], d->data + 2 + j * 2);
2019
2020       d->next = NULL;
2021       *pp = d;
2022       pp = &d->next;
2023     }
2024
2025   return first;
2026 }
2027
2028 /* Convert an ASCII string to a unicode binary string.  This always
2029    returns exactly one bindata structure.  */
2030
2031 static struct bindata *
2032 string_to_unicode_bin (const char *s, int big_endian)
2033 {
2034   size_t len, i;
2035   struct bindata *d;
2036
2037   len = strlen (s);
2038
2039   d = (struct bindata *) reswr_alloc (sizeof *d);
2040   d->length = len * 2 + 2;
2041   d->data = (unsigned char *) reswr_alloc (d->length);
2042
2043   for (i = 0; i < len; i++)
2044     put_16 (big_endian, s[i], d->data + i * 2);
2045   put_16 (big_endian, 0, d->data + i * 2);
2046
2047   d->next = NULL;
2048
2049   return d;
2050 }
2051
2052 /* Convert a versioninfo resource to binary.  */
2053
2054 static struct bindata *
2055 res_to_bin_versioninfo (const struct versioninfo *versioninfo, int big_endian)
2056 {
2057   struct bindata *first, **pp;
2058   unsigned long length;
2059   struct ver_info *vi;
2060
2061   first = (struct bindata *) reswr_alloc (sizeof *first);
2062   first->length = 6;
2063   first->data = (unsigned char *) reswr_alloc (6);
2064
2065   length = 6;
2066
2067   if (versioninfo->fixed == NULL)
2068     put_16 (big_endian, 0, first->data + 2);
2069   else
2070     put_16 (big_endian, 52, first->data + 2);
2071
2072   put_16 (big_endian, 0, first->data + 4);
2073
2074   pp = &first->next;
2075
2076   *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian);
2077   length += (*pp)->length;
2078   pp = &(*pp)->next;
2079
2080   dword_align_bin (&pp, &length);
2081
2082   if (versioninfo->fixed != NULL)
2083     {
2084       const struct fixed_versioninfo *fi;
2085       struct bindata *d;
2086
2087       d = (struct bindata *) reswr_alloc (sizeof *d);
2088       d->length = 52;
2089       d->data = (unsigned char *) reswr_alloc (52);
2090
2091       length += 52;
2092
2093       fi = versioninfo->fixed;
2094
2095       put_32 (big_endian, 0xfeef04bd, d->data);
2096       put_32 (big_endian, 0x10000, d->data + 4);
2097       put_32 (big_endian, fi->file_version_ms, d->data + 8);
2098       put_32 (big_endian, fi->file_version_ls, d->data + 12);
2099       put_32 (big_endian, fi->product_version_ms, d->data + 16);
2100       put_32 (big_endian, fi->product_version_ls, d->data + 20);
2101       put_32 (big_endian, fi->file_flags_mask, d->data + 24);
2102       put_32 (big_endian, fi->file_flags, d->data + 28);
2103       put_32 (big_endian, fi->file_os, d->data + 32);
2104       put_32 (big_endian, fi->file_type, d->data + 36);
2105       put_32 (big_endian, fi->file_subtype, d->data + 40);
2106       put_32 (big_endian, fi->file_date_ms, d->data + 44);
2107       put_32 (big_endian, fi->file_date_ls, d->data + 48);
2108
2109       d->next = NULL;
2110       *pp = d;
2111       pp = &d->next;
2112     }
2113
2114   for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2115     {
2116       struct bindata *vid;
2117       unsigned long vilen;
2118
2119       dword_align_bin (&pp, &length);
2120
2121       vid = (struct bindata *) reswr_alloc (sizeof *vid);
2122       vid->length = 6;
2123       vid->data = (unsigned char *) reswr_alloc (6);
2124
2125       length += 6;
2126       vilen = 6;
2127
2128       put_16 (big_endian, 0, vid->data + 2);
2129       put_16 (big_endian, 0, vid->data + 4);
2130
2131       *pp = vid;
2132       pp = &vid->next;
2133
2134       switch (vi->type)
2135         {
2136         default:
2137           abort ();
2138
2139         case VERINFO_STRING:
2140           {
2141             unsigned long hold, vslen;
2142             struct bindata *vsd;
2143             const struct ver_stringinfo *vs;
2144
2145             *pp = string_to_unicode_bin ("StringFileInfo", big_endian);
2146             length += (*pp)->length;
2147             vilen += (*pp)->length;
2148             pp = &(*pp)->next;
2149
2150             hold = length;
2151             dword_align_bin (&pp, &length);
2152             vilen += length - hold;
2153
2154             vsd = (struct bindata *) reswr_alloc (sizeof *vsd);
2155             vsd->length = 6;
2156             vsd->data = (unsigned char *) reswr_alloc (6);
2157
2158             length += 6;
2159             vilen += 6;
2160             vslen = 6;
2161
2162             put_16 (big_endian, 0, vsd->data + 2);
2163             put_16 (big_endian, 0, vsd->data + 4);
2164
2165             *pp = vsd;
2166             pp = &vsd->next;
2167
2168             *pp = unicode_to_bin (vi->u.string.language, big_endian);
2169             length += (*pp)->length;
2170             vilen += (*pp)->length;
2171             vslen += (*pp)->length;
2172             pp = &(*pp)->next;
2173
2174             for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2175               {
2176                 struct bindata *vssd;
2177                 unsigned long vsslen;
2178
2179                 hold = length;
2180                 dword_align_bin (&pp, &length);
2181                 vilen += length - hold;
2182                 vslen += length - hold;
2183
2184                 vssd = (struct bindata *) reswr_alloc (sizeof *vssd);
2185                 vssd->length = 6;
2186                 vssd->data = (unsigned char *) reswr_alloc (6);
2187
2188                 length += 6;
2189                 vilen += 6;
2190                 vslen += 6;
2191                 vsslen = 6;
2192
2193                 put_16 (big_endian, 1, vssd->data + 4);
2194
2195                 *pp = vssd;
2196                 pp = &vssd->next;
2197
2198                 *pp = unicode_to_bin (vs->key, big_endian);
2199                 length += (*pp)->length;
2200                 vilen += (*pp)->length;
2201                 vslen += (*pp)->length;
2202                 vsslen += (*pp)->length;
2203                 pp = &(*pp)->next;
2204
2205                 hold = length;
2206                 dword_align_bin (&pp, &length);
2207                 vilen += length - hold;
2208                 vslen += length - hold;
2209                 vsslen += length - hold;
2210
2211                 *pp = unicode_to_bin (vs->value, big_endian);
2212                 put_16 (big_endian, (*pp)->length / 2, vssd->data + 2);
2213                 length += (*pp)->length;
2214                 vilen += (*pp)->length;
2215                 vslen += (*pp)->length;
2216                 vsslen += (*pp)->length;
2217                 pp = &(*pp)->next;
2218
2219                 put_16 (big_endian, vsslen, vssd->data);
2220               }
2221
2222             put_16 (big_endian, vslen, vsd->data);
2223
2224             break;
2225           }
2226
2227         case VERINFO_VAR:
2228           {
2229             unsigned long hold, vvlen, vvvlen;
2230             struct bindata *vvd;
2231             const struct ver_varinfo *vv;
2232
2233             *pp = string_to_unicode_bin ("VarFileInfo", big_endian);
2234             length += (*pp)->length;
2235             vilen += (*pp)->length;
2236             pp = &(*pp)->next;
2237
2238             hold = length;
2239             dword_align_bin (&pp, &length);
2240             vilen += length - hold;
2241
2242             vvd = (struct bindata *) reswr_alloc (sizeof *vvd);
2243             vvd->length = 6;
2244             vvd->data = (unsigned char *) reswr_alloc (6);
2245
2246             length += 6;
2247             vilen += 6;
2248             vvlen = 6;
2249
2250             put_16 (big_endian, 0, vvd->data + 4);
2251
2252             *pp = vvd;
2253             pp = &vvd->next;
2254
2255             *pp = unicode_to_bin (vi->u.var.key, big_endian);
2256             length += (*pp)->length;
2257             vilen += (*pp)->length;
2258             vvlen += (*pp)->length;
2259             pp = &(*pp)->next;
2260
2261             hold = length;
2262             dword_align_bin (&pp, &length);
2263             vilen += length - hold;
2264             vvlen += length - hold;
2265
2266             vvvlen = 0;
2267
2268             for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2269               {
2270                 struct bindata *vvsd;
2271
2272                 vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd);
2273                 vvsd->length = 4;
2274                 vvsd->data = (unsigned char *) reswr_alloc (4);
2275
2276                 length += 4;
2277                 vilen += 4;
2278                 vvlen += 4;
2279                 vvvlen += 4;
2280
2281                 put_16 (big_endian, vv->language, vvsd->data);
2282                 put_16 (big_endian, vv->charset, vvsd->data + 2);
2283
2284                 vvsd->next = NULL;
2285                 *pp = vvsd;
2286                 pp = &vvsd->next;
2287               }
2288
2289             put_16 (big_endian, vvlen, vvd->data);
2290             put_16 (big_endian, vvvlen, vvd->data + 2);
2291
2292             break;
2293           }
2294         }
2295
2296       put_16 (big_endian, vilen, vid->data);
2297     }
2298
2299   put_16 (big_endian, length, first->data);
2300
2301   return first;
2302 }
2303
2304 /* Convert a generic resource to binary.  */
2305
2306 static struct bindata *
2307 res_to_bin_generic (unsigned long length, const unsigned char *data)
2308 {
2309   struct bindata *d;
2310
2311   d = (struct bindata *) reswr_alloc (sizeof *d);
2312   d->length = length;
2313   d->data = (unsigned char *) data;
2314
2315   d->next = NULL;
2316
2317   return d;
2318 }