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 18

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

Line No. Rev Author Line
1 15 khays
/* resbin.c -- manipulate the Windows binary resource format.
2
   Copyright 1997, 1998, 1999, 2002, 2003, 2005, 2006, 2007, 2009, 2010
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, 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
          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
  const rc_accelerator *a;
1361
 
1362
  for (a = accelerators; a != NULL; a = a->next)
1363
    {
1364
      if (wrbfd)
1365
        {
1366
          struct bin_accelerator ba;
1367
 
1368
          windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST));
1369
          windres_put_16 (wrbfd, ba.key, a->key);
1370
          windres_put_16 (wrbfd, ba.id, a->id);
1371
          windres_put_16 (wrbfd, ba.pad, 0);
1372
          set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE);
1373
    }
1374
      off += BIN_ACCELERATOR_SIZE;
1375
    }
1376
  return off;
1377
}
1378
 
1379
/* Convert a cursor resource to binary.  */
1380
 
1381
static rc_uint_type
1382
res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c)
1383
{
1384
  if (wrbfd)
1385
    {
1386
      struct bin_cursor bc;
1387
 
1388
      windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot);
1389
      windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot);
1390
      set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE);
1391
      if (c->length)
1392
        set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length);
1393
    }
1394
  off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length);
1395
  return off;
1396
}
1397
 
1398
/* Convert a group cursor resource to binary.  */
1399
 
1400
static rc_uint_type
1401
res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off,
1402
                         const rc_group_cursor *group_cursors)
1403
{
1404
  int c = 0;
1405
  const rc_group_cursor *gc;
1406
  struct bin_group_cursor bgc;
1407
  struct bin_group_cursor_item bgci;
1408
  rc_uint_type start = off;
1409
 
1410
  off += BIN_GROUP_CURSOR_SIZE;
1411
 
1412
  for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++)
1413
    {
1414
      if (wrbfd)
1415
        {
1416
          windres_put_16 (wrbfd, bgci.width, gc->width);
1417
          windres_put_16 (wrbfd, bgci.height, gc->height);
1418
          windres_put_16 (wrbfd, bgci.planes, gc->planes);
1419
          windres_put_16 (wrbfd, bgci.bits, gc->bits);
1420
          windres_put_32 (wrbfd, bgci.bytes, gc->bytes);
1421
          windres_put_16 (wrbfd, bgci.index, gc->index);
1422
          set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE);
1423
    }
1424
 
1425
      off += BIN_GROUP_CURSOR_ITEM_SIZE;
1426
    }
1427
  if (wrbfd)
1428
    {
1429
      windres_put_16 (wrbfd, bgc.sig1, 0);
1430
      windres_put_16 (wrbfd, bgc.sig2, 2);
1431
      windres_put_16 (wrbfd, bgc.nitems, c);
1432
      set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE);
1433
    }
1434
  return off;
1435
}
1436
 
1437
/* Convert a dialog resource to binary.  */
1438
 
1439
static rc_uint_type
1440
res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog)
1441
{
1442
  rc_uint_type off_delta;
1443
  rc_uint_type start, marker;
1444
  int dialogex;
1445
  int c;
1446
  rc_dialog_control *dc;
1447
  struct bin_dialogex bdx;
1448
  struct bin_dialog bd;
1449
 
1450
  off_delta = off;
1451
  start = off;
1452
  dialogex = extended_dialog (dialog);
1453
 
1454
  if (wrbfd)
1455
    {
1456
  if (! dialogex)
1457
    {
1458
          windres_put_32 (wrbfd, bd.style, dialog->style);
1459
          windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle);
1460
          windres_put_16 (wrbfd, bd.x, dialog->x);
1461
          windres_put_16 (wrbfd, bd.y, dialog->y);
1462
          windres_put_16 (wrbfd, bd.width, dialog->width);
1463
          windres_put_16 (wrbfd, bd.height, dialog->height);
1464
    }
1465
  else
1466
    {
1467
          windres_put_16 (wrbfd, bdx.sig1, 1);
1468
          windres_put_16 (wrbfd, bdx.sig2, 0xffff);
1469
          windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0));
