OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [binutils/] [resbin.c] - Blame information for rev 252

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.