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