1470
          windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle);
1471
          windres_put_32 (wrbfd, bdx.style, dialog->style);
1472
          windres_put_16 (wrbfd, bdx.x, dialog->x);
1473
          windres_put_16 (wrbfd, bdx.y, dialog->y);
1474
          windres_put_16 (wrbfd, bdx.width, dialog->width);
1475
          windres_put_16 (wrbfd, bdx.height, dialog->height);
1476
        }
1477
    }
1478
 
1479
  off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE);
1480
 
1481
  off = resid_to_bin (wrbfd, off, dialog->menu);
1482
  off = resid_to_bin (wrbfd, off, dialog->class);
1483
  off = unicode_to_bin (wrbfd, off, dialog->caption);
1484
 
1485
  if ((dialog->style & DS_SETFONT) != 0)
1486
    {
1487
      if (wrbfd)
1488
        {
1489
          if (! dialogex)
1490
            {
1491
              struct bin_dialogfont bdf;
1492
              windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize);
1493
              set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE);
1494
            }
1495
          else
1496
            {
1497
              struct bin_dialogexfont bdxf;
1498
              windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize);
1499
              windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight));
1500
              windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic));
1501
              windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset));
1502
              set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE);
1503
            }
1504
        }
1505
      off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE);
1506
      off = unicode_to_bin (wrbfd, off, dialog->font);
1507
    }
1508
  for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++)
1509
    {
1510
      bfd_byte dc_rclen[2];
1511
 
1512
      off += (4 - ((off - off_delta) & 3)) & 3;
1513
      if (wrbfd)
1514
        {
1515
      if (! dialogex)
1516
        {
1517
              struct bin_dialog_control bdc;
1518
 
1519
              windres_put_32 (wrbfd, bdc.style, dc->style);
1520
              windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
1521
              windres_put_16 (wrbfd, bdc.x, dc->x);
1522
              windres_put_16 (wrbfd, bdc.y, dc->y);
1523
              windres_put_16 (wrbfd, bdc.width, dc->width);
1524
              windres_put_16 (wrbfd, bdc.height, dc->height);
1525
              windres_put_16 (wrbfd, bdc.id, dc->id);
1526
              set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE);
1527
        }
1528
      else
1529
        {
1530
              struct bin_dialogex_control bdc;
1531
 
1532
              windres_put_32 (wrbfd, bdc.help, dc->help);
1533
              windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle);
1534
              windres_put_32 (wrbfd, bdc.style, dc->style);
1535
              windres_put_16 (wrbfd, bdc.x, dc->x);
1536
              windres_put_16 (wrbfd, bdc.y, dc->y);
1537
              windres_put_16 (wrbfd, bdc.width, dc->width);
1538
              windres_put_16 (wrbfd, bdc.height, dc->height);
1539
              windres_put_32 (wrbfd, bdc.id, dc->id);
1540
              set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE);
1541
            }
1542
        }
1543
      off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE);
1544
 
1545
      off = resid_to_bin (wrbfd, off, dc->class);
1546
      off = resid_to_bin (wrbfd, off, dc->text);
1547
 
1548
      marker = off; /* Save two bytes for size of optional data.  */
1549
      off += 2;
1550
 
1551
      if (dc->data == NULL)
1552
        {
1553
          if (wrbfd)
1554
            windres_put_16 (wrbfd, dc_rclen, 0);
1555
        }
1556
      else
1557
        {
1558
          rc_uint_type saved_off = off;
1559
          rc_uint_type old_off;
1560
          off += (4 - ((off - off_delta) & 3)) & 3;
1561
 
1562
          old_off = off;
1563
          off = res_to_bin_rcdata (wrbfd, off, dc->data);
1564
          if ((off - old_off) == 0)
1565
            old_off = off = saved_off;
1566
          if (wrbfd)
1567
            windres_put_16 (wrbfd, dc_rclen, off - old_off);
1568
            }
