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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [binutils/] [resbin.c] - Blame information for rev 163

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 15 khays
/* resbin.c -- manipulate the Windows binary resource format.
2 163 khays
   Copyright 1997, 1998, 1999, 2002, 2003, 2005, 2006, 2007, 2009, 2010, 2011
3 15 khays
   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, got;
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, &got);
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), &got);
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 *got)
274
{
275
  rc_menuitem *first, **pp;
276
 
277
  first = NULL;
278
  pp = &first;
279
 
280
  *got = 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
      *got += 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 *got)
351
{
352
  rc_menuitem *first, **pp;
353
 
354
  first = NULL;
355
  pp = &first;
356
 
357
  *got = 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
      *got += 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 163 khays
          rc_ver_stringtable **ppvst;
1031 15 khays
 
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
          /* It's convenient to round verlen to a 4 byte alignment,
1045
             since we round the subvariables in the loop.  */
1046 163 khays
 
1047 15 khays
          verlen = (verlen + 3) &~ 3;
1048
 
1049 163 khays
          vi->u.string.stringtables = NULL;
1050
          ppvst = &vi->u.string.stringtables;
1051
 
1052 15 khays
          while (verlen > 0)
1053
            {
1054 163 khays
              rc_ver_stringtable *vst;
1055
              rc_uint_type stverlen;
1056
              rc_ver_stringinfo **ppvs;
1057
 
1058
              if (length < 8)
1059
                toosmall (_("version stringtable"));
1060
 
1061
              vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable));
1062
 
1063
              get_version_header (wrbfd, data, length, (const char *) NULL,
1064
                                  &vst->language, &stverlen, &vallen, &type, &off);
1065
 
1066
              if (vallen != 0)
1067
                fatal (_("unexpected version stringtable value length %ld"), (long) vallen);
1068
 
1069
              data += off;
1070
              length -= off;
1071
              verlen -= off;
1072
 
1073
          stverlen = (stverlen + 3) &~ 3;
1074
 
1075
          vst->strings = NULL;
1076
          ppvs = &vst->strings;
1077
 
1078
          while (stverlen > 0)
1079
            {
1080 15 khays
              rc_ver_stringinfo *vs;
1081 163 khays
              rc_uint_type sverlen, vslen, valoff;
1082 15 khays
 
1083 163 khays
              if (length < 8)
1084
                toosmall (_("version string"));
1085 15 khays
 
1086 163 khays
              vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo));
1087 15 khays
 
1088 163 khays
              get_version_header (wrbfd, data, length, (const char *) NULL,
1089
                                  &vs->key, &sverlen, &vallen, &type, &off);
1090 15 khays
 
1091 163 khays
              sverlen = (sverlen + 3) &~ 3;
1092
 
1093 15 khays
              data += off;
1094
              length -= off;
1095
 
1096
              vs->value = get_unicode (wrbfd, data, length, &vslen);
1097
              valoff = vslen * 2 + 2;
1098
              valoff = (valoff + 3) &~ 3;
1099
 
1100 163 khays
              if (off + valoff != sverlen)
1101 15 khays
                fatal (_("unexpected version string length %ld != %ld + %ld"),
1102 163 khays
                       (long) sverlen, (long) off, (long) valoff);
1103 15 khays
 
1104
              data += valoff;
1105
              length -= valoff;
1106
 
1107 163 khays
              if (stverlen < sverlen)
1108 15 khays
                fatal (_("unexpected version string length %ld < %ld"),
1109 163 khays
                       (long) verlen, (long) sverlen);
1110
              stverlen -= sverlen;
1111 15 khays
 
1112 163 khays
              vs->next = NULL;
1113
              *ppvs = vs;
1114
              ppvs = &vs->next;
1115 15 khays
            }
1116 163 khays
 
1117
          vst->next = NULL;
1118
          *ppvst = vst;
1119
          ppvst = &vst->next;
1120
            }
1121 15 khays
        }
1122
      else if (ch == 'V')
1123
        {
1124
          rc_ver_varinfo **ppvv;
1125
 
1126
          vi->type = VERINFO_VAR;
1127
 
1128
          get_version_header (wrbfd, data, length, "VarFileInfo",
1129
                              (unichar **) NULL, &verlen, &vallen, &type,
1130
                              &off);
1131
 
1132
          if (vallen != 0)
1133
            fatal (_("unexpected varfileinfo value length %ld"), (long) vallen);
1134
 
1135
          data += off;
1136
          length -= off;
1137
 
1138
          get_version_header (wrbfd, data, length, (const char *) NULL,
1139
                              &vi->u.var.key, &verlen, &vallen, &type, &off);
1140
 
1141
          data += off;
1142
          length -= off;
1143
 
1144
          vi->u.var.var = NULL;
1145
          ppvv = &vi->u.var.var;
1146
 
1147
          while (vallen > 0)
1148
            {
1149
              rc_ver_varinfo *vv;
1150
 
1151
              if (length < 4)
1152
                toosmall (_("version varfileinfo"));
1153
 
1154
              vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
1155
 
1156
              vv->language = windres_get_16 (wrbfd, data, 2);
1157
              vv->charset = windres_get_16 (wrbfd, data + 2, 2);
1158
 
1159
              vv->next = NULL;
1160
              *ppvv = vv;
1161
              ppvv = &vv->next;
1162
 
1163
              data += 4;
1164
              length -= 4;
1165
 
1166
              if (vallen < 4)
1167
                fatal (_("unexpected version value length %ld"), (long) vallen);
1168
 
1169
              vallen -= 4;
1170
            }
1171
        }
