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