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