1172
      else
1173
        fatal (_("unexpected version string"));
1174
 
1175
      vi->next = NULL;
1176
      *pp = vi;
1177
      pp = &vi->next;
1178
    }
1179
 
1180
  v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo));
1181
  v->fixed = fi;
1182
  v->var = first;
1183
 
1184
  r = (rc_res_resource *) res_alloc (sizeof *r);
1185
  r->type = RES_TYPE_VERSIONINFO;
1186
  r->u.versioninfo = v;
1187
 
1188
  return r;
1189
}
1190
 
1191
/* Convert an arbitrary user defined resource from binary.  */
1192
 
1193
static rc_res_resource *
1194
bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data,
1195
                     rc_uint_type length)
1196
{
1197
  rc_rcdata_item *ri;
1198
  rc_res_resource *r;
1199
 
1200
  ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1201
 
1202
  ri->next = NULL;
1203
  ri->type = RCDATA_BUFFER;
1204
  ri->u.buffer.length = length;
1205
  ri->u.buffer.data = data;
1206
 
1207
  r = (rc_res_resource *) res_alloc (sizeof *r);
1208
  r->type = RES_TYPE_USERDATA;
1209
  r->u.rcdata = ri;
1210
 
1211
  return r;
1212
}
1213
 
1214
static rc_res_resource *
1215
bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
1216
{
1217
  rc_toolbar *ri;
1218
  rc_res_resource *r;
1219
  rc_uint_type i;
1220
 
1221
  ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
1222
  ri->button_width = windres_get_32 (wrbfd, data, 4);
1223
  ri->button_height = windres_get_32 (wrbfd, data + 4, 4);
1224
  ri->nitems = windres_get_32 (wrbfd, data + 8, 4);
1225
  ri->items = NULL;
1226
 
1227
  data += 12;
1228
  length -= 12;
1229
  for (i=0 ; i < ri->nitems; i++)
1230
  {
1231
    rc_toolbar_item *it;
1232
    it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item));
1233
    it->id.named = 0;
1234
    it->id.u.id = (int) windres_get_32 (wrbfd, data, 4);
1235
    it->prev = it->next = NULL;
1236
    data += 4;
1237
    length -= 4;
1238
    if(ri->items) {
1239
      rc_toolbar_item *ii = ri->items;
1240
      while (ii->next != NULL)
1241
        ii = ii->next;
1242
      it->prev = ii;
1243
      ii->next = it;
1244
    }
1245
    else
1246
      ri->items = it;
1247
  }
1248
  r = (rc_res_resource *) res_alloc (sizeof *r);
1249
  r->type = RES_TYPE_TOOLBAR;
1250
  r->u.toolbar = ri;
1251
  return r;
1252
}
1253
 
1254
 
1255
/* Local functions used to convert resources to binary format.  */
1256
 
1257
static rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id);
1258
static rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *);
1259
static rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *);
1260
static rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *);
1261
static rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *);
1262
static rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *);
1263
static rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *);
1264
static rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *);
1265
static rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *);
1266
static rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
1267
static rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *);
1268
static rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *);
1269
static rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *);
1270
static rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *);
1271
static rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb);
1272
static rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *);
1273
static rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type,
1274
                                        const bfd_byte *);
1275
 
1276
/* Convert a resource to binary.  */
1277
 
1278
rc_uint_type
1279
res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res)
1280
{
1281
  switch (res->type)
1282
    {
1283
    case RES_TYPE_BITMAP:
1284
    case RES_TYPE_FONT:
1285
    case RES_TYPE_ICON:
1286
    case RES_TYPE_MESSAGETABLE:
1287
      return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data);
1288
    case RES_TYPE_ACCELERATOR:
1289
      return res_to_bin_accelerator (wrbfd, off, res->u.acc);
1290
    case RES_TYPE_CURSOR:
1291
      return res_to_bin_cursor (wrbfd, off, res->u.cursor);
1292
    case RES_TYPE_GROUP_CURSOR:
1293
      return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor);
1294
    case RES_TYPE_DIALOG:
1295
      return res_to_bin_dialog (wrbfd, off, res->u.dialog);
1296
    case RES_TYPE_FONTDIR:
1297
      return res_to_bin_fontdir (wrbfd, off, res->u.fontdir);
1298
    case RES_TYPE_GROUP_ICON:
1299
      return res_to_bin_group_icon (wrbfd, off, res->u.group_icon);
1300
    case RES_TYPE_MENU:
1301
      return res_to_bin_menu (wrbfd, off, res->u.menu);
1302
    case RES_TYPE_STRINGTABLE:
