Coverage Report

Created: 2025-07-08 11:15

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