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