138889Sjdp/* resbin.c -- manipulate the Windows binary resource format.
2218822Sdim   Copyright 1997, 1998, 1999, 2002, 2003, 2007
3130561Sobrien   Free Software Foundation, Inc.
438889Sjdp   Written by Ian Lance Taylor, Cygnus Support.
5218822Sdim   Rewritten by Kai Tietz, Onevision.
638889Sjdp
738889Sjdp   This file is part of GNU Binutils.
838889Sjdp
938889Sjdp   This program is free software; you can redistribute it and/or modify
1038889Sjdp   it under the terms of the GNU General Public License as published by
1138889Sjdp   the Free Software Foundation; either version 2 of the License, or
1238889Sjdp   (at your option) any later version.
1338889Sjdp
1438889Sjdp   This program is distributed in the hope that it will be useful,
1538889Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1638889Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1738889Sjdp   GNU General Public License for more details.
1838889Sjdp
1938889Sjdp   You should have received a copy of the GNU General Public License
2038889Sjdp   along with this program; if not, write to the Free Software
21218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
22218822Sdim   02110-1301, USA.  */
2338889Sjdp
2438889Sjdp/* This file contains functions to convert between the binary resource
2538889Sjdp   format and the internal structures that we want to use.  The same
2638889Sjdp   binary resource format is used in both res and COFF files.  */
2738889Sjdp
28218822Sdim#include "sysdep.h"
2938889Sjdp#include "bfd.h"
3038889Sjdp#include "bucomm.h"
3138889Sjdp#include "libiberty.h"
3238889Sjdp#include "windres.h"
3338889Sjdp
3438889Sjdp/* Local functions.  */
3538889Sjdp
36130561Sobrienstatic void toosmall (const char *);
37130561Sobrien
38218822Sdimstatic unichar *get_unicode (windres_bfd *, const bfd_byte *, rc_uint_type, rc_uint_type *);
39218822Sdimstatic int get_resid (windres_bfd *, rc_res_id *, const bfd_byte *, rc_uint_type);
40218822Sdimstatic rc_res_resource *bin_to_res_generic (windres_bfd *, enum rc_res_type,
41218822Sdim					    const bfd_byte *, rc_uint_type);
42218822Sdimstatic rc_res_resource *bin_to_res_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
43218822Sdimstatic rc_res_resource *bin_to_res_menu (windres_bfd *,const bfd_byte *, rc_uint_type);
44218822Sdimstatic rc_menuitem *bin_to_res_menuitems (windres_bfd *, const bfd_byte *, rc_uint_type,
45218822Sdim					  rc_uint_type *);
46218822Sdimstatic rc_menuitem *bin_to_res_menuexitems (windres_bfd *, const bfd_byte *, rc_uint_type,
47218822Sdim					    rc_uint_type *);
48218822Sdimstatic rc_res_resource *bin_to_res_dialog (windres_bfd *, const bfd_byte *, rc_uint_type);
49218822Sdimstatic rc_res_resource *bin_to_res_string (windres_bfd *,const bfd_byte *, rc_uint_type);
50218822Sdimstatic rc_res_resource *bin_to_res_fontdir (windres_bfd *, const bfd_byte *, rc_uint_type);
51218822Sdimstatic rc_res_resource *bin_to_res_accelerators (windres_bfd *, const bfd_byte *, rc_uint_type);
52218822Sdimstatic rc_res_resource *bin_to_res_rcdata (windres_bfd *, const bfd_byte *, rc_uint_type, int);
53218822Sdimstatic rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
54218822Sdimstatic rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type);
55218822Sdimstatic rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type);
56218822Sdimstatic rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type);
57218822Sdimstatic rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type);
58218822Sdimstatic void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *,
59218822Sdim				unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *,
60218822Sdim				rc_uint_type *);
6138889Sjdp
6238889Sjdp/* Given a resource type ID, a pointer to data, a length, return a
63218822Sdim   rc_res_resource structure which represents that resource.  The caller
6438889Sjdp   is responsible for initializing the res_info and coff_info fields
6538889Sjdp   of the returned structure.  */
6638889Sjdp
67218822Sdimrc_res_resource *
68218822Sdimbin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data,
69218822Sdim	    rc_uint_type length)
7038889Sjdp{
7138889Sjdp  if (type.named)
72218822Sdim    return bin_to_res_userdata (wrbfd, data, length);
7338889Sjdp  else
7438889Sjdp    {
7538889Sjdp      switch (type.u.id)
7638889Sjdp	{
7738889Sjdp	default:
78218822Sdim	  return bin_to_res_userdata (wrbfd, data, length);
7938889Sjdp	case RT_CURSOR:
80218822Sdim	  return bin_to_res_cursor (wrbfd, data, length);
8138889Sjdp	case RT_BITMAP:
82218822Sdim	  return bin_to_res_generic (wrbfd, RES_TYPE_BITMAP, data, length);
8338889Sjdp	case RT_ICON:
84218822Sdim	  return bin_to_res_generic (wrbfd, RES_TYPE_ICON, data, length);
8538889Sjdp	case RT_MENU:
86218822Sdim	  return bin_to_res_menu (wrbfd, data, length);
8738889Sjdp	case RT_DIALOG:
88218822Sdim	  return bin_to_res_dialog (wrbfd, data, length);
8938889Sjdp	case RT_STRING:
90218822Sdim	  return bin_to_res_string (wrbfd, data, length);
9138889Sjdp	case RT_FONTDIR:
92218822Sdim	  return bin_to_res_fontdir (wrbfd, data, length);
9338889Sjdp	case RT_FONT:
94218822Sdim	  return bin_to_res_generic (wrbfd, RES_TYPE_FONT, data, length);
9560484Sobrien	case RT_ACCELERATOR:
96218822Sdim	  return bin_to_res_accelerators (wrbfd, data, length);
9738889Sjdp	case RT_RCDATA:
98218822Sdim	  return bin_to_res_rcdata (wrbfd, data, length, RES_TYPE_RCDATA);
9938889Sjdp	case RT_MESSAGETABLE:
100218822Sdim	  return bin_to_res_generic (wrbfd, RES_TYPE_MESSAGETABLE, data, length);
10138889Sjdp	case RT_GROUP_CURSOR:
102218822Sdim	  return bin_to_res_group_cursor (wrbfd, data, length);
10338889Sjdp	case RT_GROUP_ICON:
104218822Sdim	  return bin_to_res_group_icon (wrbfd, data, length);
10538889Sjdp	case RT_VERSION:
106218822Sdim	  return bin_to_res_version (wrbfd, data, length);
107218822Sdim	case RT_TOOLBAR:
108218822Sdim	  return  bin_to_res_toolbar (wrbfd, data, length);
109218822Sdim
11038889Sjdp	}
11138889Sjdp    }
11238889Sjdp}
11338889Sjdp
11438889Sjdp/* Give an error if the binary data is too small.  */
11538889Sjdp
11638889Sjdpstatic void
117130561Sobrientoosmall (const char *msg)
11838889Sjdp{
11960484Sobrien  fatal (_("%s: not enough binary data"), msg);
12038889Sjdp}
12138889Sjdp
12238889Sjdp/* Swap in a NULL terminated unicode string.  */
12338889Sjdp
12438889Sjdpstatic unichar *
125218822Sdimget_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
126218822Sdim	     rc_uint_type *retlen)
12738889Sjdp{
128218822Sdim  rc_uint_type c, i;
12938889Sjdp  unichar *ret;
13038889Sjdp
13138889Sjdp  c = 0;
13238889Sjdp  while (1)
13338889Sjdp    {
134218822Sdim      if (length < c * 2 + 2)
13560484Sobrien	toosmall (_("null terminated unicode string"));
136218822Sdim      if (windres_get_16 (wrbfd, data + c * 2, 2) == 0)
13738889Sjdp	break;
13838889Sjdp      ++c;
13938889Sjdp    }
14038889Sjdp
14138889Sjdp  ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
14238889Sjdp
14338889Sjdp  for (i = 0; i < c; i++)
144218822Sdim    ret[i] = windres_get_16 (wrbfd, data + i * 2, 2);
14538889Sjdp  ret[i] = 0;
14638889Sjdp
14738889Sjdp  if (retlen != NULL)
14838889Sjdp    *retlen = c;
14938889Sjdp
15038889Sjdp  return ret;
15138889Sjdp}
15238889Sjdp
15338889Sjdp/* Get a resource identifier.  This returns the number of bytes used.  */
15438889Sjdp
15538889Sjdpstatic int
156218822Sdimget_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data,
157218822Sdim	   rc_uint_type length)
15838889Sjdp{
159218822Sdim  rc_uint_type first;
16038889Sjdp
16138889Sjdp  if (length < 2)
16260484Sobrien    toosmall (_("resource ID"));
16338889Sjdp
164218822Sdim  first = windres_get_16 (wrbfd, data, 2);
16538889Sjdp  if (first == 0xffff)
16638889Sjdp    {
16738889Sjdp      if (length < 4)
16860484Sobrien	toosmall (_("resource ID"));
16938889Sjdp      id->named = 0;
170218822Sdim      id->u.id = windres_get_16 (wrbfd, data + 2, 2);
17138889Sjdp      return 4;
17238889Sjdp    }
17338889Sjdp  else
17438889Sjdp    {
17538889Sjdp      id->named = 1;
176218822Sdim      id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length);
17738889Sjdp      return id->u.n.length * 2 + 2;
17838889Sjdp    }
17938889Sjdp}
18038889Sjdp
18138889Sjdp/* Convert a resource which just stores uninterpreted data from
18238889Sjdp   binary.  */
18338889Sjdp
184218822Sdimrc_res_resource *
185218822Sdimbin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type,
186218822Sdim		    const bfd_byte *data, rc_uint_type length)
18738889Sjdp{
188218822Sdim  rc_res_resource *r;
18938889Sjdp
190218822Sdim  r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
19138889Sjdp  r->type = type;
19238889Sjdp  r->u.data.data = data;
19338889Sjdp  r->u.data.length = length;
19438889Sjdp
19538889Sjdp  return r;
19638889Sjdp}
19738889Sjdp
19838889Sjdp/* Convert a cursor resource from binary.  */
19938889Sjdp
200218822Sdimrc_res_resource *
201218822Sdimbin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
20238889Sjdp{
203218822Sdim  rc_cursor *c;
204218822Sdim  rc_res_resource *r;
20538889Sjdp
20638889Sjdp  if (length < 4)
20760484Sobrien    toosmall (_("cursor"));
20838889Sjdp
209218822Sdim  c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
210218822Sdim  c->xhotspot = windres_get_16 (wrbfd, data, 2);
211218822Sdim  c->yhotspot = windres_get_16 (wrbfd, data + 2, 2);
21238889Sjdp  c->length = length - 4;
21338889Sjdp  c->data = data + 4;
21438889Sjdp
215218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
21638889Sjdp  r->type = RES_TYPE_CURSOR;
21738889Sjdp  r->u.cursor = c;
21838889Sjdp
21938889Sjdp  return r;
22038889Sjdp}
22138889Sjdp
22238889Sjdp/* Convert a menu resource from binary.  */
22338889Sjdp
224218822Sdimrc_res_resource *
225218822Sdimbin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
22638889Sjdp{
227218822Sdim  rc_res_resource *r;
228218822Sdim  rc_menu *m;
229218822Sdim  rc_uint_type version, read;
23038889Sjdp
231218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
23238889Sjdp  r->type = RES_TYPE_MENU;
23338889Sjdp
234218822Sdim  m = (rc_menu *) res_alloc (sizeof (rc_menu));
23538889Sjdp  r->u.menu = m;
23638889Sjdp
23738889Sjdp  if (length < 2)
23860484Sobrien    toosmall (_("menu header"));
23938889Sjdp
240218822Sdim  version = windres_get_16 (wrbfd, data, 2);
24138889Sjdp
24238889Sjdp  if (version == 0)
24338889Sjdp    {
24438889Sjdp      if (length < 4)
24560484Sobrien	toosmall (_("menu header"));
24638889Sjdp      m->help = 0;
247218822Sdim      m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &read);
24838889Sjdp    }
24938889Sjdp  else if (version == 1)
25038889Sjdp    {
251218822Sdim      rc_uint_type offset;
25238889Sjdp
25338889Sjdp      if (length < 8)
25460484Sobrien	toosmall (_("menuex header"));
255218822Sdim      m->help = windres_get_32 (wrbfd, data + 4, 4);
256218822Sdim      offset = windres_get_16 (wrbfd, data + 2, 2);
25738889Sjdp      if (offset + 4 >= length)
25860484Sobrien	toosmall (_("menuex offset"));
259218822Sdim      m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset,
260218822Sdim					 length - (4 + offset), &read);
26138889Sjdp    }
26238889Sjdp  else
263218822Sdim    fatal (_("unsupported menu version %d"), (int) version);
26438889Sjdp
26538889Sjdp  return r;
26638889Sjdp}
26738889Sjdp
26838889Sjdp/* Convert menu items from binary.  */
26938889Sjdp
270218822Sdimstatic rc_menuitem *
271218822Sdimbin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
272218822Sdim		      rc_uint_type *read)
27338889Sjdp{
274218822Sdim  rc_menuitem *first, **pp;
27538889Sjdp
27638889Sjdp  first = NULL;
27738889Sjdp  pp = &first;
27838889Sjdp
27938889Sjdp  *read = 0;
28038889Sjdp
28138889Sjdp  while (length > 0)
28238889Sjdp    {
283218822Sdim      rc_uint_type flags, slen, itemlen;
284218822Sdim      rc_uint_type stroff;
285218822Sdim      rc_menuitem *mi;
28638889Sjdp
28738889Sjdp      if (length < 4)
28860484Sobrien	toosmall (_("menuitem header"));
28938889Sjdp
290218822Sdim      mi = (rc_menuitem *) res_alloc (sizeof *mi);
29138889Sjdp      mi->state = 0;
29238889Sjdp      mi->help = 0;
29338889Sjdp
294218822Sdim      flags = windres_get_16 (wrbfd, data, 2);
29538889Sjdp      mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
29638889Sjdp
29738889Sjdp      if ((flags & MENUITEM_POPUP) == 0)
29838889Sjdp	stroff = 4;
29938889Sjdp      else
30038889Sjdp	stroff = 2;
30138889Sjdp
30238889Sjdp      if (length < stroff + 2)
30360484Sobrien	toosmall (_("menuitem header"));
30438889Sjdp
305218822Sdim      if (windres_get_16 (wrbfd, data + stroff, 2) == 0)
30638889Sjdp	{
30738889Sjdp	  slen = 0;
30838889Sjdp	  mi->text = NULL;
30938889Sjdp	}
31038889Sjdp      else
311218822Sdim	mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen);
31238889Sjdp
31338889Sjdp      itemlen = stroff + slen * 2 + 2;
31438889Sjdp
31538889Sjdp      if ((flags & MENUITEM_POPUP) == 0)
31638889Sjdp	{
31738889Sjdp	  mi->popup = NULL;
318218822Sdim	  mi->id = windres_get_16 (wrbfd, data + 2, 2);
31938889Sjdp	}
32038889Sjdp      else
32138889Sjdp	{
322218822Sdim	  rc_uint_type subread;
32338889Sjdp
32438889Sjdp	  mi->id = 0;
325218822Sdim	  mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen,
326218822Sdim	  				    &subread);
32738889Sjdp	  itemlen += subread;
32838889Sjdp	}
32938889Sjdp
33038889Sjdp      mi->next = NULL;
33138889Sjdp      *pp = mi;
33238889Sjdp      pp = &mi->next;
33338889Sjdp
33438889Sjdp      data += itemlen;
33538889Sjdp      length -= itemlen;
33638889Sjdp      *read += itemlen;
33738889Sjdp
33838889Sjdp      if ((flags & MENUITEM_ENDMENU) != 0)
33938889Sjdp	return first;
34038889Sjdp    }
34138889Sjdp
34238889Sjdp  return first;
34338889Sjdp}
34438889Sjdp
34538889Sjdp/* Convert menuex items from binary.  */
34638889Sjdp
347218822Sdimstatic rc_menuitem *
348218822Sdimbin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
349218822Sdim			rc_uint_type *read)
35038889Sjdp{
351218822Sdim  rc_menuitem *first, **pp;
35238889Sjdp
35338889Sjdp  first = NULL;
35438889Sjdp  pp = &first;
35538889Sjdp
35638889Sjdp  *read = 0;
35738889Sjdp
35838889Sjdp  while (length > 0)
35938889Sjdp    {
360218822Sdim      rc_uint_type flags, slen;
361218822Sdim      rc_uint_type itemlen;
362218822Sdim      rc_menuitem *mi;
36338889Sjdp
364218822Sdim      if (length < 16)
36560484Sobrien	toosmall (_("menuitem header"));
36638889Sjdp
367218822Sdim      mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
368218822Sdim      mi->type = windres_get_32 (wrbfd, data, 4);
369218822Sdim      mi->state = windres_get_32 (wrbfd, data + 4, 4);
370218822Sdim      mi->id = windres_get_32 (wrbfd, data + 8, 4);
37138889Sjdp
372218822Sdim      flags = windres_get_16 (wrbfd, data + 12, 2);
37338889Sjdp
374218822Sdim      if (windres_get_16 (wrbfd, data + 14, 2) == 0)
37538889Sjdp	{
37638889Sjdp	  slen = 0;
37738889Sjdp	  mi->text = NULL;
37838889Sjdp	}
37938889Sjdp      else
380218822Sdim	mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen);
38138889Sjdp
382218822Sdim      itemlen = 14 + slen * 2 + 2;
38338889Sjdp      itemlen = (itemlen + 3) &~ 3;
38438889Sjdp
38538889Sjdp      if ((flags & 1) == 0)
38638889Sjdp	{
38738889Sjdp	  mi->popup = NULL;
38838889Sjdp	  mi->help = 0;
38938889Sjdp	}
39038889Sjdp      else
39138889Sjdp	{
392218822Sdim	  rc_uint_type subread;
39338889Sjdp
39438889Sjdp	  if (length < itemlen + 4)
39560484Sobrien	    toosmall (_("menuitem"));
396218822Sdim	  mi->help = windres_get_32 (wrbfd, data + itemlen, 4);
39738889Sjdp	  itemlen += 4;
39838889Sjdp
399218822Sdim	  mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen,
400218822Sdim					      length - itemlen, &subread);
40138889Sjdp	  itemlen += subread;
40238889Sjdp	}
40338889Sjdp
40438889Sjdp      mi->next = NULL;
40538889Sjdp      *pp = mi;
40638889Sjdp      pp = &mi->next;
40738889Sjdp
40838889Sjdp      data += itemlen;
40938889Sjdp      length -= itemlen;
41038889Sjdp      *read += itemlen;
41138889Sjdp
41238889Sjdp      if ((flags & 0x80) != 0)
41338889Sjdp	return first;
41438889Sjdp    }
41538889Sjdp
41638889Sjdp  return first;
41738889Sjdp}
41838889Sjdp
41938889Sjdp/* Convert a dialog resource from binary.  */
42038889Sjdp
421218822Sdimstatic rc_res_resource *
422218822Sdimbin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
42338889Sjdp{
424218822Sdim  rc_uint_type signature;
425218822Sdim  rc_dialog *d;
426218822Sdim  rc_uint_type c, sublen, i;
427218822Sdim  rc_uint_type off;
428218822Sdim  rc_dialog_control **pp;
429218822Sdim  rc_res_resource *r;
43038889Sjdp
43138889Sjdp  if (length < 18)
43260484Sobrien    toosmall (_("dialog header"));
43338889Sjdp
434218822Sdim  d = (rc_dialog *) res_alloc (sizeof (rc_dialog));
43538889Sjdp
436218822Sdim  signature = windres_get_16 (wrbfd, data + 2, 2);
43799461Sobrien  if (signature != 0xffff)
43838889Sjdp    {
43938889Sjdp      d->ex = NULL;
440218822Sdim      d->style = windres_get_32 (wrbfd, data, 4);
441218822Sdim      d->exstyle = windres_get_32 (wrbfd, data + 4, 4);
44238889Sjdp      off = 8;
44338889Sjdp    }
44438889Sjdp  else
44538889Sjdp    {
44699461Sobrien      int version;
44738889Sjdp
448218822Sdim      version = windres_get_16 (wrbfd, data, 2);
44999461Sobrien      if (version != 1)
45099461Sobrien	fatal (_("unexpected DIALOGEX version %d"), version);
45138889Sjdp
452218822Sdim      d->ex = (rc_dialog_ex *) res_alloc (sizeof (rc_dialog_ex));
453218822Sdim      d->ex->help = windres_get_32 (wrbfd, data + 4, 4);
454218822Sdim      d->exstyle = windres_get_32 (wrbfd, data + 8, 4);
455218822Sdim      d->style = windres_get_32 (wrbfd, data + 12, 4);
45638889Sjdp      off = 16;
45738889Sjdp    }
45838889Sjdp
45938889Sjdp  if (length < off + 10)
46060484Sobrien    toosmall (_("dialog header"));
46138889Sjdp
462218822Sdim  c = windres_get_16 (wrbfd, data + off, 2);
463218822Sdim  d->x = windres_get_16 (wrbfd, data + off + 2, 2);
464218822Sdim  d->y = windres_get_16 (wrbfd, data + off + 4, 2);
465218822Sdim  d->width = windres_get_16 (wrbfd, data + off + 6, 2);
466218822Sdim  d->height = windres_get_16 (wrbfd, data + off + 8, 2);
46738889Sjdp
46838889Sjdp  off += 10;
46938889Sjdp
470218822Sdim  sublen = get_resid (wrbfd, &d->menu, data + off, length - off);
47138889Sjdp  off += sublen;
47238889Sjdp
473218822Sdim  sublen = get_resid (wrbfd, &d->class, data + off, length - off);
47438889Sjdp  off += sublen;
47538889Sjdp
476218822Sdim  d->caption = get_unicode (wrbfd, data + off, length - off, &sublen);
47738889Sjdp  off += sublen * 2 + 2;
478104834Sobrien  if (sublen == 0)
47999461Sobrien    d->caption = NULL;
48038889Sjdp
48138889Sjdp  if ((d->style & DS_SETFONT) == 0)
48238889Sjdp    {
48338889Sjdp      d->pointsize = 0;
48438889Sjdp      d->font = NULL;
48538889Sjdp      if (d->ex != NULL)
48638889Sjdp	{
48738889Sjdp	  d->ex->weight = 0;
48838889Sjdp	  d->ex->italic = 0;
48999461Sobrien	  d->ex->charset = 1; /* Default charset.  */
49038889Sjdp	}
49138889Sjdp    }
49238889Sjdp  else
49338889Sjdp    {
49438889Sjdp      if (length < off + 2)
49560484Sobrien	toosmall (_("dialog font point size"));
49638889Sjdp
497218822Sdim      d->pointsize = windres_get_16 (wrbfd, data + off, 2);
49838889Sjdp      off += 2;
49938889Sjdp
50038889Sjdp      if (d->ex != NULL)
50138889Sjdp	{
50238889Sjdp	  if (length < off + 4)
50360484Sobrien	    toosmall (_("dialogex font information"));
504218822Sdim	  d->ex->weight = windres_get_16 (wrbfd, data + off, 2);
505218822Sdim	  d->ex->italic = windres_get_8 (wrbfd, data + off + 2, 1);
506218822Sdim	  d->ex->charset = windres_get_8 (wrbfd, data + off + 3, 1);
50738889Sjdp	  off += 4;
50838889Sjdp	}
50938889Sjdp
510218822Sdim      d->font = get_unicode (wrbfd, data + off, length - off, &sublen);
51138889Sjdp      off += sublen * 2 + 2;
51238889Sjdp    }
51338889Sjdp
51438889Sjdp  d->controls = NULL;
51538889Sjdp  pp = &d->controls;
51638889Sjdp
51738889Sjdp  for (i = 0; i < c; i++)
51838889Sjdp    {
519218822Sdim      rc_dialog_control *dc;
52038889Sjdp      int datalen;
52138889Sjdp
52238889Sjdp      off = (off + 3) &~ 3;
52338889Sjdp
524218822Sdim      dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
52538889Sjdp
52638889Sjdp      if (d->ex == NULL)
52738889Sjdp	{
52838889Sjdp	  if (length < off + 8)
52960484Sobrien	    toosmall (_("dialog control"));
53038889Sjdp
531218822Sdim	  dc->style = windres_get_32 (wrbfd, data + off, 4);
532218822Sdim	  dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
53338889Sjdp	  dc->help = 0;
53438889Sjdp	  off += 8;
53538889Sjdp	}
53638889Sjdp      else
53738889Sjdp	{
53838889Sjdp	  if (length < off + 12)
53960484Sobrien	    toosmall (_("dialogex control"));
540218822Sdim	  dc->help = windres_get_32 (wrbfd, data + off, 4);
541218822Sdim	  dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
542218822Sdim	  dc->style = windres_get_32 (wrbfd, data + off + 8, 4);
54338889Sjdp	  off += 12;
54438889Sjdp	}
54538889Sjdp
546218822Sdim      if (length < off + (d->ex != NULL ? 2 : 0) + 10)
54760484Sobrien	toosmall (_("dialog control"));
54838889Sjdp
549218822Sdim      dc->x = windres_get_16 (wrbfd, data + off, 2);
550218822Sdim      dc->y = windres_get_16 (wrbfd, data + off + 2, 2);
551218822Sdim      dc->width = windres_get_16 (wrbfd, data + off + 4, 2);
552218822Sdim      dc->height = windres_get_16 (wrbfd, data + off + 6, 2);
55338889Sjdp
55460484Sobrien      if (d->ex != NULL)
555218822Sdim	dc->id = windres_get_32 (wrbfd, data + off + 8, 4);
55660484Sobrien      else
557218822Sdim	dc->id = windres_get_16 (wrbfd, data + off + 8, 2);
55838889Sjdp
55960484Sobrien      off += 10 + (d->ex != NULL ? 2 : 0);
56060484Sobrien
561218822Sdim      sublen = get_resid (wrbfd, &dc->class, data + off, length - off);
56238889Sjdp      off += sublen;
56338889Sjdp
564218822Sdim      sublen = get_resid (wrbfd, &dc->text, data + off, length - off);
56538889Sjdp      off += sublen;
56638889Sjdp
56738889Sjdp      if (length < off + 2)
56860484Sobrien	toosmall (_("dialog control end"));
56938889Sjdp
570218822Sdim      datalen = windres_get_16 (wrbfd, data + off, 2);
57138889Sjdp      off += 2;
57238889Sjdp
57338889Sjdp      if (datalen == 0)
57438889Sjdp	dc->data = NULL;
57538889Sjdp      else
57638889Sjdp	{
57738889Sjdp	  off = (off + 3) &~ 3;
57838889Sjdp
57938889Sjdp	  if (length < off + datalen)
58060484Sobrien	    toosmall (_("dialog control data"));
58138889Sjdp
582218822Sdim	  dc->data = ((rc_rcdata_item *)
583218822Sdim		      res_alloc (sizeof (rc_rcdata_item)));
58438889Sjdp	  dc->data->next = NULL;
58538889Sjdp	  dc->data->type = RCDATA_BUFFER;
58638889Sjdp	  dc->data->u.buffer.length = datalen;
58738889Sjdp	  dc->data->u.buffer.data = data + off;
58838889Sjdp
589104834Sobrien	  off += datalen;
59038889Sjdp	}
59138889Sjdp
59238889Sjdp      dc->next = NULL;
59338889Sjdp      *pp = dc;
59438889Sjdp      pp = &dc->next;
59538889Sjdp    }
59638889Sjdp
597218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
59838889Sjdp  r->type = RES_TYPE_DIALOG;
59938889Sjdp  r->u.dialog = d;
60038889Sjdp
60138889Sjdp  return r;
60238889Sjdp}
60338889Sjdp
60438889Sjdp/* Convert a stringtable resource from binary.  */
60538889Sjdp
606218822Sdimstatic rc_res_resource *
607218822Sdimbin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
60838889Sjdp{
609218822Sdim  rc_stringtable *st;
61038889Sjdp  int i;
611218822Sdim  rc_res_resource *r;
61238889Sjdp
613218822Sdim  st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable));
61438889Sjdp
61538889Sjdp  for (i = 0; i < 16; i++)
61638889Sjdp    {
61760484Sobrien      unsigned int slen;
61838889Sjdp
61938889Sjdp      if (length < 2)
62060484Sobrien	toosmall (_("stringtable string length"));
621218822Sdim      slen = windres_get_16 (wrbfd, data, 2);
62238889Sjdp      st->strings[i].length = slen;
62338889Sjdp
62438889Sjdp      if (slen > 0)
62538889Sjdp	{
62638889Sjdp	  unichar *s;
62760484Sobrien	  unsigned int j;
62838889Sjdp
62938889Sjdp	  if (length < 2 + 2 * slen)
63060484Sobrien	    toosmall (_("stringtable string"));
63138889Sjdp
63238889Sjdp	  s = (unichar *) res_alloc (slen * sizeof (unichar));
63338889Sjdp	  st->strings[i].string = s;
63438889Sjdp
63538889Sjdp	  for (j = 0; j < slen; j++)
636218822Sdim	    s[j] = windres_get_16 (wrbfd, data + 2 + j * 2, 2);
63738889Sjdp	}
63838889Sjdp
63938889Sjdp      data += 2 + 2 * slen;
64038889Sjdp      length -= 2 + 2 * slen;
64138889Sjdp    }
64238889Sjdp
643218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
64438889Sjdp  r->type = RES_TYPE_STRINGTABLE;
64538889Sjdp  r->u.stringtable = st;
64638889Sjdp
64738889Sjdp  return r;
64838889Sjdp}
64938889Sjdp
65038889Sjdp/* Convert a fontdir resource from binary.  */
65138889Sjdp
652218822Sdimstatic rc_res_resource *
653218822Sdimbin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
65438889Sjdp{
655218822Sdim  rc_uint_type c, i;
656218822Sdim  rc_fontdir *first, **pp;
657218822Sdim  rc_res_resource *r;
65838889Sjdp
65938889Sjdp  if (length < 2)
66060484Sobrien    toosmall (_("fontdir header"));
66138889Sjdp
662218822Sdim  c = windres_get_16 (wrbfd, data, 2);
66338889Sjdp
66438889Sjdp  first = NULL;
66538889Sjdp  pp = &first;
66638889Sjdp
66738889Sjdp  for (i = 0; i < c; i++)
66838889Sjdp    {
669218822Sdim      const struct bin_fontdir_item *bfi;
670218822Sdim      rc_fontdir *fd;
67160484Sobrien      unsigned int off;
67238889Sjdp
67338889Sjdp      if (length < 56)
67460484Sobrien	toosmall (_("fontdir"));
67538889Sjdp
676218822Sdim      bfi = (const struct bin_fontdir_item *) data;
677218822Sdim      fd = (rc_fontdir *) res_alloc (sizeof *fd);
678218822Sdim      fd->index = windres_get_16 (wrbfd, bfi->index, 2);
67938889Sjdp
68038889Sjdp      /* To work out the length of the fontdir data, we must get the
68138889Sjdp         length of the device name and face name strings, even though
682218822Sdim         we don't store them in the rc_fontdir.  The
68338889Sjdp         documentation says that these are NULL terminated char
68438889Sjdp         strings, not Unicode strings.  */
68538889Sjdp
68638889Sjdp      off = 56;
68738889Sjdp
68838889Sjdp      while (off < length && data[off] != '\0')
68938889Sjdp	++off;
69038889Sjdp      if (off >= length)
69160484Sobrien	toosmall (_("fontdir device name"));
69238889Sjdp      ++off;
69338889Sjdp
69438889Sjdp      while (off < length && data[off] != '\0')
69538889Sjdp	++off;
69638889Sjdp      if (off >= length)
69760484Sobrien	toosmall (_("fontdir face name"));
69838889Sjdp      ++off;
69938889Sjdp
70038889Sjdp      fd->length = off;
70138889Sjdp      fd->data = data;
70238889Sjdp
70338889Sjdp      fd->next = NULL;
70438889Sjdp      *pp = fd;
70538889Sjdp      pp = &fd->next;
70638889Sjdp
70738889Sjdp      /* The documentation does not indicate that any rounding is
70838889Sjdp         required.  */
70938889Sjdp
71038889Sjdp      data += off;
71138889Sjdp      length -= off;
71238889Sjdp    }
71338889Sjdp
714218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
71538889Sjdp  r->type = RES_TYPE_FONTDIR;
71638889Sjdp  r->u.fontdir = first;
71738889Sjdp
71838889Sjdp  return r;
71938889Sjdp}
72038889Sjdp
72138889Sjdp/* Convert an accelerators resource from binary.  */
72238889Sjdp
723218822Sdimstatic rc_res_resource *
724218822Sdimbin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
72538889Sjdp{
726218822Sdim  rc_accelerator *first, **pp;
727218822Sdim  rc_res_resource *r;
72838889Sjdp
72938889Sjdp  first = NULL;
73038889Sjdp  pp = &first;
73138889Sjdp
73238889Sjdp  while (1)
73338889Sjdp    {
734218822Sdim      rc_accelerator *a;
73538889Sjdp
73638889Sjdp      if (length < 8)
73760484Sobrien	toosmall (_("accelerator"));
73838889Sjdp
739218822Sdim      a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator));
74038889Sjdp
741218822Sdim      a->flags = windres_get_16 (wrbfd, data, 2);
742218822Sdim      a->key = windres_get_16 (wrbfd, data + 2, 2);
743218822Sdim      a->id = windres_get_16 (wrbfd, data + 4, 2);
74438889Sjdp
74538889Sjdp      a->next = NULL;
74638889Sjdp      *pp = a;
74738889Sjdp      pp = &a->next;
74838889Sjdp
74938889Sjdp      if ((a->flags & ACC_LAST) != 0)
75038889Sjdp	break;
75138889Sjdp
75238889Sjdp      data += 8;
75338889Sjdp      length -= 8;
75438889Sjdp    }
75538889Sjdp
756218822Sdim  r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
75738889Sjdp  r->type = RES_TYPE_ACCELERATOR;
75838889Sjdp  r->u.acc = first;
75938889Sjdp
76038889Sjdp  return r;
76138889Sjdp}
76238889Sjdp
76338889Sjdp/* Convert an rcdata resource from binary.  */
76438889Sjdp
765218822Sdimstatic rc_res_resource *
766218822Sdimbin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
767218822Sdim		   rc_uint_type length, int rctyp)
76838889Sjdp{
769218822Sdim  rc_rcdata_item *ri;
770218822Sdim  rc_res_resource *r;
77138889Sjdp
772218822Sdim  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
77338889Sjdp
77438889Sjdp  ri->next = NULL;
77538889Sjdp  ri->type = RCDATA_BUFFER;
77638889Sjdp  ri->u.buffer.length = length;
77738889Sjdp  ri->u.buffer.data = data;
77838889Sjdp
779218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
780218822Sdim  r->type = rctyp;
78138889Sjdp  r->u.rcdata = ri;
78238889Sjdp
78338889Sjdp  return r;
78438889Sjdp}
78538889Sjdp
78638889Sjdp/* Convert a group cursor resource from binary.  */
78738889Sjdp
788218822Sdimstatic rc_res_resource *
789218822Sdimbin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
79038889Sjdp{
79138889Sjdp  int type, c, i;
792218822Sdim  rc_group_cursor *first, **pp;
793218822Sdim  rc_res_resource *r;
79438889Sjdp
79538889Sjdp  if (length < 6)
79660484Sobrien    toosmall (_("group cursor header"));
79738889Sjdp
798218822Sdim  type = windres_get_16 (wrbfd, data + 2, 2);
79938889Sjdp  if (type != 2)
80060484Sobrien    fatal (_("unexpected group cursor type %d"), type);
80138889Sjdp
802218822Sdim  c = windres_get_16 (wrbfd, data + 4, 2);
80338889Sjdp
80438889Sjdp  data += 6;
80538889Sjdp  length -= 6;
80638889Sjdp
80738889Sjdp  first = NULL;
80838889Sjdp  pp = &first;
80938889Sjdp
81038889Sjdp  for (i = 0; i < c; i++)
81138889Sjdp    {
812218822Sdim      rc_group_cursor *gc;
81338889Sjdp
81438889Sjdp      if (length < 14)
81560484Sobrien	toosmall (_("group cursor"));
81638889Sjdp
817218822Sdim      gc = (rc_group_cursor *) res_alloc (sizeof *gc);
81838889Sjdp
819218822Sdim      gc->width = windres_get_16 (wrbfd, data, 2);
820218822Sdim      gc->height = windres_get_16 (wrbfd, data + 2, 2);
821218822Sdim      gc->planes = windres_get_16 (wrbfd, data + 4, 2);
822218822Sdim      gc->bits = windres_get_16 (wrbfd, data + 6, 2);
823218822Sdim      gc->bytes = windres_get_32 (wrbfd, data + 8, 4);
824218822Sdim      gc->index = windres_get_16 (wrbfd, data + 12, 2);
82538889Sjdp
82638889Sjdp      gc->next = NULL;
82738889Sjdp      *pp = gc;
82838889Sjdp      pp = &gc->next;
82938889Sjdp
83038889Sjdp      data += 14;
83138889Sjdp      length -= 14;
83238889Sjdp    }
83338889Sjdp
834218822Sdim  r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
83538889Sjdp  r->type = RES_TYPE_GROUP_CURSOR;
83638889Sjdp  r->u.group_cursor = first;
83738889Sjdp
83838889Sjdp  return r;
83938889Sjdp}
84038889Sjdp
84138889Sjdp/* Convert a group icon resource from binary.  */
84238889Sjdp
843218822Sdimstatic rc_res_resource *
844218822Sdimbin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
84538889Sjdp{
84638889Sjdp  int type, c, i;
847218822Sdim  rc_group_icon *first, **pp;
848218822Sdim  rc_res_resource *r;
84938889Sjdp
85038889Sjdp  if (length < 6)
85160484Sobrien    toosmall (_("group icon header"));
85238889Sjdp
853218822Sdim  type = windres_get_16 (wrbfd, data + 2, 2);
85438889Sjdp  if (type != 1)
85560484Sobrien    fatal (_("unexpected group icon type %d"), type);
85638889Sjdp
857218822Sdim  c = windres_get_16 (wrbfd, data + 4, 2);
85838889Sjdp
85938889Sjdp  data += 6;
86038889Sjdp  length -= 6;
86138889Sjdp
86238889Sjdp  first = NULL;
86338889Sjdp  pp = &first;
86438889Sjdp
86538889Sjdp  for (i = 0; i < c; i++)
86638889Sjdp    {
867218822Sdim      rc_group_icon *gi;
86838889Sjdp
86938889Sjdp      if (length < 14)
87060484Sobrien	toosmall (_("group icon"));
87138889Sjdp
872218822Sdim      gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
87338889Sjdp
874218822Sdim      gi->width = windres_get_8 (wrbfd, data, 1);
875218822Sdim      gi->height = windres_get_8 (wrbfd, data + 1, 1);
876218822Sdim      gi->colors = windres_get_8 (wrbfd, data + 2, 1);
877218822Sdim      gi->planes = windres_get_16 (wrbfd, data + 4, 2);
878218822Sdim      gi->bits = windres_get_16 (wrbfd, data + 6, 2);
879218822Sdim      gi->bytes = windres_get_32 (wrbfd, data + 8, 4);
880218822Sdim      gi->index = windres_get_16 (wrbfd, data + 12, 2);
88138889Sjdp
88238889Sjdp      gi->next = NULL;
88338889Sjdp      *pp = gi;
88438889Sjdp      pp = &gi->next;
88538889Sjdp
88638889Sjdp      data += 14;
88738889Sjdp      length -= 14;
88838889Sjdp    }
88938889Sjdp
890218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
89138889Sjdp  r->type = RES_TYPE_GROUP_ICON;
89238889Sjdp  r->u.group_icon = first;
89338889Sjdp
89438889Sjdp  return r;
89538889Sjdp}
89638889Sjdp
89738889Sjdp/* Extract data from a version header.  If KEY is not NULL, then the
89838889Sjdp   key must be KEY; otherwise, the key is returned in *PKEY.  This
89938889Sjdp   sets *LEN to the total length, *VALLEN to the value length, *TYPE
90038889Sjdp   to the type, and *OFF to the offset to the children.  */
90138889Sjdp
90238889Sjdpstatic void
903218822Sdimget_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
904218822Sdim		    const char *key, unichar **pkey,
905218822Sdim		    rc_uint_type *len, rc_uint_type *vallen, rc_uint_type *type,
906218822Sdim		    rc_uint_type *off)
90738889Sjdp{
90838889Sjdp  if (length < 8)
90938889Sjdp    toosmall (key);
91038889Sjdp
911218822Sdim  *len = windres_get_16 (wrbfd, data, 2);
912218822Sdim  *vallen = windres_get_16 (wrbfd, data + 2, 2);
913218822Sdim  *type = windres_get_16 (wrbfd, data + 4, 2);
91438889Sjdp
91538889Sjdp  *off = 6;
91638889Sjdp
91738889Sjdp  length -= 6;
91838889Sjdp  data += 6;
91938889Sjdp
92038889Sjdp  if (key == NULL)
92138889Sjdp    {
922218822Sdim      rc_uint_type sublen;
92338889Sjdp
924218822Sdim      *pkey = get_unicode (wrbfd, data, length, &sublen);
925218822Sdim      *off += (sublen + 1) * sizeof (unichar);
92638889Sjdp    }
92738889Sjdp  else
92838889Sjdp    {
92938889Sjdp      while (1)
93038889Sjdp	{
93138889Sjdp	  if (length < 2)
93238889Sjdp	    toosmall (key);
933218822Sdim	  if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key)
93460484Sobrien	    fatal (_("unexpected version string"));
93538889Sjdp
93638889Sjdp	  *off += 2;
93738889Sjdp	  length -= 2;
93838889Sjdp	  data += 2;
93938889Sjdp
94038889Sjdp	  if (*key == '\0')
94138889Sjdp	    break;
94238889Sjdp
94338889Sjdp	  ++key;
94438889Sjdp	}
94538889Sjdp    }
94638889Sjdp
94738889Sjdp  *off = (*off + 3) &~ 3;
94838889Sjdp}
94938889Sjdp
95038889Sjdp/* Convert a version resource from binary.  */
95138889Sjdp
952218822Sdimstatic rc_res_resource *
953218822Sdimbin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
95438889Sjdp{
955218822Sdim  rc_uint_type verlen, vallen, type, off;
956218822Sdim  rc_fixed_versioninfo *fi;
957218822Sdim  rc_ver_info *first, **pp;
958218822Sdim  rc_versioninfo *v;
959218822Sdim  rc_res_resource *r;
96038889Sjdp
961218822Sdim  get_version_header (wrbfd, data, length, "VS_VERSION_INFO",
96299461Sobrien		      (unichar **) NULL, &verlen, &vallen, &type, &off);
96338889Sjdp
96460484Sobrien  if ((unsigned int) verlen != length)
96560484Sobrien    fatal (_("version length %d does not match resource length %lu"),
966218822Sdim	   (int) verlen, (unsigned long) length);
96738889Sjdp
96838889Sjdp  if (type != 0)
969218822Sdim    fatal (_("unexpected version type %d"), (int) type);
97038889Sjdp
97138889Sjdp  data += off;
97238889Sjdp  length -= off;
97338889Sjdp
97438889Sjdp  if (vallen == 0)
97538889Sjdp    fi = NULL;
97638889Sjdp  else
97738889Sjdp    {
97838889Sjdp      unsigned long signature, fiv;
97938889Sjdp
98038889Sjdp      if (vallen != 52)
981218822Sdim	fatal (_("unexpected fixed version information length %ld"), (long) vallen);
98238889Sjdp
98338889Sjdp      if (length < 52)
98460484Sobrien	toosmall (_("fixed version info"));
98538889Sjdp
986218822Sdim      signature = windres_get_32 (wrbfd, data, 4);
98738889Sjdp      if (signature != 0xfeef04bd)
98860484Sobrien	fatal (_("unexpected fixed version signature %lu"), signature);
98938889Sjdp
990218822Sdim      fiv = windres_get_32 (wrbfd, data + 4, 4);
99138889Sjdp      if (fiv != 0 && fiv != 0x10000)
99260484Sobrien	fatal (_("unexpected fixed version info version %lu"), fiv);
99338889Sjdp
994218822Sdim      fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo));
99538889Sjdp
996218822Sdim      fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4);
997218822Sdim      fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4);
998218822Sdim      fi->product_version_ms = windres_get_32 (wrbfd, data + 16, 4);
999218822Sdim      fi->product_version_ls = windres_get_32 (wrbfd, data + 20, 4);
1000218822Sdim      fi->file_flags_mask = windres_get_32 (wrbfd, data + 24, 4);
1001218822Sdim      fi->file_flags = windres_get_32 (wrbfd, data + 28, 4);
1002218822Sdim      fi->file_os = windres_get_32 (wrbfd, data + 32, 4);
1003218822Sdim      fi->file_type = windres_get_32 (wrbfd, data + 36, 4);
1004218822Sdim      fi->file_subtype = windres_get_32 (wrbfd, data + 40, 4);
1005218822Sdim      fi->file_date_ms = windres_get_32 (wrbfd, data + 44, 4);
1006218822Sdim      fi->file_date_ls = windres_get_32 (wrbfd, data + 48, 4);
100738889Sjdp
100838889Sjdp      data += 52;
100938889Sjdp      length -= 52;
101038889Sjdp    }
101138889Sjdp
101238889Sjdp  first = NULL;
101338889Sjdp  pp = &first;
101438889Sjdp
101538889Sjdp  while (length > 0)
101638889Sjdp    {
1017218822Sdim      rc_ver_info *vi;
101838889Sjdp      int ch;
101938889Sjdp
102038889Sjdp      if (length < 8)
102160484Sobrien	toosmall (_("version var info"));
102238889Sjdp
1023218822Sdim      vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
102438889Sjdp
1025218822Sdim      ch = windres_get_16 (wrbfd, data + 6, 2);
102638889Sjdp
102738889Sjdp      if (ch == 'S')
102838889Sjdp	{
1029218822Sdim	  rc_ver_stringinfo **ppvs;
103038889Sjdp
103138889Sjdp	  vi->type = VERINFO_STRING;
103238889Sjdp
1033218822Sdim	  get_version_header (wrbfd, data, length, "StringFileInfo",
103499461Sobrien			      (unichar **) NULL, &verlen, &vallen, &type,
103538889Sjdp			      &off);
103638889Sjdp
103738889Sjdp	  if (vallen != 0)
1038218822Sdim	    fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen);
103938889Sjdp
104038889Sjdp	  data += off;
104138889Sjdp	  length -= off;
104238889Sjdp
1043218822Sdim	  get_version_header (wrbfd, data, length, (const char *) NULL,
104438889Sjdp			      &vi->u.string.language, &verlen, &vallen,
104538889Sjdp			      &type, &off);
104638889Sjdp
104738889Sjdp	  if (vallen != 0)
1048218822Sdim	    fatal (_("unexpected version stringtable value length %ld"), (long) vallen);
104938889Sjdp
105038889Sjdp	  data += off;
105138889Sjdp	  length -= off;
105238889Sjdp	  verlen -= off;
105338889Sjdp
105438889Sjdp	  vi->u.string.strings = NULL;
105538889Sjdp	  ppvs = &vi->u.string.strings;
105638889Sjdp
105738889Sjdp	  /* It's convenient to round verlen to a 4 byte alignment,
105838889Sjdp             since we round the subvariables in the loop.  */
105938889Sjdp	  verlen = (verlen + 3) &~ 3;
106038889Sjdp
106138889Sjdp	  while (verlen > 0)
106238889Sjdp	    {
1063218822Sdim	      rc_ver_stringinfo *vs;
1064218822Sdim	      rc_uint_type subverlen, vslen, valoff;
106538889Sjdp
1066218822Sdim	      vs = (rc_ver_stringinfo *) res_alloc (sizeof *vs);
106738889Sjdp
1068218822Sdim	      get_version_header (wrbfd, data, length,
106938889Sjdp				  (const char *) NULL, &vs->key, &subverlen,
107038889Sjdp				  &vallen, &type, &off);
107138889Sjdp
107238889Sjdp	      subverlen = (subverlen + 3) &~ 3;
107338889Sjdp
107438889Sjdp	      data += off;
107538889Sjdp	      length -= off;
107638889Sjdp
1077218822Sdim	      vs->value = get_unicode (wrbfd, data, length, &vslen);
107838889Sjdp	      valoff = vslen * 2 + 2;
107938889Sjdp	      valoff = (valoff + 3) &~ 3;
108038889Sjdp
108138889Sjdp	      if (off + valoff != subverlen)
1082218822Sdim		fatal (_("unexpected version string length %ld != %ld + %ld"),
1083218822Sdim		       (long) subverlen, (long) off, (long) valoff);
108438889Sjdp
108538889Sjdp	      vs->next = NULL;
108638889Sjdp	      *ppvs = vs;
108738889Sjdp	      ppvs = &vs->next;
108838889Sjdp
108938889Sjdp	      data += valoff;
109038889Sjdp	      length -= valoff;
109138889Sjdp
109238889Sjdp	      if (verlen < subverlen)
1093218822Sdim		fatal (_("unexpected version string length %ld < %ld"),
1094218822Sdim		       (long) verlen, (long) subverlen);
109538889Sjdp
109638889Sjdp	      verlen -= subverlen;
109738889Sjdp	    }
109838889Sjdp	}
109938889Sjdp      else if (ch == 'V')
110038889Sjdp	{
1101218822Sdim	  rc_ver_varinfo **ppvv;
110238889Sjdp
110338889Sjdp	  vi->type = VERINFO_VAR;
110438889Sjdp
1105218822Sdim	  get_version_header (wrbfd, data, length, "VarFileInfo",
110699461Sobrien			      (unichar **) NULL, &verlen, &vallen, &type,
110738889Sjdp			      &off);
110838889Sjdp
110938889Sjdp	  if (vallen != 0)
1110218822Sdim	    fatal (_("unexpected varfileinfo value length %ld"), (long) vallen);
111138889Sjdp
111238889Sjdp	  data += off;
111338889Sjdp	  length -= off;
111438889Sjdp
1115218822Sdim	  get_version_header (wrbfd, data, length, (const char *) NULL,
111638889Sjdp			      &vi->u.var.key, &verlen, &vallen, &type, &off);
111738889Sjdp
111838889Sjdp	  data += off;
111938889Sjdp	  length -= off;
112038889Sjdp
112138889Sjdp	  vi->u.var.var = NULL;
112238889Sjdp	  ppvv = &vi->u.var.var;
112338889Sjdp
112438889Sjdp	  while (vallen > 0)
112538889Sjdp	    {
1126218822Sdim	      rc_ver_varinfo *vv;
112738889Sjdp
112838889Sjdp	      if (length < 4)
112960484Sobrien		toosmall (_("version varfileinfo"));
113038889Sjdp
1131218822Sdim	      vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
113238889Sjdp
1133218822Sdim	      vv->language = windres_get_16 (wrbfd, data, 2);
1134218822Sdim	      vv->charset = windres_get_16 (wrbfd, data + 2, 2);
113538889Sjdp
113638889Sjdp	      vv->next = NULL;
113738889Sjdp	      *ppvv = vv;
113838889Sjdp	      ppvv = &vv->next;
113938889Sjdp
114038889Sjdp	      data += 4;
114138889Sjdp	      length -= 4;
114238889Sjdp
114338889Sjdp	      if (vallen < 4)
1144218822Sdim		fatal (_("unexpected version value length %ld"), (long) vallen);
114538889Sjdp
114638889Sjdp	      vallen -= 4;
114738889Sjdp	    }
114838889Sjdp	}
114938889Sjdp      else
115060484Sobrien	fatal (_("unexpected version string"));
115138889Sjdp
115238889Sjdp      vi->next = NULL;
115338889Sjdp      *pp = vi;
1154104834Sobrien      pp = &vi->next;
115538889Sjdp    }
115638889Sjdp
1157218822Sdim  v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo));
115838889Sjdp  v->fixed = fi;
115938889Sjdp  v->var = first;
116038889Sjdp
1161218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
116238889Sjdp  r->type = RES_TYPE_VERSIONINFO;
116338889Sjdp  r->u.versioninfo = v;
116438889Sjdp
1165104834Sobrien  return r;
116638889Sjdp}
116738889Sjdp
116838889Sjdp/* Convert an arbitrary user defined resource from binary.  */
116938889Sjdp
1170218822Sdimstatic rc_res_resource *
1171218822Sdimbin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
1172218822Sdim		     rc_uint_type length)
117338889Sjdp{
1174218822Sdim  rc_rcdata_item *ri;
1175218822Sdim  rc_res_resource *r;
117638889Sjdp
1177218822Sdim  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
117838889Sjdp
117938889Sjdp  ri->next = NULL;
118038889Sjdp  ri->type = RCDATA_BUFFER;
118138889Sjdp  ri->u.buffer.length = length;
118238889Sjdp  ri->u.buffer.data = data;
118338889Sjdp
1184218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
118538889Sjdp  r->type = RES_TYPE_USERDATA;
118638889Sjdp  r->u.rcdata = ri;
118738889Sjdp
118838889Sjdp  return r;
118938889Sjdp}
119038889Sjdp
1191218822Sdimstatic rc_res_resource *
1192218822Sdimbin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
1193218822Sdim{
1194218822Sdim  rc_toolbar *ri;
1195218822Sdim  rc_res_resource *r;
1196218822Sdim  rc_uint_type i;
119738889Sjdp
1198218822Sdim  ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
1199218822Sdim  ri->button_width = windres_get_32 (wrbfd, data, 4);
1200218822Sdim  ri->button_height = windres_get_32 (wrbfd, data + 4, 4);
1201218822Sdim  ri->nitems = windres_get_32 (wrbfd, data + 8, 4);
1202218822Sdim  ri->items = NULL;
120338889Sjdp
1204218822Sdim  data += 12;
1205218822Sdim  length -= 12;
1206218822Sdim  for (i=0 ; i < ri->nitems; i++)
1207218822Sdim  {
1208218822Sdim    rc_toolbar_item *it;
1209218822Sdim    it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item));
1210218822Sdim    it->id.named = 0;
1211218822Sdim    it->id.u.id = (int) windres_get_32 (wrbfd, data, 4);
1212218822Sdim    it->prev = it->next = NULL;
1213218822Sdim    data += 4;
1214218822Sdim    length -= 4;
1215218822Sdim    if(ri->items) {
1216218822Sdim      rc_toolbar_item *ii = ri->items;
1217218822Sdim      while (ii->next != NULL)
1218218822Sdim	ii = ii->next;
1219218822Sdim      it->prev = ii;
1220218822Sdim      ii->next = it;
1221218822Sdim    }
1222218822Sdim    else
1223218822Sdim      ri->items = it;
1224218822Sdim  }
1225218822Sdim  r = (rc_res_resource *) res_alloc (sizeof *r);
1226218822Sdim  r->type = RES_TYPE_TOOLBAR;
1227218822Sdim  r->u.toolbar = ri;
1228218822Sdim  return r;
1229218822Sdim}
1230218822Sdim
1231218822Sdim
123238889Sjdp/* Local functions used to convert resources to binary format.  */
123338889Sjdp
1234218822Sdimstatic rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id);
1235218822Sdimstatic rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *);
1236218822Sdimstatic rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *);
1237218822Sdimstatic rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *);
1238218822Sdimstatic rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *);
1239218822Sdimstatic rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *);
1240218822Sdimstatic rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *);
1241218822Sdimstatic rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *);
1242218822Sdimstatic rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *);
1243218822Sdimstatic rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
1244218822Sdimstatic rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
1245218822Sdimstatic rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *);
1246218822Sdimstatic rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *);
1247218822Sdimstatic rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *);
1248218822Sdimstatic rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb);
1249218822Sdimstatic rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *);
1250218822Sdimstatic rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type,
1251218822Sdim					const bfd_byte *);
125238889Sjdp
125338889Sjdp/* Convert a resource to binary.  */
125438889Sjdp
1255218822Sdimrc_uint_type
1256218822Sdimres_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res)
125738889Sjdp{
125838889Sjdp  switch (res->type)
125938889Sjdp    {
126038889Sjdp    case RES_TYPE_BITMAP:
126138889Sjdp    case RES_TYPE_FONT:
126238889Sjdp    case RES_TYPE_ICON:
126338889Sjdp    case RES_TYPE_MESSAGETABLE:
1264218822Sdim      return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data);
126538889Sjdp    case RES_TYPE_ACCELERATOR:
1266218822Sdim      return res_to_bin_accelerator (wrbfd, off, res->u.acc);
126738889Sjdp    case RES_TYPE_CURSOR:
1268218822Sdim      return res_to_bin_cursor (wrbfd, off, res->u.cursor);
126938889Sjdp    case RES_TYPE_GROUP_CURSOR:
1270218822Sdim      return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor);
127138889Sjdp    case RES_TYPE_DIALOG:
1272218822Sdim      return res_to_bin_dialog (wrbfd, off, res->u.dialog);
127338889Sjdp    case RES_TYPE_FONTDIR:
1274218822Sdim      return res_to_bin_fontdir (wrbfd, off, res->u.fontdir);
127538889Sjdp    case RES_TYPE_GROUP_ICON:
1276218822Sdim      return res_to_bin_group_icon (wrbfd, off, res->u.group_icon);
127738889Sjdp    case RES_TYPE_MENU:
1278218822Sdim      return res_to_bin_menu (wrbfd, off, res->u.menu);
127938889Sjdp    case RES_TYPE_STRINGTABLE:
1280218822Sdim      return res_to_bin_stringtable (wrbfd, off, res->u.stringtable);
1281218822Sdim    case RES_TYPE_VERSIONINFO:
1282218822Sdim      return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo);
1283218822Sdim    case RES_TYPE_TOOLBAR:
1284218822Sdim      return res_to_bin_toolbar (wrbfd, off, res->u.toolbar);
128538889Sjdp    case RES_TYPE_USERDATA:
1286218822Sdim    case RES_TYPE_RCDATA:
1287218822Sdim    default:
1288218822Sdim      return res_to_bin_rcdata (wrbfd, off, res->u.rcdata);
128938889Sjdp    }
129038889Sjdp}
129138889Sjdp
129238889Sjdp/* Convert a resource ID to binary.  This always returns exactly one
129338889Sjdp   bindata structure.  */
129438889Sjdp
1295218822Sdimstatic rc_uint_type
1296218822Sdimresid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id)
129738889Sjdp{
129838889Sjdp  if (! id.named)
129938889Sjdp    {
1300218822Sdim      if (wrbfd)
1301218822Sdim	{
1302218822Sdim	  struct bin_res_id bri;
1303218822Sdim
1304218822Sdim	  windres_put_16 (wrbfd, bri.sig, 0xffff);
1305218822Sdim	  windres_put_16 (wrbfd, bri.id, id.u.id);
1306218822Sdim	  set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID);
1307218822Sdim	}
1308218822Sdim      off += BIN_RES_ID;
130938889Sjdp    }
131038889Sjdp  else
131138889Sjdp    {
1312218822Sdim      rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0);
1313218822Sdim      if (wrbfd)
1314218822Sdim	{
1315218822Sdim	  bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
1316218822Sdim	  rc_uint_type i;
1317218822Sdim	  for (i = 0; i < len; i++)
1318218822Sdim	    windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]);
1319218822Sdim	  windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
1320218822Sdim	  set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
132138889Sjdp    }
1322218822Sdim      off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1323218822Sdim    }
1324218822Sdim  return off;
132538889Sjdp}
132638889Sjdp
132738889Sjdp/* Convert a null terminated unicode string to binary.  This always
132838889Sjdp   returns exactly one bindata structure.  */
132938889Sjdp
1330218822Sdimstatic rc_uint_type
1331218822Sdimunicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str)
133238889Sjdp{
1333218822Sdim  rc_uint_type len = 0;
133438889Sjdp
133538889Sjdp  if (str != NULL)
1336218822Sdim    len = unichar_len (str);
133738889Sjdp
1338218822Sdim  if (wrbfd)
133938889Sjdp    {
1340218822Sdim      bfd_byte *d;
1341218822Sdim      rc_uint_type i;
1342218822Sdim      d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar));
1343218822Sdim      for (i = 0; i < len; i++)
1344218822Sdim	windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]);
1345218822Sdim      windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
1346218822Sdim      set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
134738889Sjdp    }
1348218822Sdim  off += (rc_uint_type) ((len + 1) * sizeof (unichar));
134938889Sjdp
1350218822Sdim  return off;
135138889Sjdp}
135238889Sjdp
135338889Sjdp/* Convert an accelerator resource to binary.  */
135438889Sjdp
1355218822Sdimstatic rc_uint_type
1356218822Sdimres_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off,
1357218822Sdim			const rc_accelerator *accelerators)
135838889Sjdp{
1359218822Sdim  bindata *first, **pp;
1360218822Sdim  const rc_accelerator *a;
136138889Sjdp
136238889Sjdp  first = NULL;
136338889Sjdp  pp = &first;
136438889Sjdp
136538889Sjdp  for (a = accelerators; a != NULL; a = a->next)
136638889Sjdp    {
1367218822Sdim      if (wrbfd)
1368218822Sdim	{
1369218822Sdim	  struct bin_accelerator ba;
137038889Sjdp
1371218822Sdim	  windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST));
1372218822Sdim	  windres_put_16 (wrbfd, ba.key, a->key);
1373218822Sdim	  windres_put_16 (wrbfd, ba.id, a->id);
1374218822Sdim	  windres_put_16 (wrbfd, ba.pad, 0);
1375218822Sdim	  set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE);
137638889Sjdp    }
1377218822Sdim      off += BIN_ACCELERATOR_SIZE;
1378218822Sdim    }
1379218822Sdim  return off;
138038889Sjdp}
138138889Sjdp
138238889Sjdp/* Convert a cursor resource to binary.  */
138338889Sjdp
1384218822Sdimstatic rc_uint_type
1385218822Sdimres_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c)
138638889Sjdp{
1387218822Sdim  if (wrbfd)
1388218822Sdim    {
1389218822Sdim      struct bin_cursor bc;
139038889Sjdp
1391218822Sdim      windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot);
1392218822Sdim      windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot);
1393218822Sdim      set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE);
1394218822Sdim      if (c->length)
1395218822Sdim	set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length);
1396218822Sdim    }
1397218822Sdim  off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length);
1398218822Sdim  return off;
139938889Sjdp}
140038889Sjdp
140138889Sjdp/* Convert a group cursor resource to binary.  */
140238889Sjdp
1403218822Sdimstatic rc_uint_type
1404218822Sdimres_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off,
1405218822Sdim			 const rc_group_cursor *group_cursors)
140638889Sjdp{
1407218822Sdim  int c = 0;
1408218822Sdim  const rc_group_cursor *gc;
1409218822Sdim  struct bin_group_cursor bgc;
1410218822Sdim  struct bin_group_cursor_item bgci;
1411218822Sdim  rc_uint_type start = off;
141238889Sjdp
1413218822Sdim  off += BIN_GROUP_CURSOR_SIZE;
141438889Sjdp
1415218822Sdim  for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++)
141638889Sjdp    {
1417218822Sdim      if (wrbfd)
1418218822Sdim	{
1419218822Sdim	  windres_put_16 (wrbfd, bgci.width, gc->width);
1420218822Sdim	  windres_put_16 (wrbfd, bgci.height, gc->height);
1421218822Sdim	  windres_put_16 (wrbfd, bgci.planes, gc->planes);
1422218822Sdim	  windres_put_16 (wrbfd, bgci.bits, gc->bits);
1423218822Sdim	  windres_put_32 (wrbfd, bgci.bytes, gc->bytes);
1424218822Sdim	  windres_put_16 (wrbfd, bgci.index, gc->index);
1425218822Sdim	  set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE);
1426218822Sdim    }
142738889Sjdp
1428218822Sdim      off += BIN_GROUP_CURSOR_ITEM_SIZE;
142938889Sjdp    }
1430218822Sdim  if (wrbfd)
1431218822Sdim    {
1432218822Sdim      windres_put_16 (wrbfd, bgc.sig1, 0);
1433218822Sdim      windres_put_16 (wrbfd, bgc.sig2, 2);
1434218822Sdim      windres_put_16 (wrbfd, bgc.nitems, c);
1435218822Sdim      set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE);
1436218822Sdim    }
1437218822Sdim  return off;
143838889Sjdp}
143938889Sjdp
144038889Sjdp/* Convert a dialog resource to binary.  */
144138889Sjdp
1442218822Sdimstatic rc_uint_type
1443218822Sdimres_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog)
144438889Sjdp{
1445218822Sdim  rc_uint_type off_delta;
1446218822Sdim  rc_uint_type start, marker;
144738889Sjdp  int dialogex;
1448218822Sdim  int c;
1449218822Sdim  rc_dialog_control *dc;
1450218822Sdim  struct bin_dialogex bdx;
1451218822Sdim  struct bin_dialog bd;
145238889Sjdp
1453218822Sdim  off_delta = off;
1454218822Sdim  start = off;
145538889Sjdp  dialogex = extended_dialog (dialog);
145638889Sjdp
1457218822Sdim  if (wrbfd)
1458218822Sdim    {
145938889Sjdp  if (! dialogex)
146038889Sjdp    {
1461218822Sdim	  windres_put_32 (wrbfd, bd.style, dialog->style);
1462218822Sdim	  windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle);
1463218822Sdim	  windres_put_16 (wrbfd, bd.x, dialog->x);
1464218822Sdim	  windres_put_16 (wrbfd, bd.y, dialog->y);
1465218822Sdim	  windres_put_16 (wrbfd, bd.width, dialog->width);
1466218822Sdim	  windres_put_16 (wrbfd, bd.height, dialog->height);
146738889Sjdp    }
146838889Sjdp  else
146938889Sjdp    {
1470218822Sdim	  windres_put_16 (wrbfd, bdx.sig1, 1);
1471218822Sdim	  windres_put_16 (wrbfd, bdx.sig2, 0xffff);
1472218822Sdim	  windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0));
1473218822Sdim	  windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle);
1474218822Sdim	  windres_put_32 (wrbfd, bdx.style, dialog->style);
1475218822Sdim	  windres_put_16 (wrbfd, bdx.x, dialog->x);
1476218822Sdim	  windres_put_16 (wrbfd, bdx.y, dialog->y);
1477218822Sdim	  windres_put_16 (wrbfd, bdx.width, dialog->width);
1478218822Sdim	  windres_put_16 (wrbfd, bdx.height, dialog->height);
1479218822Sdim	}
148038889Sjdp    }
148138889Sjdp
1482218822Sdim  off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE);
148338889Sjdp
1484218822Sdim  off = resid_to_bin (wrbfd, off, dialog->menu);
1485218822Sdim  off = resid_to_bin (wrbfd, off, dialog->class);
1486218822Sdim  off = unicode_to_bin (wrbfd, off, dialog->caption);
148738889Sjdp
148838889Sjdp  if ((dialog->style & DS_SETFONT) != 0)
148938889Sjdp    {
1490218822Sdim      if (wrbfd)
149138889Sjdp	{
1492218822Sdim	  if (! dialogex)
149338889Sjdp	    {
1494218822Sdim	      struct bin_dialogfont bdf;
1495218822Sdim	      windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize);
1496218822Sdim	      set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE);
149738889Sjdp	    }
149838889Sjdp	  else
149938889Sjdp	    {
1500218822Sdim	      struct bin_dialogexfont bdxf;
1501218822Sdim	      windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize);
1502218822Sdim	      windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight));
1503218822Sdim	      windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic));
1504218822Sdim	      windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset));
1505218822Sdim	      set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE);
150638889Sjdp	    }
150738889Sjdp	}
1508218822Sdim      off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE);
1509218822Sdim      off = unicode_to_bin (wrbfd, off, dialog->font);
151038889Sjdp    }
1511218822Sdim  for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++)
151238889Sjdp    {
1513218822Sdim      bfd_byte dc_rclen[2];
151438889Sjdp
1515218822Sdim      off += (4 - ((off - off_delta) & 3)) & 3;
1516218822Sdim      if (wrbfd)
1517218822Sdim	{
151838889Sjdp      if (! dialogex)
151938889Sjdp	{
1520218822Sdim	      struct bin_dialog_control bdc;
1521218822Sdim
1522218822Sdim	      windres_put_32 (wrbfd, bdc.style, dc->style);
1523218822Sdim	      windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
1524218822Sdim	      windres_put_16 (wrbfd, bdc.x, dc->x);
1525218822Sdim	      windres_put_16 (wrbfd, bdc.y, dc->y);
1526218822Sdim	      windres_put_16 (wrbfd, bdc.width, dc->width);
1527218822Sdim	      windres_put_16 (wrbfd, bdc.height, dc->height);
1528218822Sdim	      windres_put_16 (wrbfd, bdc.id, dc->id);
1529218822Sdim	      set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE);
153038889Sjdp	}
153138889Sjdp      else
153238889Sjdp	{
1533218822Sdim	      struct bin_dialogex_control bdc;
153438889Sjdp
1535218822Sdim	      windres_put_32 (wrbfd, bdc.help, dc->help);
1536218822Sdim	      windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
1537218822Sdim	      windres_put_32 (wrbfd, bdc.style, dc->style);
1538218822Sdim	      windres_put_16 (wrbfd, bdc.x, dc->x);
1539218822Sdim	      windres_put_16 (wrbfd, bdc.y, dc->y);
1540218822Sdim	      windres_put_16 (wrbfd, bdc.width, dc->width);
1541218822Sdim	      windres_put_16 (wrbfd, bdc.height, dc->height);
1542218822Sdim	      windres_put_32 (wrbfd, bdc.id, dc->id);
1543218822Sdim	      set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE);
1544218822Sdim	    }
1545218822Sdim	}
1546218822Sdim      off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE);
154738889Sjdp
1548218822Sdim      off = resid_to_bin (wrbfd, off, dc->class);
1549218822Sdim      off = resid_to_bin (wrbfd, off, dc->text);
155060484Sobrien
1551218822Sdim      marker = off; /* Save two bytes for size of optional data.  */
1552218822Sdim      off += 2;
155338889Sjdp
155438889Sjdp      if (dc->data == NULL)
1555218822Sdim        {
1556218822Sdim	  if (wrbfd)
1557218822Sdim	    windres_put_16 (wrbfd, dc_rclen, 0);
1558218822Sdim	}
155938889Sjdp      else
156038889Sjdp	{
1561218822Sdim	  rc_uint_type saved_off = off;
1562218822Sdim	  rc_uint_type old_off;
1563218822Sdim	  off += (4 - ((off - off_delta) & 3)) & 3;
156438889Sjdp
1565218822Sdim	  old_off = off;
1566218822Sdim	  off = res_to_bin_rcdata (wrbfd, off, dc->data);
1567218822Sdim	  if ((off - old_off) == 0)
1568218822Sdim	    old_off = off = saved_off;
1569218822Sdim	  if (wrbfd)
1570218822Sdim	    windres_put_16 (wrbfd, dc_rclen, off - old_off);
157138889Sjdp	    }
1572218822Sdim      if (wrbfd)
1573218822Sdim	set_windres_bfd_content (wrbfd, dc_rclen, marker, 2);
1574218822Sdim	}
157538889Sjdp
1576218822Sdim  if (wrbfd)
1577218822Sdim    {
1578218822Sdim      windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c);
1579218822Sdim      if (! dialogex)
1580218822Sdim	set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE);
1581218822Sdim      else
1582218822Sdim	set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE);
158338889Sjdp    }
158438889Sjdp
1585218822Sdim  return off;
158638889Sjdp}
158738889Sjdp
158838889Sjdp/* Convert a fontdir resource to binary.  */
1589218822Sdimstatic rc_uint_type
1590218822Sdimres_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs)
159138889Sjdp{
1592218822Sdim  rc_uint_type start;
159338889Sjdp  int c;
1594218822Sdim  const rc_fontdir *fd;
159538889Sjdp
1596218822Sdim  start = off;
1597218822Sdim  off += 2;
159838889Sjdp
1599218822Sdim  for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++)
1600218822Sdim    {
1601218822Sdim      if (wrbfd)
1602218822Sdim	{
1603218822Sdim	  bfd_byte d[2];
1604218822Sdim	  windres_put_16 (wrbfd, d, fd->index);
1605218822Sdim	  set_windres_bfd_content (wrbfd, d, off, 2);
1606218822Sdim	  if (fd->length)
1607218822Sdim	    set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length);
1608218822Sdim	}
1609218822Sdim      off += (rc_uint_type) fd->length + 2;
1610218822Sdim    }
161138889Sjdp
1612218822Sdim  if (wrbfd)
161338889Sjdp    {
1614218822Sdim      bfd_byte d[2];
1615218822Sdim      windres_put_16 (wrbfd, d, c);
1616218822Sdim      set_windres_bfd_content (wrbfd, d, start, 2);
161738889Sjdp    }
1618218822Sdim  return off;
161938889Sjdp}
162038889Sjdp
162138889Sjdp/* Convert a group icon resource to binary.  */
162238889Sjdp
1623218822Sdimstatic rc_uint_type
1624218822Sdimres_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons)
162538889Sjdp{
1626218822Sdim  rc_uint_type start;
1627218822Sdim  struct bin_group_icon bgi;
162838889Sjdp  int c;
1629218822Sdim  const rc_group_icon *gi;
163038889Sjdp
1631218822Sdim  start = off;
1632218822Sdim  off += BIN_GROUP_ICON_SIZE;
163338889Sjdp
1634218822Sdim  for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++)
1635218822Sdim    {
1636218822Sdim      struct bin_group_icon_item bgii;
163738889Sjdp
1638218822Sdim      if (wrbfd)
1639218822Sdim	{
1640218822Sdim	  windres_put_8 (wrbfd, bgii.width, gi->width);
1641218822Sdim	  windres_put_8 (wrbfd, bgii.height, gi->height);
1642218822Sdim	  windres_put_8 (wrbfd, bgii.colors, gi->colors);
1643218822Sdim	  windres_put_8 (wrbfd, bgii.pad, 0);
1644218822Sdim	  windres_put_16 (wrbfd, bgii.planes, gi->planes);
1645218822Sdim	  windres_put_16 (wrbfd, bgii.bits, gi->bits);
1646218822Sdim	  windres_put_32 (wrbfd, bgii.bytes, gi->bytes);
1647218822Sdim	  windres_put_16 (wrbfd, bgii.index, gi->index);
1648218822Sdim	  set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE);
1649218822Sdim	}
1650218822Sdim      off += BIN_GROUP_ICON_ITEM_SIZE;
1651218822Sdim    }
165238889Sjdp
1653218822Sdim  if (wrbfd)
165438889Sjdp    {
1655218822Sdim      windres_put_16 (wrbfd, bgi.sig1, 0);
1656218822Sdim      windres_put_16 (wrbfd, bgi.sig2, 1);
1657218822Sdim      windres_put_16 (wrbfd, bgi.count, c);
1658218822Sdim      set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE);
165938889Sjdp    }
1660218822Sdim  return off;
166138889Sjdp}
166238889Sjdp
166338889Sjdp/* Convert a menu resource to binary.  */
166438889Sjdp
1665218822Sdimstatic rc_uint_type
1666218822Sdimres_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu)
166738889Sjdp{
166838889Sjdp  int menuex;
166938889Sjdp
167038889Sjdp  menuex = extended_menu (menu);
167138889Sjdp
1672218822Sdim  if (wrbfd)
1673218822Sdim    {
167438889Sjdp  if (! menuex)
167538889Sjdp    {
1676218822Sdim	  struct bin_menu bm;
1677218822Sdim	  windres_put_16 (wrbfd, bm.sig1, 0);
1678218822Sdim	  windres_put_16 (wrbfd, bm.sig2, 0);
1679218822Sdim	  set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE);
168038889Sjdp    }
168138889Sjdp  else
168238889Sjdp    {
1683218822Sdim	  struct bin_menuex bm;
1684218822Sdim	  windres_put_16 (wrbfd, bm.sig1, 1);
1685218822Sdim	  windres_put_16 (wrbfd, bm.sig2, 4);
1686218822Sdim	  windres_put_32 (wrbfd, bm.help, menu->help);
1687218822Sdim	  set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE);
168838889Sjdp    }
1689218822Sdim    }
1690218822Sdim  off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE);
1691218822Sdim  if (! menuex)
1692218822Sdim    {
1693218822Sdim      off = res_to_bin_menuitems (wrbfd, off, menu->items);
1694218822Sdim    }
1695218822Sdim  else
1696218822Sdim    {
1697218822Sdim      off = res_to_bin_menuexitems (wrbfd, off, menu->items);
1698218822Sdim    }
1699218822Sdim  return off;
170038889Sjdp}
170138889Sjdp
170238889Sjdp/* Convert menu items to binary.  */
170338889Sjdp
1704218822Sdimstatic rc_uint_type
1705218822Sdimres_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
170638889Sjdp{
1707218822Sdim  const rc_menuitem *mi;
170838889Sjdp
170938889Sjdp  for (mi = items; mi != NULL; mi = mi->next)
171038889Sjdp    {
1711218822Sdim      struct bin_menuitem bmi;
171238889Sjdp      int flags;
171338889Sjdp
171438889Sjdp      flags = mi->type;
171538889Sjdp      if (mi->next == NULL)
171638889Sjdp	flags |= MENUITEM_ENDMENU;
171738889Sjdp      if (mi->popup != NULL)
171838889Sjdp	flags |= MENUITEM_POPUP;
171938889Sjdp
1720218822Sdim      if (wrbfd)
1721218822Sdim	{
1722218822Sdim	  windres_put_16 (wrbfd, bmi.flags, flags);
172338889Sjdp      if (mi->popup == NULL)
1724218822Sdim	    windres_put_16 (wrbfd, bmi.id, mi->id);
1725218822Sdim	  set_windres_bfd_content (wrbfd, &bmi, off,
1726218822Sdim				   mi->popup == NULL ? BIN_MENUITEM_SIZE
1727218822Sdim				   		     : BIN_MENUITEM_POPUP_SIZE);
1728218822Sdim	}
1729218822Sdim      off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE);
173038889Sjdp
1731218822Sdim      off = unicode_to_bin (wrbfd, off, mi->text);
173238889Sjdp
173338889Sjdp      if (mi->popup != NULL)
173438889Sjdp	{
1735218822Sdim	  off = res_to_bin_menuitems (wrbfd, off, mi->popup);
173638889Sjdp	}
173738889Sjdp    }
1738218822Sdim  return off;
173938889Sjdp}
174038889Sjdp
174138889Sjdp/* Convert menuex items to binary.  */
174238889Sjdp
1743218822Sdimstatic rc_uint_type
1744218822Sdimres_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
174538889Sjdp{
1746218822Sdim  rc_uint_type off_delta = off;
1747218822Sdim  const rc_menuitem *mi;
174838889Sjdp
174938889Sjdp  for (mi = items; mi != NULL; mi = mi->next)
175038889Sjdp    {
1751218822Sdim      struct bin_menuitemex bmi;
175238889Sjdp      int flags;
175338889Sjdp
1754218822Sdim      off += (4 - ((off - off_delta) & 3)) & 3;
175538889Sjdp
175638889Sjdp      flags = 0;
175738889Sjdp      if (mi->next == NULL)
175838889Sjdp	flags |= 0x80;
175938889Sjdp      if (mi->popup != NULL)
176038889Sjdp	flags |= 1;
176138889Sjdp
1762218822Sdim      if (wrbfd)
1763218822Sdim	{
1764218822Sdim	  windres_put_32 (wrbfd, bmi.type, mi->type);
1765218822Sdim	  windres_put_32 (wrbfd, bmi.state, mi->state);
1766218822Sdim	  windres_put_32 (wrbfd, bmi.id, mi->id);
1767218822Sdim	  windres_put_16 (wrbfd, bmi.flags, flags);
1768218822Sdim	  set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE);
1769218822Sdim	}
1770218822Sdim      off += BIN_MENUITEMEX_SIZE;
177138889Sjdp
1772218822Sdim      off = unicode_to_bin (wrbfd, off, mi->text);
177338889Sjdp
177438889Sjdp      if (mi->popup != NULL)
177538889Sjdp	{
1776218822Sdim	  bfd_byte help[4];
177738889Sjdp
1778218822Sdim	  off += (4 - ((off - off_delta) & 3)) & 3;
177938889Sjdp
1780218822Sdim	  if (wrbfd)
178138889Sjdp	    {
1782218822Sdim	      windres_put_32 (wrbfd, help, mi->help);
1783218822Sdim	      set_windres_bfd_content (wrbfd, help, off, 4);
178438889Sjdp	    }
1785218822Sdim	  off += 4;
1786218822Sdim	  off = res_to_bin_menuexitems (wrbfd, off, mi->popup);
178738889Sjdp	}
178838889Sjdp    }
1789218822Sdim  return off;
179038889Sjdp}
179138889Sjdp
179238889Sjdp/* Convert an rcdata resource to binary.  This is also used to convert
1793218822Sdim   other information which happens to be stored in rc_rcdata_item lists
179438889Sjdp   to binary.  */
179538889Sjdp
1796218822Sdimstatic rc_uint_type
1797218822Sdimres_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items)
179838889Sjdp{
1799218822Sdim  const rc_rcdata_item *ri;
180038889Sjdp
180138889Sjdp  for (ri = items; ri != NULL; ri = ri->next)
180238889Sjdp    {
1803218822Sdim      rc_uint_type len;
180438889Sjdp      switch (ri->type)
180538889Sjdp	{
180638889Sjdp	default:
180738889Sjdp	  abort ();
180838889Sjdp	case RCDATA_WORD:
1809218822Sdim	  len = 2;
181038889Sjdp	  break;
181138889Sjdp	case RCDATA_DWORD:
1812218822Sdim	  len = 4;
181338889Sjdp	  break;
181438889Sjdp	case RCDATA_STRING:
1815218822Sdim	  len = ri->u.string.length;
181638889Sjdp	  break;
181738889Sjdp	case RCDATA_WSTRING:
1818218822Sdim	  len = ri->u.wstring.length * sizeof (unichar);
1819218822Sdim	  break;
1820218822Sdim	case RCDATA_BUFFER:
1821218822Sdim	  len = ri->u.buffer.length;
1822218822Sdim	  break;
1823218822Sdim	}
1824218822Sdim      if (wrbfd)
1825218822Sdim	{
1826218822Sdim	  bfd_byte h[4];
1827218822Sdim	  bfd_byte *hp = &h[0];
1828218822Sdim	  switch (ri->type)
1829218822Sdim	    {
1830218822Sdim	    case RCDATA_WORD:
1831218822Sdim	      windres_put_16 (wrbfd, hp, ri->u.word);
1832218822Sdim	      break;
1833218822Sdim	    case RCDATA_DWORD:
1834218822Sdim	      windres_put_32 (wrbfd, hp, ri->u.dword);
1835218822Sdim	      break;
1836218822Sdim	    case RCDATA_STRING:
1837218822Sdim	      hp = (bfd_byte *) ri->u.string.s;
1838218822Sdim	  break;
1839218822Sdim	case RCDATA_WSTRING:
184038889Sjdp	  {
1841218822Sdim		rc_uint_type i;
184238889Sjdp
1843218822Sdim		hp = (bfd_byte *) reswr_alloc (len);
184438889Sjdp	    for (i = 0; i < ri->u.wstring.length; i++)
1845218822Sdim		  windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]);
184638889Sjdp	  }
1847218822Sdim	      break;
184838889Sjdp	case RCDATA_BUFFER:
1849218822Sdim	      hp = (bfd_byte *) ri->u.buffer.data;
185038889Sjdp	  break;
185138889Sjdp	}
1852218822Sdim	  set_windres_bfd_content (wrbfd, hp, off, len);
185338889Sjdp    }
1854218822Sdim      off += len;
1855218822Sdim    }
1856218822Sdim  return off;
185738889Sjdp}
185838889Sjdp
185938889Sjdp/* Convert a stringtable resource to binary.  */
186038889Sjdp
1861218822Sdimstatic rc_uint_type
1862218822Sdimres_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off,
1863218822Sdim			const rc_stringtable *st)
186438889Sjdp{
186538889Sjdp  int i;
186638889Sjdp
186738889Sjdp  for (i = 0; i < 16; i++)
186838889Sjdp    {
1869218822Sdim      rc_uint_type slen, length;
187038889Sjdp      unichar *s;
187138889Sjdp
1872218822Sdim      slen = (rc_uint_type) st->strings[i].length;
187338889Sjdp      s = st->strings[i].string;
187438889Sjdp
1875218822Sdim      length = 2 + slen * 2;
1876218822Sdim      if (wrbfd)
1877218822Sdim	{
1878218822Sdim	  bfd_byte *hp;
1879218822Sdim	  rc_uint_type j;
188038889Sjdp
1881218822Sdim	  hp = (bfd_byte *) reswr_alloc (length);
1882218822Sdim	  windres_put_16 (wrbfd, hp, slen);
188338889Sjdp
188438889Sjdp      for (j = 0; j < slen; j++)
1885218822Sdim	    windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]);
1886218822Sdim	  set_windres_bfd_content (wrbfd, hp, off, length);
188738889Sjdp    }
1888218822Sdim      off += length;
1889218822Sdim    }
1890218822Sdim  return off;
189138889Sjdp}
189238889Sjdp
189338889Sjdp/* Convert an ASCII string to a unicode binary string.  This always
189438889Sjdp   returns exactly one bindata structure.  */
189538889Sjdp
1896218822Sdimstatic rc_uint_type
1897218822Sdimstring_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s)
189838889Sjdp{
1899218822Sdim  rc_uint_type len;
190038889Sjdp
1901218822Sdim  len = (rc_uint_type) strlen (s);
190238889Sjdp
1903218822Sdim  if (wrbfd)
1904218822Sdim    {
1905218822Sdim      rc_uint_type i;
1906218822Sdim      bfd_byte *hp;
190738889Sjdp
1908218822Sdim      hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
190938889Sjdp
1910218822Sdim      for (i = 0; i < len; i++)
1911218822Sdim	windres_put_16 (wrbfd, hp + i * 2, s[i]);
1912218822Sdim      windres_put_16 (wrbfd, hp + i * 2, 0);
1913218822Sdim      set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar));
1914218822Sdim    }
1915218822Sdim  off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1916218822Sdim  return off;
191738889Sjdp}
191838889Sjdp
1919218822Sdimstatic rc_uint_type
1920218822Sdimres_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb)
192138889Sjdp{
1922218822Sdim  if (wrbfd)
1923218822Sdim    {
1924218822Sdim      struct bin_toolbar bt;
1925218822Sdim      windres_put_32 (wrbfd, bt.button_width, tb->button_width);
1926218822Sdim      windres_put_32 (wrbfd, bt.button_height, tb->button_height);
1927218822Sdim      windres_put_32 (wrbfd, bt.nitems, tb->nitems);
1928218822Sdim      set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE);
1929218822Sdim      if (tb->nitems > 0)
1930218822Sdim	{
1931218822Sdim	  rc_toolbar_item *it;
1932218822Sdim	  bfd_byte *ids;
1933218822Sdim	  rc_uint_type i = 0;
193438889Sjdp
1935218822Sdim	  ids = (bfd_byte *) reswr_alloc (tb->nitems * 4);
1936218822Sdim	  it=tb->items;
1937218822Sdim	  while(it != NULL)
1938218822Sdim	    {
1939218822Sdim	      windres_put_32 (wrbfd, ids + i, it->id.u.id);
1940218822Sdim	      i += 4;
1941218822Sdim	      it = it->next;
1942218822Sdim	    }
1943218822Sdim	  set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i);
1944218822Sdim 	}
1945218822Sdim    }
1946218822Sdim  off += BIN_TOOLBAR_SIZE + tb->nitems * 4;
194738889Sjdp
1948218822Sdim  return off;
1949218822Sdim}
195038889Sjdp
1951218822Sdim/* Convert a versioninfo resource to binary.  */
195238889Sjdp
1953218822Sdimstatic rc_uint_type
1954218822Sdimres_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off,
1955218822Sdim			const rc_versioninfo *versioninfo)
1956218822Sdim{
1957218822Sdim  rc_uint_type off_delta = off;
1958218822Sdim  rc_uint_type start;
1959218822Sdim  struct bin_versioninfo bvi;
1960218822Sdim  rc_ver_info *vi;
196138889Sjdp
1962218822Sdim  start = off;
1963218822Sdim  off += BIN_VERSIONINFO_SIZE;
1964218822Sdim  off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO");
1965218822Sdim  off += (4 - ((off - off_delta) & 3)) & 3;
196638889Sjdp
196738889Sjdp  if (versioninfo->fixed != NULL)
196838889Sjdp    {
1969218822Sdim      if (wrbfd)
1970218822Sdim	{
1971218822Sdim	  struct bin_fixed_versioninfo bfv;
1972218822Sdim	  const rc_fixed_versioninfo *fi;
197338889Sjdp
197438889Sjdp      fi = versioninfo->fixed;
1975218822Sdim	  windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd);
1976218822Sdim	  windres_put_32 (wrbfd, bfv.sig2, 0x10000);
1977218822Sdim	  windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms);
1978218822Sdim	  windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls);
1979218822Sdim	  windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms);
1980218822Sdim	  windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls);
1981218822Sdim	  windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask);
1982218822Sdim	  windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags);
1983218822Sdim	  windres_put_32 (wrbfd, bfv.file_os, fi->file_os);
1984218822Sdim	  windres_put_32 (wrbfd, bfv.file_type, fi->file_type);
1985218822Sdim	  windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype);
1986218822Sdim	  windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms);
1987218822Sdim	  windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls);
1988218822Sdim	  set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE);
1989218822Sdim	}
1990218822Sdim      off += BIN_FIXED_VERSIONINFO_SIZE;
199138889Sjdp    }
199238889Sjdp
199338889Sjdp  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
199438889Sjdp    {
1995218822Sdim      struct bin_ver_info bv;
1996218822Sdim      rc_uint_type bv_off;
199738889Sjdp
1998218822Sdim      off += (4 - ((off - off_delta) & 3)) & 3;
199938889Sjdp
2000218822Sdim      bv_off = off;
200138889Sjdp
2002218822Sdim      off += BIN_VER_INFO_SIZE;
200338889Sjdp
200438889Sjdp      switch (vi->type)
200538889Sjdp	{
200638889Sjdp	default:
200738889Sjdp	  abort ();
200838889Sjdp	case VERINFO_STRING:
200938889Sjdp	  {
2010218822Sdim	    struct bin_ver_info bvsd;
2011218822Sdim	    rc_uint_type vs_off;
2012218822Sdim	    const rc_ver_stringinfo *vs;
201338889Sjdp
2014218822Sdim	    off = string_to_unicode_bin (wrbfd, off, "StringFileInfo");
2015218822Sdim	    off += (4 - ((off - off_delta) & 3)) & 3;
201638889Sjdp
2017218822Sdim	    vs_off = off;
201838889Sjdp
2019218822Sdim	    off += BIN_VER_INFO_SIZE;
202038889Sjdp
2021218822Sdim	    off = unicode_to_bin (wrbfd, off, vi->u.string.language);
202238889Sjdp
202338889Sjdp	    for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
202438889Sjdp	      {
2025218822Sdim		struct bin_ver_info bvss;
2026218822Sdim		rc_uint_type vss_off,str_off;
202738889Sjdp
2028218822Sdim		off += (4 - ((off - off_delta) & 3)) & 3;
202938889Sjdp
2030218822Sdim		vss_off = off;
2031218822Sdim		off += BIN_VER_INFO_SIZE;
203238889Sjdp
2033218822Sdim		off = unicode_to_bin (wrbfd, off, vs->key);
203438889Sjdp
2035218822Sdim		off += (4 - ((off - off_delta) & 3)) & 3;
203638889Sjdp
2037218822Sdim		str_off = off;
2038218822Sdim		off = unicode_to_bin (wrbfd, off, vs->value);
2039218822Sdim		if (wrbfd)
2040218822Sdim		  {
2041218822Sdim		    windres_put_16 (wrbfd, bvss.size, off - vss_off);
2042218822Sdim		    windres_put_16 (wrbfd, bvss.sig1, (off - str_off) / 2);
2043218822Sdim		    windres_put_16 (wrbfd, bvss.sig2, 1);
2044218822Sdim		    set_windres_bfd_content (wrbfd, &bvss, vss_off,
2045218822Sdim		    			     BIN_VER_INFO_SIZE);
2046218822Sdim		  }
204738889Sjdp	      }
2048218822Sdim	    if (wrbfd)
2049218822Sdim	      {
2050218822Sdim		windres_put_16 (wrbfd, bvsd.size, off - vs_off);
2051218822Sdim		windres_put_16 (wrbfd, bvsd.sig1, 0);
2052218822Sdim		windres_put_16 (wrbfd, bvsd.sig2, 0);
2053218822Sdim		set_windres_bfd_content (wrbfd, &bvsd, vs_off,
2054218822Sdim					 BIN_VER_INFO_SIZE);
2055218822Sdim	      }
205638889Sjdp	    break;
205738889Sjdp	  }
205838889Sjdp
205938889Sjdp	case VERINFO_VAR:
206038889Sjdp	  {
2061218822Sdim	    rc_uint_type vvd_off, vvvd_off;
2062218822Sdim	    struct bin_ver_info bvvd;
2063218822Sdim	    const rc_ver_varinfo *vv;
206438889Sjdp
2065218822Sdim	    off = string_to_unicode_bin (wrbfd, off, "VarFileInfo");
206638889Sjdp
2067218822Sdim	    off += (4 - ((off - off_delta) & 3)) & 3;
206838889Sjdp
2069218822Sdim	    vvd_off = off;
2070218822Sdim	    off += BIN_VER_INFO_SIZE;
207138889Sjdp
2072218822Sdim	    off = unicode_to_bin (wrbfd, off, vi->u.var.key);
207338889Sjdp
2074218822Sdim	    off += (4 - ((off - off_delta) & 3)) & 3;
207538889Sjdp
2076218822Sdim	    vvvd_off = off;
207738889Sjdp
207838889Sjdp	    for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
207938889Sjdp	      {
2080218822Sdim		if (wrbfd)
2081218822Sdim		  {
2082218822Sdim		    bfd_byte vvsd[4];
208338889Sjdp
2084218822Sdim		    windres_put_16 (wrbfd, &vvsd[0], vv->language);
2085218822Sdim		    windres_put_16 (wrbfd, &vvsd[2], vv->charset);
2086218822Sdim		    set_windres_bfd_content (wrbfd, vvsd, off, 4);
2087218822Sdim		  }
2088218822Sdim		off += 4;
208938889Sjdp	      }
2090218822Sdim	    if (wrbfd)
2091218822Sdim	    {
2092218822Sdim		windres_put_16 (wrbfd, bvvd.size, off - vvd_off);
2093218822Sdim		windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off);
2094218822Sdim		windres_put_16 (wrbfd, bvvd.sig2, 0);
2095218822Sdim		set_windres_bfd_content (wrbfd, &bvvd, vvd_off,
2096218822Sdim					 BIN_VER_INFO_SIZE);
2097218822Sdim	    }
209838889Sjdp
209938889Sjdp	    break;
210038889Sjdp	  }
210138889Sjdp	}
210238889Sjdp
2103218822Sdim      if (wrbfd)
2104218822Sdim	{
2105218822Sdim	  windres_put_16 (wrbfd, bv.size, off-bv_off);
2106218822Sdim	  windres_put_16 (wrbfd, bv.sig1, 0);
2107218822Sdim	  windres_put_16 (wrbfd, bv.sig2, 0);
2108218822Sdim	  set_windres_bfd_content (wrbfd, &bv, bv_off,
2109218822Sdim	  			   BIN_VER_INFO_SIZE);
2110218822Sdim	}
211138889Sjdp    }
211238889Sjdp
2113218822Sdim  if (wrbfd)
2114218822Sdim    {
2115218822Sdim      windres_put_16 (wrbfd, bvi.size, off - start);
2116218822Sdim      windres_put_16 (wrbfd, bvi.fixed_size,
2117218822Sdim		      versioninfo->fixed == NULL ? 0
2118218822Sdim		      				 : BIN_FIXED_VERSIONINFO_SIZE);
2119218822Sdim      windres_put_16 (wrbfd, bvi.sig2, 0);
2120218822Sdim      set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE);
2121218822Sdim    }
2122218822Sdim  return off;
212338889Sjdp}
212438889Sjdp
212538889Sjdp/* Convert a generic resource to binary.  */
212638889Sjdp
2127218822Sdimstatic rc_uint_type
2128218822Sdimres_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length,
2129218822Sdim		    const bfd_byte *data)
213038889Sjdp{
2131218822Sdim  if (wrbfd && length != 0)
2132218822Sdim    set_windres_bfd_content (wrbfd, data, off, length);
2133218822Sdim  return off + (rc_uint_type) length;
213438889Sjdp}
2135