1569
      if (wrbfd)
1570
        set_windres_bfd_content (wrbfd, dc_rclen, marker, 2);
1571
        }
1572
 
1573
  if (wrbfd)
1574
    {
1575
      windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c);
1576
      if (! dialogex)
1577
        set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE);
1578
      else
1579
        set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE);
1580
    }
1581
 
1582
  return off;
1583
}
1584
 
1585
/* Convert a fontdir resource to binary.  */
1586
static rc_uint_type
1587
res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs)
1588
{
1589
  rc_uint_type start;
1590
  int c;
1591
  const rc_fontdir *fd;
1592
 
1593
  start = off;
1594
  off += 2;
1595
 
1596
  for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++)
1597
    {
1598
      if (wrbfd)
1599
        {
1600
          bfd_byte d[2];
1601
          windres_put_16 (wrbfd, d, fd->index);
1602
          set_windres_bfd_content (wrbfd, d, off, 2);
1603
          if (fd->length)
1604
            set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length);
1605
        }
1606
      off += (rc_uint_type) fd->length + 2;
1607
    }
1608
 
1609
  if (wrbfd)
1610
    {
1611
      bfd_byte d[2];
1612
      windres_put_16 (wrbfd, d, c);
1613
      set_windres_bfd_content (wrbfd, d, start, 2);
1614
    }
1615
  return off;
1616
}
1617
 
1618
/* Convert a group icon resource to binary.  */
1619
 
1620
static rc_uint_type
1621
res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons)
1622
{
1623
  rc_uint_type start;
1624
  struct bin_group_icon bgi;
1625
  int c;
1626
  const rc_group_icon *gi;
1627
 
1628
  start = off;
1629
  off += BIN_GROUP_ICON_SIZE;
1630
 
1631
  for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++)
1632
    {
1633
      struct bin_group_icon_item bgii;
1634
 
1635
      if (wrbfd)
1636
        {
1637
          windres_put_8 (wrbfd, bgii.width, gi->width);
1638
          windres_put_8 (wrbfd, bgii.height, gi->height);
1639
          windres_put_8 (wrbfd, bgii.colors, gi->colors);
1640
          windres_put_8 (wrbfd, bgii.pad, 0);
1641
          windres_put_16 (wrbfd, bgii.planes, gi->planes);
1642
          windres_put_16 (wrbfd, bgii.bits, gi->bits);
1643
          windres_put_32 (wrbfd, bgii.bytes, gi->bytes);
1644
          windres_put_16 (wrbfd, bgii.index, gi->index);
1645
          set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE);
1646
        }
1647
      off += BIN_GROUP_ICON_ITEM_SIZE;
1648
    }
1649
 
1650
  if (wrbfd)
1651
    {
1652
      windres_put_16 (wrbfd, bgi.sig1, 0);
1653
      windres_put_16 (wrbfd, bgi.sig2, 1);
1654
      windres_put_16 (wrbfd, bgi.count, c);
1655
      set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE);
1656
    }
1657
  return off;
1658
}
1659
 
1660
/* Convert a menu resource to binary.  */
1661
 
1662
static rc_uint_type
1663
res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu)
1664
{
1665
  int menuex;
1666
 
1667
  menuex = extended_menu (menu);
1668
 
1669
  if (wrbfd)
1670
    {
1671
  if (! menuex)
1672
    {
1673
          struct bin_menu bm;
1674
          windres_put_16 (wrbfd, bm.sig1, 0);
1675
          windres_put_16 (wrbfd, bm.sig2, 0);
1676
          set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE);
1677
    }
1678
  else
1679
    {
1680
          struct bin_menuex bm;
1681
          windres_put_16 (wrbfd, bm.sig1, 1);
1682
          windres_put_16 (wrbfd, bm.sig2, 4);
1683
          windres_put_32 (wrbfd, bm.help, menu->help);
1684
          set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE);
1685
    }
1686
    }