1303
      return res_to_bin_stringtable (wrbfd, off, res->u.stringtable);
1304
    case RES_TYPE_VERSIONINFO:
1305
      return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo);
1306
    case RES_TYPE_TOOLBAR:
1307
      return res_to_bin_toolbar (wrbfd, off, res->u.toolbar);
1308
    case RES_TYPE_USERDATA:
1309
    case RES_TYPE_RCDATA:
1310
    default:
1311
      return res_to_bin_rcdata (wrbfd, off, res->u.rcdata);
1312
    }
1313
}
1314
 
1315
/* Convert a resource ID to binary.  This always returns exactly one
1316
   bindata structure.  */
1317
 
1318
static rc_uint_type
1319
resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id)
1320
{
1321
  if (! id.named)
1322
    {
1323
      if (wrbfd)
1324
        {
1325
          struct bin_res_id bri;
1326
 
1327
          windres_put_16 (wrbfd, bri.sig, 0xffff);
1328
          windres_put_16 (wrbfd, bri.id, id.u.id);
1329
          set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID);
1330
        }
1331
      off += BIN_RES_ID;
1332
    }
1333
  else
1334
    {
1335
      rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0);
1336
      if (wrbfd)
1337
        {
1338
          bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
1339
          rc_uint_type i;
1340
          for (i = 0; i < len; i++)
1341
            windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]);
1342
          windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
1343
          set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
1344
    }
1345
      off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1346
    }
1347
  return off;
1348
}
1349
 
1350
/* Convert a null terminated unicode string to binary.  This always
1351
   returns exactly one bindata structure.  */
1352
 
1353
static rc_uint_type
1354
unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str)
1355
{
1356
  rc_uint_type len = 0;
1357
 
1358
  if (str != NULL)
1359
    len = unichar_len (str);
1360
 
1361
  if (wrbfd)
1362
    {
1363
      bfd_byte *d;
1364
      rc_uint_type i;
1365
      d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar));
1366
      for (i = 0; i < len; i++)
1367
        windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]);
1368
      windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0);
1369
      set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar));
1370
    }
1371
  off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1372
 
1373
  return off;
1374
}
1375
 
1376
/* Convert an accelerator resource to binary.  */
1377
 
1378
static rc_uint_type
1379
res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off,
1380
                        const rc_accelerator *accelerators)
1381
{
1382
  const rc_accelerator *a;
1383
 
1384
  for (a = accelerators; a != NULL; a = a->next)
1385
    {
1386
      if (wrbfd)
1387
        {
1388
          struct bin_accelerator ba;
1389
 
1390
          windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST));
1391
          windres_put_16 (wrbfd, ba.key, a->key);
1392
          windres_put_16 (wrbfd, ba.id, a->id);
1393
          windres_put_16 (wrbfd, ba.pad, 0);
1394
          set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE);
1395
    }
1396
      off += BIN_ACCELERATOR_SIZE;
1397
    }
1398
  return off;
1399
}
1400
 
1401
/* Convert a cursor resource to binary.  */
1402
 
1403
static rc_uint_type
1404
res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c)
1405
{
1406
  if (wrbfd)
1407
    {
1408
      struct bin_cursor bc;
1409
 
1410
      windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot);
1411
      windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot);
1412
      set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE);
1413
      if (c->length)
1414
        set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length);
1415
    }
1416
  off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length);
1417
  return off;
1418
}
1419
 
1420
/* Convert a group cursor resource to binary.  */
1421
 
1422
static rc_uint_type
1423
res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off,
1424
                         const rc_group_cursor *group_cursors)
1425
{
1426
  int c = 0;
1427
  const rc_group_cursor *gc;
1428
  struct bin_group_cursor bgc;
1429
  struct bin_group_cursor_item bgci;
1430
  rc_uint_type start = off;
1431
 
1432
  off += BIN_GROUP_CURSOR_SIZE;
1433
 
1434
  for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++)
1435
    {
1436
      if (wrbfd)
1437
        {
1438
          windres_put_16 (wrbfd, bgci.width, gc->width);
1439
          windres_put_16 (wrbfd, bgci.height, gc->height);
1440
          windres_put_16 (wrbfd, bgci.planes, gc->planes);
1441
          windres_put_16 (wrbfd, bgci.bits, gc->bits);
1442
          windres_put_32 (wrbfd, bgci.bytes, gc->bytes);
1443
          windres_put_16 (wrbfd, bgci.index, gc->index);
1444
          set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE);
1445
    }
1446
 
1447
      off += BIN_GROUP_CURSOR_ITEM_SIZE;
1448
    }
1449
  if (wrbfd)
1450
    {
1451
      windres_put_16 (wrbfd, bgc.sig1, 0);
1452
      windres_put_16 (wrbfd, bgc.sig2, 2);
1453
      windres_put_16 (wrbfd, bgc.nitems, c);
1454
      set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE);
1455
    }
1456
  return off;
1457
}
1458
 
1459
/* Convert a dialog resource to binary.  */
1460
 
