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