1687
  off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE);
1688
  if (! menuex)
1689
    {
1690
      off = res_to_bin_menuitems (wrbfd, off, menu->items);
1691
    }
1692
  else
1693
    {
1694
      off = res_to_bin_menuexitems (wrbfd, off, menu->items);
1695
    }
1696
  return off;
1697
}
1698
 
1699
/* Convert menu items to binary.  */
1700
 
1701
static rc_uint_type
1702
res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
1703
{
1704
  const rc_menuitem *mi;
1705
 
1706
  for (mi = items; mi != NULL; mi = mi->next)
1707
    {
1708
      struct bin_menuitem bmi;
1709
      int flags;
1710
 
1711
      flags = mi->type;
1712
      if (mi->next == NULL)
1713
        flags |= MENUITEM_ENDMENU;
1714
      if (mi->popup != NULL)
1715
        flags |= MENUITEM_POPUP;
1716
 
1717
      if (wrbfd)
1718
        {
1719
          windres_put_16 (wrbfd, bmi.flags, flags);
1720
      if (mi->popup == NULL)
1721
            windres_put_16 (wrbfd, bmi.id, mi->id);
1722
          set_windres_bfd_content (wrbfd, &bmi, off,
1723
                                   mi->popup == NULL ? BIN_MENUITEM_SIZE
1724
                                                     : BIN_MENUITEM_POPUP_SIZE);
1725
        }
1726
      off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE);
1727
 
1728
      off = unicode_to_bin (wrbfd, off, mi->text);
1729
 
1730
      if (mi->popup != NULL)
1731
        {
1732
          off = res_to_bin_menuitems (wrbfd, off, mi->popup);
1733
        }
1734
    }
1735
  return off;
1736
}
1737
 
1738
/* Convert menuex items to binary.  */
1739
 
1740
static rc_uint_type
1741
res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items)
1742
{
1743
  rc_uint_type off_delta = off;
1744
  const rc_menuitem *mi;
1745
 
1746
  for (mi = items; mi != NULL; mi = mi->next)
1747
    {
1748
      struct bin_menuitemex bmi;
1749
      int flags;
1750
 
1751
      off += (4 - ((off - off_delta) & 3)) & 3;
1752
 
1753
      flags = 0;
1754
      if (mi->next == NULL)
1755
        flags |= 0x80;
1756
      if (mi->popup != NULL)
1757
        flags |= 1;
1758
 
1759
      if (wrbfd)
1760
        {
1761
          windres_put_32 (wrbfd, bmi.type, mi->type);
1762
          windres_put_32 (wrbfd, bmi.state, mi->state);
1763
          windres_put_32 (wrbfd, bmi.id, mi->id);
1764
          windres_put_16 (wrbfd, bmi.flags, flags);
1765
          set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE);
1766
        }
1767
      off += BIN_MENUITEMEX_SIZE;
1768
 
1769
      off = unicode_to_bin (wrbfd, off, mi->text);
1770
 
1771
      if (mi->popup != NULL)
1772
        {
1773
          bfd_byte help[4];
1774
 
1775
          off += (4 - ((off - off_delta) & 3)) & 3;
1776
 
1777
          if (wrbfd)
1778
            {
1779
              windres_put_32 (wrbfd, help, mi->help);
1780
              set_windres_bfd_content (wrbfd, help, off, 4);
1781
            }
1782
          off += 4;
1783
          off = res_to_bin_menuexitems (wrbfd, off, mi->popup);
1784
        }
1785
    }
1786
  return off;
1787
}
1788
 
1789
/* Convert an rcdata resource to binary.  This is also used to convert
1790
   other information which happens to be stored in rc_rcdata_item lists
1791
   to binary.  */
1792
 