1461
static rc_uint_type
1462
res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog)
1463
{
1464
  rc_uint_type off_delta;
1465
  rc_uint_type start, marker;
1466
  int dialogex;
1467
  int c;
1468
  rc_dialog_control *dc;
1469
  struct bin_dialogex bdx;
1470
  struct bin_dialog bd;
1471
 
1472
  off_delta = off;
1473
  start = off;
1474
  dialogex = extended_dialog (dialog);
1475
 
1476
  if (wrbfd)
1477
    {
1478
  if (! dialogex)
1479
    {
1480
          windres_put_32 (wrbfd, bd.style, dialog->style);
1481
          windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle);
1482
          windres_put_16 (wrbfd, bd.x, dialog->x);
1483
          windres_put_16 (wrbfd, bd.y, dialog->y);
1484
          windres_put_16 (wrbfd, bd.width, dialog->width);
1485
          windres_put_16 (wrbfd, bd.height, dialog->height);
1486
    }
1487
  else
1488
    {
1489
          windres_put_16 (wrbfd, bdx.sig1, 1);
1490
          windres_put_16 (wrbfd, bdx.sig2, 0xffff);
1491
          windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0));
1492
          windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle);
1493
          windres_put_32 (wrbfd, bdx.style, dialog->style);
1494
          windres_put_16 (wrbfd, bdx.x, dialog->x);
1495
          windres_put_16 (wrbfd, bdx.y, dialog->y);
1496
          windres_put_16 (wrbfd, bdx.width, dialog->width);
1497
          windres_put_16 (wrbfd, bdx.height, dialog->height);
1498
        }
1499
    }
1500
 
1501
  off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE);
1502
 
1503
  off = resid_to_bin (wrbfd, off, dialog->menu);
1504
  off = resid_to_bin (wrbfd, off, dialog->class);
1505
  off = unicode_to_bin (wrbfd, off, dialog->caption);
1506
 
1507
  if ((dialog->style & DS_SETFONT) != 0)
1508
    {
1509
      if (wrbfd)
1510
        {
1511
          if (! dialogex)
1512
            {
1513
              struct bin_dialogfont bdf;
1514
              windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize);
1515
              set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE);
1516
            }
1517
          else
1518
            {
1519
              struct bin_dialogexfont bdxf;
1520
              windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize);
1521
              windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight));
1522
              windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic));
1523
              windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset));
1524
              set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE);
1525
            }
1526
        }
1527
      off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE);
1528
      off = unicode_to_bin (wrbfd, off, dialog->font);
1529
    }
1530
  for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++)
1531
    {
1532
      bfd_byte dc_rclen[2];
1533
 
1534
      off += (4 - ((off - off_delta) & 3)) & 3;
1535
      if (wrbfd)
1536
        {
1537
      if (! dialogex)
1538
        {
1539
              struct bin_dialog_control bdc;
1540
 
1541
              windres_put_32 (wrbfd, bdc.style, dc->style);
1542
              windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
1543
              windres_put_16 (wrbfd, bdc.x, dc->x);
1544
              windres_put_16 (wrbfd, bdc.y, dc->y);
1545
              windres_put_16 (wrbfd, bdc.width, dc->width);
1546
              windres_put_16 (wrbfd, bdc.height, dc->height);
1547
              windres_put_16 (wrbfd, bdc.id, dc->id);
1548
              set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE);
1549
        }
1550
      else
1551
        {
1552
              struct bin_dialogex_control bdc;
1553
 
1554
              windres_put_32 (wrbfd, bdc.help, dc->help);
1555
              windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
1556
              windres_put_32 (wrbfd, bdc.style, dc->style);
1557
              windres_put_16 (wrbfd, bdc.x, dc->x);
1558
              windres_put_16 (wrbfd, bdc.y, dc->y);
1559
              windres_put_16 (wrbfd, bdc.width, dc->width);
1560
              windres_put_16 (wrbfd, bdc.height, dc->height);
1561
              windres_put_32 (wrbfd, bdc.id, dc->id);
1562
              set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE);
1563
            }
1564
        }
1565
      off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE);
1566
 
1567
      off = resid_to_bin (wrbfd, off, dc->class);
1568
      off = resid_to_bin (wrbfd, off, dc->text);
1569
 
1570
      marker = off; /* Save two bytes for size of optional data.  */
1571
      off += 2;
1572
 
1573
      if (dc->data == NULL)
1574
        {
1575
          if (wrbfd)
1576
            windres_put_16 (wrbfd, dc_rclen, 0);
1577
        }
1578
      else
1579
        {
1580
          rc_uint_type saved_off = off;
1581
          rc_uint_type old_off;
1582
          off += (4 - ((off - off_delta) & 3)) & 3;
1583
 
1584
          old_off = off;
1585
          off = res_to_bin_rcdata (wrbfd, off, dc->data);
1586
          if ((off - old_off) == 0)
1587
            old_off = off = saved_off;
1588
          if (wrbfd)
1589
            windres_put_16 (wrbfd, dc_rclen, off - old_off);
1590
            }
1591
      if (wrbfd)
