From Ton van Overbeek <tvoverbe@wk.estec.esa.nl>:
[external/binutils.git] / binutils / resbin.c
1 /* resbin.c -- manipulate the Windows binary resource format.
2    Copyright 1997 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor, Cygnus Support.
4
5    This file is part of GNU Binutils.
6
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.
11
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.
16
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.  */
21
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.  */
25
26 #include "bfd.h"
27 #include "bucomm.h"
28 #include "libiberty.h"
29 #include "windres.h"
30
31 /* Macros to swap in values.  */
32
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))
35
36 /* Local functions.  */
37
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));
71
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.  */
76
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;
83 {
84   if (type.named)
85     return bin_to_res_userdata (data, length, big_endian);
86   else
87     {
88       switch (type.u.id)
89         {
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);
120         }
121     }
122 }
123
124 /* Give an error if the binary data is too small.  */
125
126 static void
127 toosmall (msg)
128      const char *msg;
129 {
130   fatal ("%s: not enough binary data", msg);
131 }
132
133 /* Swap in a NULL terminated unicode string.  */
134
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;
141 {
142   int c, i;
143   unichar *ret;
144
145   c = 0;
146   while (1)
147     {
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;
153     }
154
155   ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
156
157   for (i = 0; i < c; i++)
158     ret[i] = get_16 (big_endian, data + i * 2);
159   ret[i] = 0;
160
161   if (retlen != NULL)
162     *retlen = c;
163
164   return ret;
165 }
166
167 /* Get a resource identifier.  This returns the number of bytes used.  */
168
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;
175 {
176   int first;
177
178   if (length < 2)
179     toosmall ("resource ID");
180
181   first = get_16 (big_endian, data);
182   if (first == 0xffff)
183     {
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;
189     }
190   else
191     {
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;
195     }
196 }
197
198 /* Convert a resource which just stores uninterpreted data from
199    binary.  */
200
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;
206 {
207   struct res_resource *r;
208
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;
213
214   return r;
215 }
216
217 /* Convert a cursor resource from binary.  */
218
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;
224 {
225   struct cursor *c;
226   struct res_resource *r;
227
228   if (length < 4)
229     toosmall ("cursor");
230
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;
236
237   r = (struct res_resource *) res_alloc (sizeof *r);
238   r->type = RES_TYPE_CURSOR;
239   r->u.cursor = c;
240
241   return r;
242 }
243
244 /* Convert a menu resource from binary.  */
245
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;
251 {
252   struct res_resource *r;
253   struct menu *m;
254   int version, read;
255
256   r = (struct res_resource *) res_alloc (sizeof *r);
257   r->type = RES_TYPE_MENU;
258
259   m = (struct menu *) res_alloc (sizeof *m);
260   r->u.menu = m;
261
262   if (length < 2)
263     toosmall ("menu header");
264
265   version = get_16 (big_endian, data);
266
267   if (version == 0)
268     {
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);
274     }
275   else if (version == 1)
276     {
277       int offset;
278
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);
289     }
290   else
291     fatal ("unsupported menu version %d", version);
292
293   return r;
294 }
295
296 /* Convert menu items from binary.  */
297
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;
304 {
305   struct menuitem *first, **pp;
306
307   first = NULL;
308   pp = &first;
309
310   *read = 0;
311
312   while (length > 0)
313     {
314       int flags, stroff, slen, itemlen;
315       struct menuitem *mi;
316
317       if (length < 4)
318         toosmall ("menuitem header");
319
320       mi = (struct menuitem *) res_alloc (sizeof *mi);
321       mi->state = 0;
322       mi->help = 0;
323
324       flags = get_16 (big_endian, data);
325       mi->type = flags;
326
327       if ((flags & MENUITEM_POPUP) == 0)
328         stroff = 4;
329       else
330         stroff = 2;
331
332       if (length < stroff + 2)
333         toosmall ("menuitem header");
334
335       if (get_16 (big_endian, data + stroff) == 0)
336         {
337           slen = 0;
338           mi->text = NULL;
339         }
340       else
341         mi->text = get_unicode (data + stroff, length - stroff, big_endian,
342                                 &slen);
343
344       itemlen = stroff + slen * 2 + 2;
345
346       if ((flags & MENUITEM_POPUP) == 0)
347         {
348           mi->popup = NULL;
349           mi->id = get_16 (big_endian, data + 2);
350         }
351       else
352         {
353           int subread;
354
355           mi->id = 0;
356           mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen,
357                                             big_endian, &subread);
358           itemlen += subread;
359         }
360
361       mi->next = NULL;
362       *pp = mi;
363       pp = &mi->next;
364
365       data += itemlen;
366       length -= itemlen;
367       *read += itemlen;
368
369       if ((flags & MENUITEM_ENDMENU) != 0)
370         return first;
371     }
372
373   return first;
374 }
375
376 /* Convert menuex items from binary.  */
377
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;
384 {
385   struct menuitem *first, **pp;
386
387   first = NULL;
388   pp = &first;
389
390   *read = 0;
391
392   while (length > 0)
393     {
394       int flags, slen, itemlen;
395       struct menuitem *mi;
396
397       if (length < 14)
398         toosmall ("menuitem header");
399
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);
404
405       flags = get_16 (big_endian, data + 10);
406
407       if (get_16 (big_endian, data + 12) == 0)
408         {
409           slen = 0;
410           mi->text = NULL;
411         }
412       else
413         mi->text = get_unicode (data + 12, length - 12, big_endian, &slen);
414
415       itemlen = 12 + slen * 2 + 2;
416       itemlen = (itemlen + 3) &~ 3;
417
418       if ((flags & 1) == 0)
419         {
420           mi->popup = NULL;
421           mi->help = 0;
422         }
423       else
424         {
425           int subread;
426
427           if (length < itemlen + 4)
428             toosmall ("menuitem");
429           mi->help = get_32 (big_endian, data + itemlen);
430           itemlen += 4;
431
432           mi->popup = bin_to_res_menuexitems (data + itemlen,
433                                               length - itemlen,
434                                               big_endian, &subread);
435           itemlen += subread;
436         }
437
438       mi->next = NULL;
439       *pp = mi;
440       pp = &mi->next;
441
442       data += itemlen;
443       length -= itemlen;
444       *read += itemlen;
445
446       if ((flags & 0x80) != 0)
447         return first;
448     }
449
450   return first;
451 }
452
453 /* Convert a dialog resource from binary.  */
454
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;
460 {
461   int version;
462   struct dialog *d;
463   int c, sublen, off, i;
464   struct dialog_control **pp;
465   struct res_resource *r;
466
467   if (length < 18)
468     toosmall ("dialog header");
469
470   d = (struct dialog *) res_alloc (sizeof *d);
471
472   version = get_16 (big_endian, data);
473   if (version != 0xffff)
474     {
475       d->ex = NULL;
476       d->style = get_32 (big_endian, data);
477       d->exstyle = get_32 (big_endian, data + 4);
478       off = 8;
479     }
480   else
481     {
482       int signature;
483
484       signature = get_16 (big_endian, data + 2);
485       if (signature != 1)
486         fatal ("unexpected dialog signature %d", signature);
487
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;
493     }
494
495   if (length < off + 10)
496     toosmall ("dialog header");
497
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);
503
504   off += 10;
505
506   sublen = get_resid (&d->menu, data + off, length - off, big_endian);
507   off += sublen;
508
509   sublen = get_resid (&d->class, data + off, length - off, big_endian);
510   off += sublen;
511
512   d->caption = get_unicode (data + off, length - off, big_endian, &sublen);
513   off += sublen * 2 + 2;
514
515   if ((d->style & DS_SETFONT) == 0)
516     {
517       d->pointsize = 0;
518       d->font = NULL;
519       if (d->ex != NULL)
520         {
521           d->ex->weight = 0;
522           d->ex->italic = 0;
523         }
524     }
525   else
526     {
527       if (length < off + 2)
528         toosmall ("dialog font point size");
529
530       d->pointsize = get_16 (big_endian, data + off);
531       off += 2;
532
533       if (d->ex != NULL)
534         {
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;
540         }
541
542       d->font = get_unicode (data + off, length - off, big_endian, &sublen);
543       off += sublen * 2 + 2;
544     }
545
546   d->controls = NULL;
547   pp = &d->controls;
548
549   for (i = 0; i < c; i++)
550     {
551       struct dialog_control *dc;
552       int datalen;
553
554       off = (off + 3) &~ 3;
555
556       dc = (struct dialog_control *) res_alloc (sizeof *dc);
557
558       if (d->ex == NULL)
559         {
560           if (length < off + 8)
561             toosmall ("dialog control");
562
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;
567         }
568       else
569         {
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;
576         }
577
578       if (length < off + 10)
579         toosmall ("dialog control");
580
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);
586
587       off += 10;
588
589       sublen = get_resid (&dc->class, data + off, length - off, big_endian);
590       off += sublen;
591
592       sublen = get_resid (&dc->text, data + off, length - off, big_endian);
593       off += sublen;
594
595       if (length < off + 2)
596         toosmall ("dialog control end");
597
598       datalen = get_16 (big_endian, data + off);
599       off += 2;
600
601       if (datalen == 0)
602         dc->data = NULL;
603       else
604         {
605           off = (off + 3) &~ 3;
606
607           if (length < off + datalen)
608             toosmall ("dialog control data");
609
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;
616
617           off += datalen;         
618         }
619
620       dc->next = NULL;
621       *pp = dc;
622       pp = &dc->next;
623     }
624
625   r = (struct res_resource *) res_alloc (sizeof *r);
626   r->type = RES_TYPE_DIALOG;
627   r->u.dialog = d;
628
629   return r;
630 }
631
632 /* Convert a stringtable resource from binary.  */
633
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;
639 {
640   struct stringtable *st;
641   int i;
642   struct res_resource *r;
643
644   st = (struct stringtable *) res_alloc (sizeof *st);
645
646   for (i = 0; i < 16; i++)
647     {
648       int slen;
649
650       if (length < 2)
651         toosmall ("stringtable string length");
652       slen = get_16 (big_endian, data);
653       st->strings[i].length = slen;
654
655       if (slen > 0)
656         {
657           unichar *s;
658           int j;
659
660           if (length < 2 + 2 * slen)
661             toosmall ("stringtable string");
662
663           s = (unichar *) res_alloc (slen * sizeof (unichar));
664           st->strings[i].string = s;
665
666           for (j = 0; j < slen; j++)
667             s[j] = get_16 (big_endian, data + 2 + j * 2);
668         }
669
670       data += 2 + 2 * slen;
671       length -= 2 + 2 * slen;
672     }
673
674   r = (struct res_resource *) res_alloc (sizeof *r);
675   r->type = RES_TYPE_STRINGTABLE;
676   r->u.stringtable = st;
677
678   return r;
679 }
680
681 /* Convert a fontdir resource from binary.  */
682
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;
688 {
689   int c, i;
690   struct fontdir *first, **pp;
691   struct res_resource *r;
692
693   if (length < 2)
694     toosmall ("fontdir header");
695
696   c = get_16 (big_endian, data);
697
698   first = NULL;
699   pp = &first;
700
701   for (i = 0; i < c; i++)
702     {
703       struct fontdir *fd;
704       int off;
705
706       if (length < 56)
707         toosmall ("fontdir");
708
709       fd = (struct fontdir *) res_alloc (sizeof *fd);
710       fd->index = get_16 (big_endian, data);
711
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.  */
717
718       off = 56;
719
720       while (off < length && data[off] != '\0')
721         ++off;
722       if (off >= length)
723         toosmall ("fontdir device name");
724       ++off;
725
726       while (off < length && data[off] != '\0')
727         ++off;
728       if (off >= length)
729         toosmall ("fontdir face name");
730       ++off;
731
732       fd->length = off;
733       fd->data = data;
734
735       fd->next = NULL;
736       *pp = fd;
737       pp = &fd->next;
738
739       /* The documentation does not indicate that any rounding is
740          required.  */
741
742       data += off;
743       length -= off;
744     }
745
746   r = (struct res_resource *) res_alloc (sizeof *r);
747   r->type = RES_TYPE_FONTDIR;
748   r->u.fontdir = first;
749
750   return r;
751 }
752
753 /* Convert an accelerators resource from binary.  */
754
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;
760 {
761   struct accelerator *first, **pp;
762   struct res_resource *r;
763
764   first = NULL;
765   pp = &first;
766
767   while (1)
768     {
769       struct accelerator *a;
770
771       if (length < 8)
772         toosmall ("accelerator");
773
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);
777
778       a->next = NULL;
779       *pp = a;
780       pp = &a->next;
781
782       if ((a->flags & ACC_LAST) != 0)
783         break;
784
785       data += 8;
786       length -= 8;
787     }
788
789   r = (struct res_resource *) res_alloc (sizeof *r);
790   r->type = RES_TYPE_ACCELERATOR;
791   r->u.acc = first;
792
793   return r;
794 }
795
796 /* Convert an rcdata resource from binary.  */
797
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;
803 {
804   struct rcdata_item *ri;
805   struct res_resource *r;
806
807   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
808
809   ri->next = NULL;
810   ri->type = RCDATA_BUFFER;
811   ri->u.buffer.length = length;
812   ri->u.buffer.data = data;
813
814   r = (struct res_resource *) res_alloc (sizeof *r);
815   r->type = RES_TYPE_RCDATA;
816   r->u.rcdata = ri;
817
818   return r;
819 }
820
821 /* Convert a group cursor resource from binary.  */
822
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;
828 {
829   int type, c, i;
830   struct group_cursor *first, **pp;
831   struct res_resource *r;
832
833   if (length < 6)
834     toosmall ("group cursor header");
835
836   type = get_16 (big_endian, data + 2);
837   if (type != 2)
838     fatal ("unexpected group cursor type %d", type);
839
840   c = get_16 (big_endian, data + 4);
841
842   data += 6;
843   length -= 6;
844
845   first = NULL;
846   pp = &first;
847
848   for (i = 0; i < c; i++)
849     {
850       struct group_cursor *gc;
851
852       if (length < 14)
853         toosmall ("group cursor");
854
855       gc = (struct group_cursor *) res_alloc (sizeof *gc);
856
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);
863
864       gc->next = NULL;
865       *pp = gc;
866       pp = &gc->next;
867
868       data += 14;
869       length -= 14;
870     }
871
872   r = (struct res_resource *) res_alloc (sizeof *r);
873   r->type = RES_TYPE_GROUP_CURSOR;
874   r->u.group_cursor = first;
875
876   return r;
877 }
878
879 /* Convert a group icon resource from binary.  */
880
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;
886 {
887   int type, c, i;
888   struct group_icon *first, **pp;
889   struct res_resource *r;
890
891   if (length < 6)
892     toosmall ("group icon header");
893
894   type = get_16 (big_endian, data + 2);
895   if (type != 1)
896     fatal ("unexpected group icon type %d", type);
897
898   c = get_16 (big_endian, data + 4);
899
900   data += 6;
901   length -= 6;
902
903   first = NULL;
904   pp = &first;
905
906   for (i = 0; i < c; i++)
907     {
908       struct group_icon *gi;
909
910       if (length < 14)
911         toosmall ("group icon");
912
913       gi = (struct group_icon *) res_alloc (sizeof *gi);
914
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);
922
923       gi->next = NULL;
924       *pp = gi;
925       pp = &gi->next;
926
927       data += 14;
928       length -= 14;
929     }
930
931   r = (struct res_resource *) res_alloc (sizeof *r);
932   r->type = RES_TYPE_GROUP_ICON;
933   r->u.group_icon = first;
934
935   return r;
936 }
937
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.  */
942
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;
955 {
956   if (length < 8)
957     toosmall (key);
958
959   *len = get_16 (big_endian, data);
960   *vallen = get_16 (big_endian, data + 2);
961   *type = get_16 (big_endian, data + 4);
962
963   *off = 6;
964
965   length -= 6;
966   data += 6;
967
968   if (key == NULL)
969     {
970       int sublen;
971
972       *pkey = get_unicode (data, length, big_endian, &sublen);
973       *off += sublen * 2 + 2;
974     }
975   else
976     {
977       while (1)
978         {
979           if (length < 2)
980             toosmall (key);
981           if (get_16 (big_endian, data) != *key)
982             fatal ("unexpected version string");
983
984           *off += 2;
985           length -= 2;
986           data += 2;
987
988           if (*key == '\0')
989             break;
990
991           ++key;
992         }
993     }
994
995   *off = (*off + 3) &~ 3;
996 }
997
998 /* Convert a version resource from binary.  */
999
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;
1005 {
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;
1011
1012   get_version_header (data, length, big_endian, "VS_VERSION_INFO",
1013                       (unichar *) NULL, &verlen, &vallen, &type, &off);
1014
1015   if (verlen != length)
1016     fatal ("version length %d does not match resource length %lu",
1017            verlen, length);
1018
1019   if (type != 0)
1020     fatal ("unexpected version type %d", type);
1021
1022   data += off;
1023   length -= off;
1024
1025   if (vallen == 0)
1026     fi = NULL;
1027   else
1028     {
1029       unsigned long signature, fiv;
1030
1031       if (vallen != 52)
1032         fatal ("unexpected fixed version information length %d", vallen);
1033
1034       if (length < 52)
1035         toosmall ("fixed version info");
1036
1037       signature = get_32 (big_endian, data);
1038       if (signature != 0xfeef04bd)
1039         fatal ("unexpected fixed version signature %lu", signature);
1040
1041       fiv = get_32 (big_endian, data + 4);
1042       if (fiv != 0 && fiv != 0x10000)
1043         fatal ("unexpected fixed version info version %lu", fiv);
1044
1045       fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi);
1046
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);
1058
1059       data += 52;
1060       length -= 52;
1061     }
1062
1063   first = NULL;
1064   pp = &first;
1065
1066   while (length > 0)
1067     {
1068       struct ver_info *vi;
1069       int ch;
1070
1071       if (length < 8)
1072         toosmall ("version var info");
1073
1074       vi = (struct ver_info *) res_alloc (sizeof *vi);
1075
1076       ch = get_16 (big_endian, data + 6);
1077
1078       if (ch == 'S')
1079         {
1080           struct ver_stringinfo **ppvs;
1081
1082           vi->type = VERINFO_STRING;
1083
1084           get_version_header (data, length, big_endian, "StringFileInfo",
1085                               (unichar *) NULL, &verlen, &vallen, &type,
1086                               &off);
1087
1088           if (vallen != 0)
1089             fatal ("unexpected stringfileinfo value length %d", vallen);
1090
1091           data += off;
1092           length -= off;
1093
1094           get_version_header (data, length, big_endian, (const char *) NULL,
1095                               &vi->u.string.language, &verlen, &vallen,
1096                               &type, &off);
1097
1098           if (vallen != 0)
1099             fatal ("unexpected version stringtable value length %d", vallen);
1100
1101           data += off;
1102           length -= off;
1103           verlen -= off;
1104
1105           vi->u.string.strings = NULL;
1106           ppvs = &vi->u.string.strings;
1107
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;
1111
1112           while (verlen > 0)
1113             {
1114               struct ver_stringinfo *vs;
1115               int subverlen, vslen, valoff;
1116
1117               vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1118
1119               get_version_header (data, length, big_endian,
1120                                   (const char *) NULL, &vs->key, &subverlen,
1121                                   &vallen, &type, &off);
1122
1123               subverlen = (subverlen + 3) &~ 3;
1124
1125               data += off;
1126               length -= off;
1127
1128               vs->value = get_unicode (data, length, big_endian, &vslen);
1129               valoff = vslen * 2 + 2;
1130               valoff = (valoff + 3) &~ 3;
1131
1132               if (off + valoff != subverlen)
1133                 fatal ("unexpected version string length %d != %d + %d",
1134                        subverlen, off, valoff);
1135
1136               vs->next = NULL;
1137               *ppvs = vs;
1138               ppvs = &vs->next;
1139
1140               data += valoff;
1141               length -= valoff;
1142
1143               if (verlen < subverlen)
1144                 fatal ("unexpected version string length %d < %d",
1145                        verlen, subverlen);
1146
1147               verlen -= subverlen;
1148             }
1149         }
1150       else if (ch == 'V')
1151         {
1152           struct ver_varinfo **ppvv;
1153
1154           vi->type = VERINFO_VAR;
1155
1156           get_version_header (data, length, big_endian, "VarFileInfo",
1157                               (unichar *) NULL, &verlen, &vallen, &type,
1158                               &off);
1159
1160           if (vallen != 0)
1161             fatal ("unexpected varfileinfo value length %d", vallen);
1162
1163           data += off;
1164           length -= off;
1165
1166           get_version_header (data, length, big_endian, (const char *) NULL,
1167                               &vi->u.var.key, &verlen, &vallen, &type, &off);
1168
1169           data += off;
1170           length -= off;
1171
1172           vi->u.var.var = NULL;
1173           ppvv = &vi->u.var.var;
1174
1175           while (vallen > 0)
1176             {
1177               struct ver_varinfo *vv;
1178
1179               if (length < 4)
1180                 toosmall ("version varfileinfo");
1181
1182               vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1183
1184               vv->language = get_16 (big_endian, data);
1185               vv->charset = get_16 (big_endian, data + 2);
1186
1187               vv->next = NULL;
1188               *ppvv = vv;
1189               ppvv = &vv->next;
1190
1191               data += 4;
1192               length -= 4;
1193
1194               if (vallen < 4)
1195                 fatal ("unexpected version value length %d", vallen);
1196
1197               vallen -= 4;
1198             }
1199         }
1200       else
1201         fatal ("unexpected version string");
1202
1203       vi->next = NULL;
1204       *pp = vi;
1205       pp = &vi->next;      
1206     }
1207
1208   v = (struct versioninfo *) res_alloc (sizeof *v);
1209   v->fixed = fi;
1210   v->var = first;
1211
1212   r = (struct res_resource *) res_alloc (sizeof *r);
1213   r->type = RES_TYPE_VERSIONINFO;
1214   r->u.versioninfo = v;
1215
1216   return r;  
1217 }
1218
1219 /* Convert an arbitrary user defined resource from binary.  */
1220
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;
1226 {
1227   struct rcdata_item *ri;
1228   struct res_resource *r;
1229
1230   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1231
1232   ri->next = NULL;
1233   ri->type = RCDATA_BUFFER;
1234   ri->u.buffer.length = length;
1235   ri->u.buffer.data = data;
1236
1237   r = (struct res_resource *) res_alloc (sizeof *r);
1238   r->type = RES_TYPE_USERDATA;
1239   r->u.rcdata = ri;
1240
1241   return r;
1242 }
1243 \f
1244 /* Macros to swap out values.  */
1245
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)))
1248
1249 /* Local functions used to convert resources to binary format.  */
1250
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 *));
1281
1282 /* Convert a resource to binary.  */
1283
1284 struct bindata *
1285 res_to_bin (res, big_endian)
1286      const struct res_resource *res;
1287      int big_endian;
1288 {
1289   switch (res->type)
1290     {
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);
1320     }
1321 }
1322
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.  */
1327
1328 static void
1329 dword_align_bin (ppp, length)
1330      struct bindata ***ppp;
1331      unsigned long *length;
1332 {
1333   int add;
1334   struct bindata *d;
1335
1336   if ((*length & 3) == 0)
1337     return;
1338
1339   add = 4 - (*length & 3);
1340
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);
1345
1346   d->next = NULL;
1347   **ppp = d;
1348   *ppp = &(**ppp)->next;
1349
1350   *length += add;
1351 }
1352
1353 /* Convert a resource ID to binary.  This always returns exactly one
1354    bindata structure.  */
1355
1356 static struct bindata *
1357 resid_to_bin (id, big_endian)
1358      struct res_id id;
1359      int big_endian;
1360 {
1361   struct bindata *d;
1362
1363   d = (struct bindata *) reswr_alloc (sizeof *d);
1364
1365   if (! id.named)
1366     {
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);
1371     }
1372   else
1373     {
1374       int i;
1375
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);
1381     }
1382
1383   d->next = NULL;
1384
1385   return d;
1386 }
1387
1388 /* Convert a null terminated unicode string to binary.  This always
1389    returns exactly one bindata structure.  */
1390
1391 static struct bindata *
1392 unicode_to_bin (str, big_endian)
1393      const unichar *str;
1394      int big_endian;
1395 {
1396   int len;
1397   struct bindata *d;
1398
1399   len = 0;
1400   if (str != NULL)
1401     {
1402       const unichar *s;
1403
1404       for (s = str; *s != 0; s++)
1405         ++len;
1406     }
1407
1408   d = (struct bindata *) reswr_alloc (sizeof *d);
1409   d->length = len * 2 + 2;
1410   d->data = (unsigned char *) reswr_alloc (d->length);
1411
1412   if (str == NULL)
1413     put_16 (big_endian, 0, d->data);
1414   else
1415     {
1416       const unichar *s;
1417       int i;
1418
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);
1422     }
1423
1424   d->next = NULL;
1425
1426   return d;
1427 }
1428
1429 /* Convert an accelerator resource to binary.  */
1430
1431 static struct bindata *
1432 res_to_bin_accelerator (accelerators, big_endian)
1433      const struct accelerator *accelerators;
1434      int big_endian;
1435 {
1436   struct bindata *first, **pp;
1437   const struct accelerator *a;
1438
1439   first = NULL;
1440   pp = &first;
1441
1442   for (a = accelerators; a != NULL; a = a->next)
1443     {
1444       struct bindata *d;
1445
1446       d = (struct bindata *) reswr_alloc (sizeof *d);
1447       d->length = 8;
1448       d->data = (unsigned char *) reswr_alloc (8);
1449
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);
1456
1457       d->next = NULL;
1458       *pp = d;
1459       pp = &d->next;
1460     }
1461
1462   return first;
1463 }
1464
1465 /* Convert a cursor resource to binary.  */
1466
1467 static struct bindata *
1468 res_to_bin_cursor (c, big_endian)
1469      const struct cursor *c;
1470      int big_endian;
1471 {
1472   struct bindata *d;
1473
1474   d = (struct bindata *) reswr_alloc (sizeof *d);
1475   d->length = 4;
1476   d->data = (unsigned char *) reswr_alloc (4);
1477
1478   put_16 (big_endian, c->xhotspot, d->data);
1479   put_16 (big_endian, c->yhotspot, d->data + 2);
1480
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;
1485
1486   return d;
1487 }
1488
1489 /* Convert a group cursor resource to binary.  */
1490
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;
1495 {
1496   struct bindata *first, **pp;
1497   int c;
1498   const struct group_cursor *gc;
1499
1500   first = (struct bindata *) reswr_alloc (sizeof *first);
1501   first->length = 6;
1502   first->data = (unsigned char *) reswr_alloc (6);
1503
1504   put_16 (big_endian, 0, first->data);
1505   put_16 (big_endian, 2, first->data + 2);
1506
1507   first->next = NULL;
1508   pp = &first->next;
1509
1510   c = 0;
1511   for (gc = group_cursors; gc != NULL; gc = gc->next)
1512     {
1513       struct bindata *d;
1514
1515       ++c;
1516
1517       d = (struct bindata *) reswr_alloc (sizeof *d);
1518       d->length = 14;
1519       d->data = (unsigned char *) reswr_alloc (14);
1520
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);
1527
1528       d->next = NULL;
1529       *pp = d;
1530       pp = &d->next;
1531     }
1532
1533   put_16 (big_endian, c, first->data + 4);
1534
1535   return first;
1536 }
1537
1538 /* Convert a dialog resource to binary.  */
1539
1540 static struct bindata *
1541 res_to_bin_dialog (dialog, big_endian)
1542      const struct dialog *dialog;
1543      int big_endian;
1544 {
1545   int dialogex;
1546   struct bindata *first, **pp;
1547   unsigned long length;
1548   int off, c;
1549   struct dialog_control *dc;
1550
1551   dialogex = extended_dialog (dialog);
1552
1553   first = (struct bindata *) reswr_alloc (sizeof *first);
1554   first->length = dialogex ? 26 : 18;
1555   first->data = (unsigned char *) reswr_alloc (first->length);
1556
1557   length = first->length;
1558
1559   if (! dialogex)
1560     {
1561       put_32 (big_endian, dialog->style, first->data);
1562       put_32 (big_endian, dialog->style, first->data + 4);
1563       off = 8;
1564     }
1565   else
1566     {
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;
1576     }
1577
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);
1582
1583   pp = &first->next;
1584
1585   *pp = resid_to_bin (dialog->menu, big_endian);
1586   length += (*pp)->length;
1587   pp = &(*pp)->next;
1588
1589   *pp = resid_to_bin (dialog->class, big_endian);
1590   length += (*pp)->length;
1591   pp = &(*pp)->next;
1592
1593   *pp = unicode_to_bin (dialog->caption, big_endian);
1594   length += (*pp)->length;
1595   pp = &(*pp)->next;
1596
1597   if ((dialog->style & DS_SETFONT) != 0)
1598     {
1599       struct bindata *d;
1600
1601       d = (struct bindata *) reswr_alloc (sizeof *d);
1602       d->length = dialogex ? 2 : 6;
1603       d->data = (unsigned char *) reswr_alloc (d->length);
1604
1605       length += d->length;
1606
1607       put_16 (big_endian, dialog->pointsize, d->data);
1608
1609       if (dialogex)
1610         {
1611           if (dialog->ex == NULL)
1612             {
1613               put_16 (big_endian, 0, d->data + 2);
1614               put_16 (big_endian, 0, d->data + 4);
1615             }
1616           else
1617             {
1618               put_16 (big_endian, dialog->ex->weight, d->data + 2);
1619               put_16 (big_endian, dialog->ex->italic, d->data + 4);
1620             }
1621         }
1622
1623       *pp = d;
1624       pp = &d->next;
1625
1626       *pp = unicode_to_bin (dialog->font, big_endian);
1627       length += (*pp)->length;
1628       pp = &(*pp)->next;
1629     }
1630
1631   c = 0;
1632   for (dc = dialog->controls; dc != NULL; dc = dc->next)
1633     {
1634       unsigned long length;
1635       struct bindata *d;
1636       int dcoff;
1637
1638       ++c;
1639
1640       dword_align_bin (&pp, &length);
1641
1642       d = (struct bindata *) reswr_alloc (sizeof *d);
1643       d->length = dialogex ? 22 : 18;
1644       d->data = (unsigned char *) reswr_alloc (d->length);
1645
1646       length += d->length;
1647
1648       if (! dialogex)
1649         {
1650           put_32 (big_endian, dc->style, d->data);
1651           put_32 (big_endian, dc->exstyle, d->data + 4);
1652           dcoff = 8;
1653         }
1654       else
1655         {
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;
1660         }
1661
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);
1667
1668       *pp = d;
1669       pp = &d->next;
1670
1671       *pp = resid_to_bin (dc->class, big_endian);
1672       length += (*pp)->length;
1673       pp = &(*pp)->next;
1674
1675       *pp = resid_to_bin (dc->text, big_endian);
1676       length += (*pp)->length;
1677       pp = &(*pp)->next;
1678
1679       d = (struct bindata *) reswr_alloc (sizeof *d);
1680       d->length = 2;
1681       d->data = (unsigned char *) reswr_alloc (2);
1682
1683       length += 2;
1684
1685       d->next = NULL;
1686       *pp = d;
1687       pp = &d->next;
1688
1689       if (dc->data == NULL)
1690         put_16 (big_endian, 0, d->data);
1691       else
1692         {
1693           dword_align_bin (&pp, &length);
1694
1695           *pp = res_to_bin_rcdata (dc->data, big_endian);
1696           while (*pp != NULL)
1697             {
1698               length += (*pp)->length;
1699               pp = &(*pp)->next;
1700             }
1701         }
1702     }
1703
1704   put_16 (big_endian, c, first->data + off);
1705
1706   return first;
1707 }
1708
1709 /* Convert a fontdir resource to binary.  */
1710
1711 static struct bindata *
1712 res_to_bin_fontdir (fontdirs, big_endian)
1713      const struct fontdir *fontdirs;
1714      int big_endian;
1715 {
1716   struct bindata *first, **pp;
1717   int c;
1718   const struct fontdir *fd;
1719
1720   first = (struct bindata *) reswr_alloc (sizeof *first);
1721   first->length = 2;
1722   first->data = (unsigned char *) reswr_alloc (2);
1723
1724   first->next = NULL;
1725   pp = &first->next;
1726
1727   c = 0;
1728   for (fd = fontdirs; fd != NULL; fd = fd->next)
1729     {
1730       struct bindata *d;
1731
1732       ++c;
1733
1734       d = (struct bindata *) reswr_alloc (sizeof *d);
1735       d->length = 2;
1736       d->data = (unsigned char *) reswr_alloc (2);
1737
1738       put_16 (big_endian, fd->index, d->data);
1739
1740       *pp = d;
1741       pp = &d->next;
1742
1743       d = (struct bindata *) reswr_alloc (sizeof *d);
1744       d->length = fd->length;
1745       d->data = (unsigned char *) fd->data;
1746
1747       d->next = NULL;
1748       *pp = d;
1749       pp = &d->next;      
1750     }
1751
1752   put_16 (big_endian, c, first->data);
1753
1754   return first;  
1755 }
1756
1757 /* Convert a group icon resource to binary.  */
1758
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;
1763 {
1764   struct bindata *first, **pp;
1765   int c;
1766   const struct group_icon *gi;
1767
1768   first = (struct bindata *) reswr_alloc (sizeof *first);
1769   first->length = 6;
1770   first->data = (unsigned char *) reswr_alloc (6);
1771
1772   put_16 (big_endian, 0, first->data);
1773   put_16 (big_endian, 1, first->data + 2);
1774
1775   first->next = NULL;
1776   pp = &first->next;
1777
1778   c = 0;
1779   for (gi = group_icons; gi != NULL; gi = gi->next)
1780     {
1781       struct bindata *d;
1782
1783       ++c;
1784
1785       d = (struct bindata *) reswr_alloc (sizeof *d);
1786       d->length = 14;
1787       d->data = (unsigned char *) reswr_alloc (14);
1788
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);
1797
1798       d->next = NULL;
1799       *pp = d;
1800       pp = &d->next;
1801     }
1802
1803   put_16 (big_endian, c, first->data + 4);
1804
1805   return first;
1806 }
1807
1808 /* Convert a menu resource to binary.  */
1809
1810 static struct bindata *
1811 res_to_bin_menu (menu, big_endian)
1812      const struct menu *menu;
1813      int big_endian;
1814 {
1815   int menuex;
1816   struct bindata *d;
1817
1818   menuex = extended_menu (menu);
1819
1820   d = (struct bindata *) reswr_alloc (sizeof *d);
1821   d->length = menuex ? 8 : 4;
1822   d->data = (unsigned char *) reswr_alloc (d->length);
1823
1824   if (! menuex)
1825     {
1826       put_16 (big_endian, 0, d->data);
1827       put_16 (big_endian, 0, d->data + 2);
1828
1829       d->next = res_to_bin_menuitems (menu->items, big_endian);
1830     }
1831   else
1832     {
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);
1836
1837       d->next = res_to_bin_menuexitems (menu->items, big_endian);
1838     }
1839
1840   return d;
1841 }
1842
1843 /* Convert menu items to binary.  */
1844
1845 static struct bindata *
1846 res_to_bin_menuitems (items, big_endian)
1847      const struct menuitem *items;
1848      int big_endian;
1849 {
1850   struct bindata *first, **pp;
1851   const struct menuitem *mi;
1852
1853   first = NULL;
1854   pp = &first;
1855
1856   for (mi = items; mi != NULL; mi = mi->next)
1857     {
1858       struct bindata *d;
1859       int flags;
1860
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);
1864
1865       flags = mi->type;
1866       if (mi->next == NULL)
1867         flags |= MENUITEM_ENDMENU;
1868       if (mi->popup != NULL)
1869         flags |= MENUITEM_POPUP;
1870
1871       put_16 (big_endian, flags, d->data);
1872
1873       if (mi->popup == NULL)
1874         put_16 (big_endian, mi->id, d->data + 2);
1875
1876       *pp = d;
1877       pp = &d->next;
1878
1879       *pp = unicode_to_bin (mi->text, big_endian);
1880       pp = &(*pp)->next;
1881
1882       if (mi->popup != NULL)
1883         {
1884           *pp = res_to_bin_menuitems (mi->popup, big_endian);
1885           while (*pp != NULL)
1886             pp = &(*pp)->next;
1887         }
1888     }
1889
1890   return first;
1891 }
1892
1893 /* Convert menuex items to binary.  */
1894
1895 static struct bindata *
1896 res_to_bin_menuexitems (items, big_endian)
1897      const struct menuitem *items;
1898      int big_endian;
1899 {
1900   struct bindata *first, **pp;
1901   unsigned long length;
1902   const struct menuitem *mi;
1903
1904   first = NULL;
1905   pp = &first;
1906
1907   length = 0;
1908
1909   for (mi = items; mi != NULL; mi = mi->next)
1910     {
1911       struct bindata *d;
1912       int flags;
1913
1914       dword_align_bin (&pp, &length);
1915
1916       d = (struct bindata *) reswr_alloc (sizeof *d);
1917       d->length = 12;
1918       d->data = (unsigned char *) reswr_alloc (12);
1919
1920       length += 12;
1921
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);
1925
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);
1932
1933       *pp = d;
1934       pp = &d->next;
1935
1936       *pp = unicode_to_bin (mi->text, big_endian);
1937       length += (*pp)->length;
1938       pp = &(*pp)->next;
1939
1940       if (mi->popup != NULL)
1941         {
1942           dword_align_bin (&pp, &length);
1943
1944           d = (struct bindata *) reswr_alloc (sizeof *d);
1945           d->length = 4;
1946           d->data = (unsigned char *) reswr_alloc (4);
1947
1948           put_32 (big_endian, mi->help, d->data);
1949
1950           *pp = d;
1951           pp = &d->next;
1952
1953           *pp = res_to_bin_menuexitems (mi->popup, big_endian);
1954           while (*pp != NULL)
1955             {
1956               length += (*pp)->length;
1957               pp = &(*pp)->next;
1958             }
1959         }
1960     }
1961
1962   return first;
1963 }
1964
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.  */
1968
1969 static struct bindata *
1970 res_to_bin_rcdata (items, big_endian)
1971      const struct rcdata_item *items;
1972      int big_endian;
1973 {
1974   struct bindata *first, **pp;
1975   const struct rcdata_item *ri;
1976
1977   first = NULL;
1978   pp = &first;
1979
1980   for (ri = items; ri != NULL; ri = ri->next)
1981     {
1982       struct bindata *d;
1983
1984       d = (struct bindata *) reswr_alloc (sizeof *d);
1985
1986       switch (ri->type)
1987         {
1988         default:
1989           abort ();
1990
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;
1996
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;
2002
2003         case RCDATA_STRING:
2004           d->length = ri->u.string.length;
2005           d->data = (unsigned char *) ri->u.string.s;
2006           break;
2007
2008         case RCDATA_WSTRING:
2009           {
2010             unsigned long i;
2011
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;
2017           }
2018
2019         case RCDATA_BUFFER:
2020           d->length = ri->u.buffer.length;
2021           d->data = (unsigned char *) ri->u.buffer.data;
2022           break;
2023         }
2024
2025       d->next = NULL;
2026       *pp = d;
2027       pp = &d->next;
2028     }
2029
2030   return first;
2031 }
2032
2033 /* Convert a stringtable resource to binary.  */
2034
2035 static struct bindata *
2036 res_to_bin_stringtable (st, big_endian)
2037      const struct stringtable *st;
2038      int big_endian;
2039 {
2040   struct bindata *first, **pp;
2041   int i;
2042
2043   first = NULL;
2044   pp = &first;
2045
2046   for (i = 0; i < 16; i++)
2047     {
2048       int slen, j;
2049       struct bindata *d;
2050       unichar *s;
2051
2052       slen = st->strings[i].length;
2053       s = st->strings[i].string;
2054
2055       d = (struct bindata *) reswr_alloc (sizeof *d);
2056       d->length = 2 + slen * 2;
2057       d->data = (unsigned char *) reswr_alloc (d->length);
2058
2059       put_16 (big_endian, slen, d->data);
2060
2061       for (j = 0; j < slen; j++)
2062         put_16 (big_endian, s[j], d->data + 2 + j * 2);
2063
2064       d->next = NULL;
2065       *pp = d;
2066       pp = &d->next;      
2067     }
2068
2069   return first;
2070 }
2071
2072 /* Convert an ASCII string to a unicode binary string.  This always
2073    returns exactly one bindata structure.  */
2074
2075 static struct bindata *
2076 string_to_unicode_bin (s, big_endian)
2077      const char *s;
2078      int big_endian;
2079 {
2080   size_t len, i;
2081   struct bindata *d;
2082
2083   len = strlen (s);
2084
2085   d = (struct bindata *) reswr_alloc (sizeof *d);
2086   d->length = len * 2 + 2;
2087   d->data = (unsigned char *) reswr_alloc (d->length);
2088
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);
2092
2093   d->next = NULL;
2094
2095   return d;  
2096 }
2097
2098 /* Convert a versioninfo resource to binary.  */
2099
2100 static struct bindata *
2101 res_to_bin_versioninfo (versioninfo, big_endian)
2102      const struct versioninfo *versioninfo;
2103      int big_endian;
2104 {
2105   struct bindata *first, **pp;
2106   unsigned long length;
2107   struct ver_info *vi;
2108
2109   first = (struct bindata *) reswr_alloc (sizeof *first);
2110   first->length = 6;
2111   first->data = (unsigned char *) reswr_alloc (6);
2112
2113   length = 6;
2114
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);
2119
2120   put_16 (big_endian, 0, first->data + 4);
2121
2122   pp = &first->next;
2123
2124   *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian);
2125   length += (*pp)->length;
2126   pp = &(*pp)->next;
2127
2128   dword_align_bin (&pp, &length);
2129
2130   if (versioninfo->fixed != NULL)
2131     {
2132       const struct fixed_versioninfo *fi;
2133       struct bindata *d;
2134
2135       d = (struct bindata *) reswr_alloc (sizeof *d);
2136       d->length = 52;
2137       d->data = (unsigned char *) reswr_alloc (52);
2138
2139       length += 52;
2140
2141       fi = versioninfo->fixed;
2142
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);
2156
2157       d->next = NULL;
2158       *pp = d;
2159       pp = &d->next;
2160     }
2161
2162   for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2163     {
2164       struct bindata *vid;
2165       unsigned long vilen;
2166
2167       dword_align_bin (&pp, &length);
2168
2169       vid = (struct bindata *) reswr_alloc (sizeof *vid);
2170       vid->length = 6;
2171       vid->data = (unsigned char *) reswr_alloc (6);
2172
2173       length += 6;
2174       vilen = 6;
2175
2176       put_16 (big_endian, 0, vid->data + 2);
2177       put_16 (big_endian, 0, vid->data + 4);
2178
2179       *pp = vid;
2180       pp = &vid->next;
2181
2182       switch (vi->type)
2183         {
2184         default:
2185           abort ();
2186
2187         case VERINFO_STRING:
2188           {
2189             unsigned long hold, vslen;
2190             struct bindata *vsd;
2191             const struct ver_stringinfo *vs;
2192
2193             *pp = string_to_unicode_bin ("StringFileInfo", big_endian);
2194             length += (*pp)->length;
2195             vilen += (*pp)->length;
2196             pp = &(*pp)->next;
2197
2198             hold = length;
2199             dword_align_bin (&pp, &length);
2200             vilen += length - hold;
2201
2202             vsd = (struct bindata *) reswr_alloc (sizeof *vsd);
2203             vsd->length = 6;
2204             vsd->data = (unsigned char *) reswr_alloc (6);
2205
2206             length += 6;
2207             vilen += 6;
2208             vslen = 6;
2209
2210             put_16 (big_endian, 0, vsd->data + 2);
2211             put_16 (big_endian, 0, vsd->data + 4);
2212
2213             *pp = vsd;
2214             pp = &vsd->next;
2215
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;
2221
2222             for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2223               {
2224                 struct bindata *vssd;
2225                 unsigned long vsslen;
2226
2227                 hold = length;
2228                 dword_align_bin (&pp, &length);
2229                 vilen += length - hold;
2230                 vslen += length - hold;
2231
2232                 vssd = (struct bindata *) reswr_alloc (sizeof *vssd);
2233                 vssd->length = 6;
2234                 vssd->data = (unsigned char *) reswr_alloc (6);
2235
2236                 length += 6;
2237                 vilen += 6;
2238                 vslen += 6;
2239                 vsslen = 6;
2240
2241                 put_16 (big_endian, 0, vssd->data + 2);
2242                 put_16 (big_endian, 1, vssd->data + 4);
2243
2244                 *pp = vssd;
2245                 pp = &vssd->next;
2246
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;
2253
2254                 hold = length;
2255                 dword_align_bin (&pp, &length);
2256                 vilen += length - hold;
2257                 vslen += length - hold;
2258                 vsslen += length - hold;
2259
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;
2266
2267                 put_16 (big_endian, vsslen, vssd->data);
2268               }
2269
2270             put_16 (big_endian, vslen, vsd->data);
2271
2272             break;
2273           }
2274
2275         case VERINFO_VAR:
2276           {
2277             unsigned long hold, vvlen, vvvlen;
2278             struct bindata *vvd;
2279             const struct ver_varinfo *vv;
2280
2281             *pp = string_to_unicode_bin ("VarFileInfo", big_endian);
2282             length += (*pp)->length;
2283             vilen += (*pp)->length;
2284             pp = &(*pp)->next;
2285
2286             hold = length;
2287             dword_align_bin (&pp, &length);
2288             vilen += length - hold;
2289
2290             vvd = (struct bindata *) reswr_alloc (sizeof *vvd);
2291             vvd->length = 6;
2292             vvd->data = (unsigned char *) reswr_alloc (6);
2293
2294             length += 6;
2295             vilen += 6;
2296             vvlen = 6;
2297
2298             put_16 (big_endian, 0, vvd->data + 4);
2299
2300             *pp = vvd;
2301             pp = &vvd->next;
2302
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;
2308
2309             hold = length;
2310             dword_align_bin (&pp, &length);
2311             vilen += length - hold;
2312             vvlen += length - hold;
2313
2314             vvvlen = 0;
2315
2316             for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2317               {
2318                 struct bindata *vvsd;
2319
2320                 vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd);
2321                 vvsd->length = 4;
2322                 vvsd->data = (unsigned char *) reswr_alloc (4);
2323
2324                 length += 4;
2325                 vilen += 4;
2326                 vvlen += 4;
2327                 vvvlen += 4;
2328
2329                 put_16 (big_endian, vv->language, vvsd->data);
2330                 put_16 (big_endian, vv->charset, vvsd->data + 2);
2331
2332                 vvsd->next = NULL;
2333                 *pp = vvsd;
2334                 pp = &vvsd->next;
2335               }
2336
2337             put_16 (big_endian, vvlen, vvd->data);
2338             put_16 (big_endian, vvvlen, vvd->data + 2);
2339
2340             break;
2341           }
2342         }
2343
2344       put_16 (big_endian, vilen, vid->data);
2345     }
2346
2347   put_16 (big_endian, length, first->data);
2348
2349   return first;
2350 }
2351
2352 /* Convert a generic resource to binary.  */
2353
2354 static struct bindata *
2355 res_to_bin_generic (length, data)
2356      unsigned long length;
2357      const unsigned char *data;
2358 {
2359   struct bindata *d;
2360
2361   d = (struct bindata *) reswr_alloc (sizeof *d);
2362   d->length = length;
2363   d->data = (unsigned char *) data;
2364
2365   d->next = NULL;
2366
2367   return d;
2368 }