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