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