1592
        set_windres_bfd_content (wrbfd, dc_rclen, marker, 2);
1593
        }
1594
 
1595
  if (wrbfd)
1596
    {
1597
      windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c);
1598
      if (! dialogex)
1599
        set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE);
1600
      else
1601
        set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE);
1602
    }
1603
 
1604
  return off;
1605
}
1606
 
1607
/* Convert a fontdir resource to binary.  */
1608
static rc_uint_type
1609
res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs)
1610
{
1611
  rc_uint_type start;
1612
  int c;
1613
  const rc_fontdir *fd;
1614
 
1615
  start = off;
1616
  off += 2;
1617
 
1618
  for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++)
1619
    {
1620
      if (wrbfd)
1621
        {
1622
          bfd_byte d[2];
1623
          windres_put_16 (wrbfd, d, fd->index);
1624
          set_windres_bfd_content (wrbfd, d, off, 2);
1625
          if (fd->length)
1626
            set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length);
1627
        }
1628
      off += (rc_uint_type) fd->length + 2;
1629
    }
1630
 
1631
  if (wrbfd)
1632
    {
1633
      bfd_byte d[2];
1634
      windres_put_16 (wrbfd, d, c);
1635
      set_windres_bfd_content (wrbfd, d, start, 2);
1636
    }
1637
  return off;
1638
}
1639
 
1640
/* Convert a group icon resource to binary.  */
1641
 
1642
static rc_uint_type
1643
res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons)
1644
{
1645
  rc_uint_type start;
1646
  struct bin_group_icon bgi;
1647
  int c;
1648
  const rc_group_icon *gi;
1649
 
1650
  start = off;
1651
  off += BIN_GROUP_ICON_SIZE;
1652
 
1653
  for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++)
1654
    {
1655
      struct bin_group_icon_item bgii;
1656
 
1657
      if (wrbfd)
1658
        {
1659
          windres_put_8 (wrbfd, bgii.width, gi->width);
1660
          windres_put_8 (wrbfd, bgii.height, gi->height);
1661
          windres_put_8 (wrbfd, bgii.colors, gi->colors);
1662
          windres_put_8 (wrbfd, bgii.pad, 0);
1663
          windres_put_16 (wrbfd, bgii.planes, gi->planes);
1664
          windres_put_16 (wrbfd, bgii.bits, gi->bits);
1665
          windres_put_32 (wrbfd, bgii.bytes, gi->bytes);
1666
          windres_put_16 (wrbfd, bgii.index, gi->index);
1667
          set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE);
1668
        }
1669
      off += BIN_GROUP_ICON_ITEM_SIZE;
1670
    }
1671
 
1672
  if (wrbfd)
1673
    {
1674
      windres_put_16 (wrbfd, bgi.sig1, 0);
1675
      windres_put_16 (wrbfd, bgi.sig2, 1);
1676
      windres_put_16 (wrbfd, bgi.count, c);
1677
      set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE);
1678
    }
1679
  return off;
1680
}
1681
 
1682
/* Convert a menu resource to binary.  */
1683
 
1684
static rc_uint_type
1685
res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu)
1686
{
1687
  int menuex;
1688
 
1689
  menuex = extended_menu (menu);
1690
 
1691
  if (wrbfd)
1692
    {
1693
  if (! menuex)
1694
    {
1695
          struct bin_menu bm;
1696
          windres_put_16 (wrbfd, bm.sig1, 0);
1697
          windres_put_16 (wrbfd, bm.sig2, 0);
1698
          set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE);
1699
    }
1700
  else
1701
    {
1702
          struct bin_menuex bm;
1703
          windres_put_16 (wrbfd, bm.sig1, 1);
1704
          windres_put_16 (wrbfd, bm.sig2, 4);
1705
          windres_put_32 (wrbfd, bm.help, menu->help);
1706
          set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE);
1707
    }
1708
    }
1709
  off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE);
1710
  if (! menuex)
1711
    {
1712
      off = res_to_bin_menuitems (wrbfd, off, menu->items);
1713
    }
1714
  else
1715
    {
1716
      off = res_to_bin_menuexitems (wrbfd, off, menu->items);
1717
    }
1718
  return off;
1719
}
1720
 
1721
/* Convert menu items to binary.  */
1722
 
1723
static rc_uint_type
1724
res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
1725
{
1726
  const rc_menuitem *mi;
1727
 
1728
  for (mi = items; mi != NULL; mi = mi->next)
1729
    {
1730
      struct bin_menuitem bmi;
1731
      int flags;
1732
 
1733
      flags = mi->type;
1734
      if (mi->next == NULL)
1735
        flags |= MENUITEM_ENDMENU;
1736
      if (mi->popup != NULL)
1737
        flags |= MENUITEM_POPUP;
1738
 
1739
      if (wrbfd)
1740
        {
1741
          windres_put_16 (wrbfd, bmi.flags, flags);
1742
      if (mi->popup == NULL)
1743
            windres_put_16 (wrbfd, bmi.id, mi->id);
1744
          set_windres_bfd_content (wrbfd, &bmi, off,
1745
                                   mi->popup == NULL ? BIN_MENUITEM_SIZE
1746
                                                     : BIN_MENUITEM_POPUP_SIZE);
1747
        }
1748
      off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE);
1749
 
1750
      off = unicode_to_bin (wrbfd, off, mi->text);
1751
 
1752
      if (mi->popup != NULL)
1753
        {
1754
          off = res_to_bin_menuitems (wrbfd, off, mi->popup);
1755
        }
1756
    }
