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