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