1757
  return off;
1758
}
1759
 
1760
/* Convert menuex items to binary.  */
1761
 
1762
static rc_uint_type
1763
res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
1764
{
1765
  rc_uint_type off_delta = off;
1766
  const rc_menuitem *mi;
1767
 
1768
  for (mi = items; mi != NULL; mi = mi->next)
1769
    {
1770
      struct bin_menuitemex bmi;
1771
      int flags;
1772
 
1773
      off += (4 - ((off - off_delta) & 3)) & 3;
1774
 
1775
      flags = 0;
1776
      if (mi->next == NULL)
1777
        flags |= 0x80;
1778
      if (mi->popup != NULL)
1779
        flags |= 1;
1780
 
1781
      if (wrbfd)
1782
        {
1783
          windres_put_32 (wrbfd, bmi.type, mi->type);
1784
          windres_put_32 (wrbfd, bmi.state, mi->state);
1785
          windres_put_32 (wrbfd, bmi.id, mi->id);
1786
          windres_put_16 (wrbfd, bmi.flags, flags);
1787
          set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE);
1788
        }
1789
      off += BIN_MENUITEMEX_SIZE;
1790
 
1791
      off = unicode_to_bin (wrbfd, off, mi->text);
1792
 
1793
      if (mi->popup != NULL)
1794
        {
1795
          bfd_byte help[4];
1796
 
1797
          off += (4 - ((off - off_delta) & 3)) & 3;
1798
 
1799
          if (wrbfd)
1800
            {
1801
              windres_put_32 (wrbfd, help, mi->help);
1802
              set_windres_bfd_content (wrbfd, help, off, 4);
1803
            }
1804
          off += 4;
1805
          off = res_to_bin_menuexitems (wrbfd, off, mi->popup);
1806
        }
1807
    }
1808
  return off;
1809
}
1810
 
1811
/* Convert an rcdata resource to binary.  This is also used to convert
1812
   other information which happens to be stored in rc_rcdata_item lists
1813
   to binary.  */
1814
 
1815
static rc_uint_type
1816
res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items)
1817
{
1818
  const rc_rcdata_item *ri;
1819
 
1820
  for (ri = items; ri != NULL; ri = ri->next)
1821
    {
1822
      rc_uint_type len;
1823
      switch (ri->type)
1824
        {
1825
        default:
1826
          abort ();
1827
        case RCDATA_WORD:
1828
          len = 2;
1829
          break;
1830
        case RCDATA_DWORD:
1831
          len = 4;
1832
          break;
1833
        case RCDATA_STRING:
1834
          len = ri->u.string.length;
1835
          break;
1836
        case RCDATA_WSTRING:
1837
          len = ri->u.wstring.length * sizeof (unichar);
1838
          break;
1839
        case RCDATA_BUFFER:
1840
          len = ri->u.buffer.length;
1841
          break;
1842
        }
1843
      if (wrbfd)
1844
        {
1845
          bfd_byte h[4];
1846
          bfd_byte *hp = &h[0];
1847
          switch (ri->type)
1848
            {
1849
            case RCDATA_WORD:
1850
              windres_put_16 (wrbfd, hp, ri->u.word);
1851
              break;
1852
            case RCDATA_DWORD:
1853
              windres_put_32 (wrbfd, hp, ri->u.dword);
1854
              break;
1855
            case RCDATA_STRING:
1856
              hp = (bfd_byte *) ri->u.string.s;
1857
          break;
1858
        case RCDATA_WSTRING:
1859
          {
1860
                rc_uint_type i;
1861
 
1862
                hp = (bfd_byte *) reswr_alloc (len);
1863
            for (i = 0; i < ri->u.wstring.length; i++)
1864
                  windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]);
1865
          }
1866
              break;
1867
        case RCDATA_BUFFER:
1868
              hp = (bfd_byte *) ri->u.buffer.data;
1869
          break;
1870
        }
1871
          set_windres_bfd_content (wrbfd, hp, off, len);
1872
    }
1873
      off += len;
1874
    }
1875
  return off;
1876
}
1877
 
1878
/* Convert a stringtable resource to binary.  */
1879
 
1880
static rc_uint_type
1881
res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off,
1882
                        const rc_stringtable *st)
