Coverage Report

Created: 2023-06-29 07:13

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