1793
static rc_uint_type
1794
res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items)
1795
{
1796
  const rc_rcdata_item *ri;
1797
 
1798
  for (ri = items; ri != NULL; ri = ri->next)
1799
    {
1800
      rc_uint_type len;
1801
      switch (ri->type)
1802
        {
1803
        default:
1804
          abort ();
1805
        case RCDATA_WORD:
1806
          len = 2;
1807
          break;
1808
        case RCDATA_DWORD:
1809
          len = 4;
1810
          break;
1811
        case RCDATA_STRING:
1812
          len = ri->u.string.length;
1813
          break;
1814
        case RCDATA_WSTRING:
1815
          len = ri->u.wstring.length * sizeof (unichar);
1816
          break;
1817
        case RCDATA_BUFFER:
1818
          len = ri->u.buffer.length;
1819
          break;
1820
        }
1821
      if (wrbfd)
1822
        {
1823
          bfd_byte h[4];
1824
          bfd_byte *hp = &h[0];
1825
          switch (ri->type)
1826
            {
1827
            case RCDATA_WORD:
1828
              windres_put_16 (wrbfd, hp, ri->u.word);
1829
              break;
1830
            case RCDATA_DWORD:
1831
              windres_put_32 (wrbfd, hp, ri->u.dword);
1832
              break;
1833
            case RCDATA_STRING:
1834
              hp = (bfd_byte *) ri->u.string.s;
1835
          break;
1836
        case RCDATA_WSTRING:
1837
          {
1838
                rc_uint_type i;
1839
 
1840
                hp = (bfd_byte *) reswr_alloc (len);
1841
            for (i = 0; i < ri->u.wstring.length; i++)
1842
                  windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]);
1843
          }
1844
              break;
1845
        case RCDATA_BUFFER:
1846
              hp = (bfd_byte *) ri->u.buffer.data;
1847
          break;
1848
        }
1849
          set_windres_bfd_content (wrbfd, hp, off, len);
1850
    }
1851
      off += len;
1852
    }
1853
  return off;
1854
}
1855
 
1856
/* Convert a stringtable resource to binary.  */
1857
 
1858
static rc_uint_type
1859
res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off,
1860
                        const rc_stringtable *st)
1861
{
1862
  int i;
1863
 
1864
  for (i = 0; i < 16; i++)
1865
    {
1866
      rc_uint_type slen, length;
1867
      unichar *s;
1868
 
1869
      slen = (rc_uint_type) st->strings[i].length;
1870
      if (slen == 0xffffffff) slen = 0;
1871
      s = st->strings[i].string;
1872
 
1873
      length = 2 + slen * 2;
1874
      if (wrbfd)
1875
        {
1876
          bfd_byte *hp;
1877
          rc_uint_type j;
1878
 
1879
          hp = (bfd_byte *) reswr_alloc (length);
1880
          windres_put_16 (wrbfd, hp, slen);
1881
 
1882
      for (j = 0; j < slen; j++)
1883
            windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]);
1884
          set_windres_bfd_content (wrbfd, hp, off, length);
1885
    }
1886
      off += length;
1887
    }
1888
  return off;
1889
}
1890
 
1891
/* Convert an ASCII string to a unicode binary string.  This always
1892
   returns exactly one bindata structure.  */
1893
 
1894
static rc_uint_type
1895
string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s)
1896
{
1897
  rc_uint_type len;
1898
 
1899
  len = (rc_uint_type) strlen (s);
1900
 
1901
  if (wrbfd)
1902
    {
1903
      rc_uint_type i;
1904
      bfd_byte *hp;
1905
 
1906
      hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar));
1907
 
1908
      for (i = 0; i < len; i++)
1909
        windres_put_16 (wrbfd, hp + i * 2, s[i]);
1910
      windres_put_16 (wrbfd, hp + i * 2, 0);
1911
      set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar));
1912
    }
1913
  off += (rc_uint_type) ((len + 1) * sizeof (unichar));
1914
  return off;
1915
}
1916
 