1883
{
1884
  int i;
1885
 
1886
  for (i = 0; i < 16; i++)
1887
    {
1888
      rc_uint_type slen, length;
1889
      unichar *s;
1890
 
1891
      slen = (rc_uint_type) st->strings[i].length;
1892
      if (slen == 0xffffffff) slen = 0;
1893
      s = st->strings[i].string;
1894
 
1895
      length = 2 + slen * 2;
1896
      if (wrbfd)
1897
        {
1898
          bfd_byte *hp;
1899
          rc_uint_type j;
1900
 
1901
          hp = (bfd_byte *) reswr_alloc (length);
1902
          windres_put_16 (wrbfd, hp, slen);
1903
 
1904
      for (j = 0; j < slen; j++)
1905
            windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]);
1906
          set_windres_bfd_content (wrbfd, hp, off, length);
1907
    }
1908
      off += length;
1909
    }
1910
  return off;
1911
}
1912
 
1913
/* Convert an ASCII string to a unicode binary string.  This always
1914
   returns exactly one bindata structure.  */
1915
 
1916
static rc_uint_type
1917
string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s)
1918
{
1919
  rc_uint_type len;
1920
 
1921
  len = (rc_uint_type) strlen (s);
1922
 
1923
  if (wrbfd)
1924
    {
1925
      rc_uint_type i;
1926
      bfd_byte *hp;
1927
 
1928
      hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
1929
 
1930
      for (i = 0; i < len; i++)
1931
        windres_put_16 (wrbfd, hp + i * 2, s[i]);
1932
      windres_put_16 (wrbfd, hp + i * 2, 0);
1933
      set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar));
1934
    }
1935
  off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1936
  return off;
1937
}
1938
 
1939
static rc_uint_type
1940
res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb)
1941
{
1942
  if (wrbfd)
1943
    {
1944
      struct bin_toolbar bt;
1945
      windres_put_32 (wrbfd, bt.button_width, tb->button_width);
1946
      windres_put_32 (wrbfd, bt.button_height, tb->button_height);
1947
      windres_put_32 (wrbfd, bt.nitems, tb->nitems);
1948
      set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE);
1949
      if (tb->nitems > 0)
1950
        {
1951
          rc_toolbar_item *it;
1952
          bfd_byte *ids;
1953
          rc_uint_type i = 0;
1954
 
1955
          ids = (bfd_byte *) reswr_alloc (tb->nitems * 4);
1956
          it=tb->items;
1957
          while(it != NULL)
1958
            {
1959
              windres_put_32 (wrbfd, ids + i, it->id.u.id);
1960
              i += 4;
1961
              it = it->next;
1962
            }
1963
          set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i);
1964
        }
1965
    }
1966
  off += BIN_TOOLBAR_SIZE + tb->nitems * 4;
1967
 
1968
  return off;
1969
}
1970
 
1971
/* Convert a versioninfo resource to binary.  */
1972
 
1973
static rc_uint_type
1974
res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off,
1975
                        const rc_versioninfo *versioninfo)
1976
{
1977
  rc_uint_type off_delta = off;
1978
  rc_uint_type start;
1979
  struct bin_versioninfo bvi;
1980
  rc_ver_info *vi;
1981
 
1982
  start = off;
1983
  off += BIN_VERSIONINFO_SIZE;
1984
  off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO");
1985
  off += (4 - ((off - off_delta) & 3)) & 3;
1986
 
1987
  if (versioninfo->fixed != NULL)
1988
    {
1989
      if (wrbfd)
1990
        {
1991
          struct bin_fixed_versioninfo bfv;
1992
          const rc_fixed_versioninfo *fi;
1993
 
1994
      fi = versioninfo->fixed;
1995
          windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd);
1996
          windres_put_32 (wrbfd, bfv.sig2, 0x10000);
1997
          windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms);
1998
          windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls);
1999
          windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms);
2000
          windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls);
2001
          windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask);
2002
          windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags);
2003
          windres_put_32 (wrbfd, bfv.file_os, fi->file_os);
2004
          windres_put_32 (wrbfd, bfv.file_type, fi->file_type);
2005
          windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype);
2006
          windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms);
2007
          windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls);
2008
          set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE);
2009
        }
2010
      off += BIN_FIXED_VERSIONINFO_SIZE;
2011
    }
2012
 
