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