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