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