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