1917
static rc_uint_type
1918
res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb)
1919
{
1920
  if (wrbfd)
1921
    {
1922
      struct bin_toolbar bt;
1923
      windres_put_32 (wrbfd, bt.button_width, tb->button_width);
1924
      windres_put_32 (wrbfd, bt.button_height, tb->button_height);
1925
      windres_put_32 (wrbfd, bt.nitems, tb->nitems);
1926
      set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE);
1927
      if (tb->nitems > 0)
1928
        {
1929
          rc_toolbar_item *it;
1930
          bfd_byte *ids;
1931
          rc_uint_type i = 0;
1932
 
1933
          ids = (bfd_byte *) reswr_alloc (tb->nitems * 4);
1934
          it=tb->items;
1935
          while(it != NULL)
1936
            {
1937
              windres_put_32 (wrbfd, ids + i, it->id.u.id);
1938
              i += 4;
1939
              it = it->next;
1940
            }
1941
          set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i);
1942
        }
1943
    }
1944
  off += BIN_TOOLBAR_SIZE + tb->nitems * 4;
1945
 
1946
  return off;
1947
}
1948
 
1949
/* Convert a versioninfo resource to binary.  */
1950
 
1951
static rc_uint_type
1952
res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off,
1953
                        const rc_versioninfo *versioninfo)
1954
{
1955
  rc_uint_type off_delta = off;
1956
  rc_uint_type start;
1957
  struct bin_versioninfo bvi;
1958
  rc_ver_info *vi;
1959
 
1960
  start = off;
1961
  off += BIN_VERSIONINFO_SIZE;
1962
  off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO");
1963
  off += (4 - ((off - off_delta) & 3)) & 3;
1964
 
1965
  if (versioninfo->fixed != NULL)
1966
    {
1967
      if (wrbfd)
1968
        {
1969
          struct bin_fixed_versioninfo bfv;
1970
          const rc_fixed_versioninfo *fi;
1971
 
1972
      fi = versioninfo->fixed;
1973
          windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd);
1974
          windres_put_32 (wrbfd, bfv.sig2, 0x10000);
1975
          windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms);
1976
          windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls);
1977
          windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms);
1978
          windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls);
1979
          windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask);
1980
          windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags);
1981
          windres_put_32 (wrbfd, bfv.file_os, fi->file_os);
1982
          windres_put_32 (wrbfd, bfv.file_type, fi->file_type);
1983
          windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype);
1984
          windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms);
1985
          windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls);
1986
          set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE);
1987
        }
1988
      off += BIN_FIXED_VERSIONINFO_SIZE;
1989
    }
1990
 
1991
  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
