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