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