1992
    {
1993
      struct bin_ver_info bv;
1994
      rc_uint_type bv_off;
1995
 
1996
      off += (4 - ((off - off_delta) & 3)) & 3;
1997
 
1998
      bv_off = off;
1999
 
2000
      off += BIN_VER_INFO_SIZE;
2001
 
2002
      switch (vi->type)
2003
        {
2004
        default:
2005
          abort ();
2006
        case VERINFO_STRING:
2007
          {
2008
            struct bin_ver_info bvsd;
2009
            rc_uint_type vs_off;
2010
            const rc_ver_stringinfo *vs;
2011
 
2012
            off = string_to_unicode_bin (wrbfd, off, "StringFileInfo");
2013
            off += (4 - ((off - off_delta) & 3)) & 3;
2014
 
2015
            vs_off = off;
2016
 
2017
            off += BIN_VER_INFO_SIZE;
2018
 
2019
            off = unicode_to_bin (wrbfd, off, vi->u.string.language);
2020
 
2021
            for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2022
              {
2023
                struct bin_ver_info bvss;
2024
                rc_uint_type vss_off,str_off;
2025
 
2026
                off += (4 - ((off - off_delta) & 3)) & 3;
2027
 
2028
                vss_off = off;
2029
                off += BIN_VER_INFO_SIZE;
2030
 
2031
                off = unicode_to_bin (wrbfd, off, vs->key);
2032
 
2033
                off += (4 - ((off - off_delta) & 3)) & 3;
2034
 
2035
                str_off = off;
2036
                off = unicode_to_bin (wrbfd, off, vs->value);
2037
                if (wrbfd)
2038
                  {
2039
                    windres_put_16 (wrbfd, bvss.size, off - vss_off);
2040
                    windres_put_16 (wrbfd, bvss.sig1, (off - str_off) / 2);
2041
                    windres_put_16 (wrbfd, bvss.sig2, 1);
2042
                    set_windres_bfd_content (wrbfd, &bvss, vss_off,
2043
                                             BIN_VER_INFO_SIZE);
2044
                  }
2045
              }
2046
            if (wrbfd)
2047
              {
2048
                windres_put_16 (wrbfd, bvsd.size, off - vs_off);
2049
                windres_put_16 (wrbfd, bvsd.sig1, 0);
2050
                windres_put_16 (wrbfd, bvsd.sig2, 0);
2051
                set_windres_bfd_content (wrbfd, &bvsd, vs_off,
2052
                                         BIN_VER_INFO_SIZE);
2053
              }
2054
            break;
2055
          }
2056
 
2057
        case VERINFO_VAR:
2058
          {
2059
            rc_uint_type vvd_off, vvvd_off;
2060
            struct bin_ver_info bvvd;
2061
            const rc_ver_varinfo *vv;
2062
 
2063
            off = string_to_unicode_bin (wrbfd, off, "VarFileInfo");
2064
 
2065
            off += (4 - ((off - off_delta) & 3)) & 3;
2066
 
2067
            vvd_off = off;
2068
            off += BIN_VER_INFO_SIZE;
2069
 
2070
            off = unicode_to_bin (wrbfd, off, vi->u.var.key);
2071
 
2072
            off += (4 - ((off - off_delta) & 3)) & 3;
2073
 
2074
            vvvd_off = off;
2075
 
2076
            for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2077
              {
2078
                if (wrbfd)
2079
                  {
2080
                    bfd_byte vvsd[4];
2081
 
2082
                    windres_put_16 (wrbfd, &vvsd[0], vv->language);
2083
                    windres_put_16 (wrbfd, &vvsd[2], vv->charset);
2084
                    set_windres_bfd_content (wrbfd, vvsd, off, 4);
2085
                  }
2086
                off += 4;
2087
              }
2088
            if (wrbfd)
2089
            {
2090
                windres_put_16 (wrbfd, bvvd.size, off - vvd_off);
2091
                windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off);
2092
                windres_put_16 (wrbfd, bvvd.sig2, 0);
2093
                set_windres_bfd_content (wrbfd, &bvvd, vvd_off,
2094
                                         BIN_VER_INFO_SIZE);
2095
            }
2096
 
2097
            break;
2098
          }
2099
        }
2100
 
2101
      if (wrbfd)
2102
        {
2103
          windres_put_16 (wrbfd, bv.size, off-bv_off);
2104
          windres_put_16 (wrbfd, bv.sig1, 0);
2105
          windres_put_16 (wrbfd, bv.sig2, 0);
2106
          set_windres_bfd_content (wrbfd, &bv, bv_off,
2107
                                   BIN_VER_INFO_SIZE);
2108
        }
2109
    }
2110
 
2111
  if (wrbfd)
2112
    {
2113
      windres_put_16 (wrbfd, bvi.size, off - start);
2114
      windres_put_16 (wrbfd, bvi.fixed_size,
2115
                      versioninfo->fixed == NULL ? 0
2116
                                                 : BIN_FIXED_VERSIONINFO_SIZE);
2117
      windres_put_16 (wrbfd, bvi.sig2, 0);
2118
      set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE);
2119
    }
2120
  return off;
2121
}
2122
 
2123
/* Convert a generic resource to binary.  */
2124
 
2125
static rc_uint_type
2126
res_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length,
2127
                    const bfd_byte *data)
2128
{
2129
  if (wrbfd && length != 0)
2130
    set_windres_bfd_content (wrbfd, data, off, length);
2131
  return off + (rc_uint_type) length;
2132
}

powered by: WebSVN 2.1.0

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