2013
  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2014
    {
2015
      struct bin_ver_info bv;
2016
      rc_uint_type bv_off;
2017
 
2018
      off += (4 - ((off - off_delta) & 3)) & 3;
2019
 
2020
      bv_off = off;
2021
 
2022
      off += BIN_VER_INFO_SIZE;
2023
 
2024
      switch (vi->type)
2025
        {
2026
        default:
2027
          abort ();
2028
        case VERINFO_STRING:
2029
          {
2030 163 khays
            const rc_ver_stringtable *vst;
2031 15 khays
 
2032
            off = string_to_unicode_bin (wrbfd, off, "StringFileInfo");
2033
 
2034 163 khays
            if (!vi->u.string.stringtables)
2035
              off += (4 - ((off - off_delta) & 3)) & 3;
2036 15 khays
 
2037 163 khays
            for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next)
2038 15 khays
              {
2039 163 khays
                struct bin_ver_info bvst;
2040
                rc_uint_type vst_off;
2041
                const rc_ver_stringinfo *vs;
2042 15 khays
 
2043
                off += (4 - ((off - off_delta) & 3)) & 3;
2044
 
2045 163 khays
                vst_off = off;
2046 15 khays
                off += BIN_VER_INFO_SIZE;
2047
 
2048 163 khays
                off = unicode_to_bin (wrbfd, off, vst->language);
2049 15 khays
 
2050 163 khays
                for (vs = vst->strings; vs != NULL; vs = vs->next)
2051
                  {
2052
                    struct bin_ver_info bvs;
2053
                    rc_uint_type vs_off, str_off;
2054 15 khays
 
2055 163 khays
                    off += (4 - ((off - off_delta) & 3)) & 3;
2056
 
2057
                    vs_off = off;
2058
                    off += BIN_VER_INFO_SIZE;
2059
 
2060
                    off = unicode_to_bin (wrbfd, off, vs->key);
2061
 
2062
                    off += (4 - ((off - off_delta) & 3)) & 3;
2063
 
2064
                    str_off = off;
2065
                    off = unicode_to_bin (wrbfd, off, vs->value);
2066
 
2067
                    if (wrbfd)
2068
                      {
2069
                        windres_put_16 (wrbfd, bvs.size, off - vs_off);
2070
                        windres_put_16 (wrbfd, bvs.sig1, (off - str_off) / 2);
2071
                        windres_put_16 (wrbfd, bvs.sig2, 1);
2072
                        set_windres_bfd_content (wrbfd, &bvs, vs_off,
2073
                                                 BIN_VER_INFO_SIZE);
2074
                      }
2075
                  }
2076
 
2077 15 khays
                if (wrbfd)
2078
                  {
2079 163 khays
                    windres_put_16 (wrbfd, bvst.size, off - vst_off);
2080
                    windres_put_16 (wrbfd, bvst.sig1, 0);
2081
                    windres_put_16 (wrbfd, bvst.sig2, 1);
2082
                    set_windres_bfd_content (wrbfd, &bvst, vst_off,
2083
                                             BIN_VER_INFO_SIZE);
2084 15 khays
                  }
2085
              }
2086
            break;
2087
          }
2088
 
2089
        case VERINFO_VAR:
2090
          {
2091
            rc_uint_type vvd_off, vvvd_off;
2092
            struct bin_ver_info bvvd;
2093
            const rc_ver_varinfo *vv;
2094
 
2095
            off = string_to_unicode_bin (wrbfd, off, "VarFileInfo");
2096
 
2097
            off += (4 - ((off - off_delta) & 3)) & 3;
2098
 
2099
            vvd_off = off;
2100
            off += BIN_VER_INFO_SIZE;
2101
 
2102
            off = unicode_to_bin (wrbfd, off, vi->u.var.key);
2103
 
2104
            off += (4 - ((off - off_delta) & 3)) & 3;
2105
 
2106
            vvvd_off = off;
2107
 
2108
            for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2109
              {
2110
                if (wrbfd)
2111
                  {
2112
                    bfd_byte vvsd[4];
2113
 
2114
                    windres_put_16 (wrbfd, &vvsd[0], vv->language);
2115
                    windres_put_16 (wrbfd, &vvsd[2], vv->charset);
2116
                    set_windres_bfd_content (wrbfd, vvsd, off, 4);
2117
                  }
2118
                off += 4;
2119
              }
2120
            if (wrbfd)
2121
            {
2122
                windres_put_16 (wrbfd, bvvd.size, off - vvd_off);
2123
                windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off);
2124
                windres_put_16 (wrbfd, bvvd.sig2, 0);
2125
                set_windres_bfd_content (wrbfd, &bvvd, vvd_off,
2126
                                         BIN_VER_INFO_SIZE);
2127
            }
2128
 
2129
            break;
2130
          }
2131
        }
2132
 
2133
      if (wrbfd)
2134
        {
2135 163 khays
          windres_put_16 (wrbfd, bv.size, off - bv_off);
2136 15 khays
          windres_put_16 (wrbfd, bv.sig1, 0);
2137 163 khays
          windres_put_16 (wrbfd, bv.sig2, 1);
2138 15 khays
          set_windres_bfd_content (wrbfd, &bv, bv_off,
2139
                                   BIN_VER_INFO_SIZE);
2140
        }
2141
    }
2142
 
2143
  if (wrbfd)
2144
    {
2145
      windres_put_16 (wrbfd, bvi.size, off - start);
2146
      windres_put_16 (wrbfd, bvi.fixed_size,
2147
                      versioninfo->fixed == NULL ? 0
2148
                                                 : BIN_FIXED_VERSIONINFO_SIZE);
2149
      windres_put_16 (wrbfd, bvi.sig2, 0);
2150
      set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE);
2151
    }
2152
  return off;
2153
}
2154
 
2155
/* Convert a generic resource to binary.  */
2156
 
2157
static rc_uint_type
2158
res_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length,
2159
                    const bfd_byte *data)
2160
{
2161
  if (wrbfd && length != 0)
2162
    set_windres_bfd_content (wrbfd, data, off, length);
2163
  return off + (rc_uint_type) length;
2164
}

powered by: WebSVN 2.1.0

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