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