1 /* resbin.c -- manipulate the Windows binary resource format. 2 Copyright (C) 1997-2022 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 36 static void toosmall (const char *); 37 38 static unichar *get_unicode (windres_bfd *, const bfd_byte *, rc_uint_type, rc_uint_type *); 39 static int get_resid (windres_bfd *, rc_res_id *, const bfd_byte *, rc_uint_type); 40 static rc_res_resource *bin_to_res_generic (windres_bfd *, enum rc_res_type, 41 const bfd_byte *, rc_uint_type); 42 static rc_res_resource *bin_to_res_cursor (windres_bfd *, const bfd_byte *, rc_uint_type); 43 static rc_res_resource *bin_to_res_menu (windres_bfd *,const bfd_byte *, rc_uint_type); 44 static rc_menuitem *bin_to_res_menuitems (windres_bfd *, const bfd_byte *, rc_uint_type, 45 rc_uint_type *); 46 static rc_menuitem *bin_to_res_menuexitems (windres_bfd *, const bfd_byte *, rc_uint_type, 47 rc_uint_type *); 48 static rc_res_resource *bin_to_res_dialog (windres_bfd *, const bfd_byte *, rc_uint_type); 49 static rc_res_resource *bin_to_res_string (windres_bfd *,const bfd_byte *, rc_uint_type); 50 static rc_res_resource *bin_to_res_fontdir (windres_bfd *, const bfd_byte *, rc_uint_type); 51 static rc_res_resource *bin_to_res_accelerators (windres_bfd *, const bfd_byte *, rc_uint_type); 52 static rc_res_resource *bin_to_res_rcdata (windres_bfd *, const bfd_byte *, rc_uint_type, int); 53 static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *, rc_uint_type); 54 static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type); 55 static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type); 56 static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type); 57 static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *); 58 static 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 67 rc_res_resource * 68 bin_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); 109 110 } 111 } 112 } 113 114 /* Give an error if the binary data is too small. */ 115 116 static void 117 toosmall (const char *msg) 118 { 119 fatal (_("%s: not enough binary data"), msg); 120 } 121 122 /* Swap in a NULL terminated unicode string. */ 123 124 static unichar * 125 get_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 155 static int 156 get_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 184 rc_res_resource * 185 bin_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 200 rc_res_resource * 201 bin_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 224 rc_res_resource * 225 bin_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 270 static rc_menuitem * 271 bin_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 347 static rc_menuitem * 348 bin_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 421 static rc_res_resource * 422 bin_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 if (length < off + datalen) 578 toosmall (_("dialog control data")); 579 580 dc->data = ((rc_rcdata_item *) 581 res_alloc (sizeof (rc_rcdata_item))); 582 dc->data->next = NULL; 583 dc->data->type = RCDATA_BUFFER; 584 dc->data->u.buffer.length = datalen; 585 dc->data->u.buffer.data = data + off; 586 587 off += datalen; 588 } 589 590 dc->next = NULL; 591 *pp = dc; 592 pp = &dc->next; 593 } 594 595 r = (rc_res_resource *) res_alloc (sizeof *r); 596 r->type = RES_TYPE_DIALOG; 597 r->u.dialog = d; 598 599 return r; 600 } 601 602 /* Convert a stringtable resource from binary. */ 603 604 static rc_res_resource * 605 bin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 606 { 607 rc_stringtable *st; 608 int i; 609 rc_res_resource *r; 610 611 st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable)); 612 613 for (i = 0; i < 16; i++) 614 { 615 unsigned int slen; 616 617 if (length < 2) 618 toosmall (_("stringtable string length")); 619 slen = windres_get_16 (wrbfd, data, 2); 620 st->strings[i].length = slen; 621 622 if (slen > 0) 623 { 624 unichar *s; 625 unsigned int j; 626 627 if (length < 2 + 2 * slen) 628 toosmall (_("stringtable string")); 629 630 s = (unichar *) res_alloc (slen * sizeof (unichar)); 631 st->strings[i].string = s; 632 633 for (j = 0; j < slen; j++) 634 s[j] = windres_get_16 (wrbfd, data + 2 + j * 2, 2); 635 } 636 637 data += 2 + 2 * slen; 638 length -= 2 + 2 * slen; 639 } 640 641 r = (rc_res_resource *) res_alloc (sizeof *r); 642 r->type = RES_TYPE_STRINGTABLE; 643 r->u.stringtable = st; 644 645 return r; 646 } 647 648 /* Convert a fontdir resource from binary. */ 649 650 static rc_res_resource * 651 bin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 652 { 653 rc_uint_type c, i; 654 rc_fontdir *first, **pp; 655 rc_res_resource *r; 656 657 if (length < 2) 658 toosmall (_("fontdir header")); 659 660 c = windres_get_16 (wrbfd, data, 2); 661 662 first = NULL; 663 pp = &first; 664 665 for (i = 0; i < c; i++) 666 { 667 const struct bin_fontdir_item *bfi; 668 rc_fontdir *fd; 669 unsigned int off; 670 671 if (length < 56) 672 toosmall (_("fontdir")); 673 674 bfi = (const struct bin_fontdir_item *) data; 675 fd = (rc_fontdir *) res_alloc (sizeof *fd); 676 fd->index = windres_get_16 (wrbfd, bfi->index, 2); 677 678 /* To work out the length of the fontdir data, we must get the 679 length of the device name and face name strings, even though 680 we don't store them in the rc_fontdir. The 681 documentation says that these are NULL terminated char 682 strings, not Unicode strings. */ 683 684 off = 56; 685 686 while (off < length && data[off] != '\0') 687 ++off; 688 if (off >= length) 689 toosmall (_("fontdir device name")); 690 ++off; 691 692 while (off < length && data[off] != '\0') 693 ++off; 694 if (off >= length) 695 toosmall (_("fontdir face name")); 696 ++off; 697 698 fd->length = off; 699 fd->data = data; 700 701 fd->next = NULL; 702 *pp = fd; 703 pp = &fd->next; 704 705 /* The documentation does not indicate that any rounding is 706 required. */ 707 708 data += off; 709 length -= off; 710 } 711 712 r = (rc_res_resource *) res_alloc (sizeof *r); 713 r->type = RES_TYPE_FONTDIR; 714 r->u.fontdir = first; 715 716 return r; 717 } 718 719 /* Convert an accelerators resource from binary. */ 720 721 static rc_res_resource * 722 bin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 723 { 724 rc_accelerator *first, **pp; 725 rc_res_resource *r; 726 727 first = NULL; 728 pp = &first; 729 730 while (1) 731 { 732 rc_accelerator *a; 733 734 if (length < 8) 735 toosmall (_("accelerator")); 736 737 a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator)); 738 739 a->flags = windres_get_16 (wrbfd, data, 2); 740 a->key = windres_get_16 (wrbfd, data + 2, 2); 741 a->id = windres_get_16 (wrbfd, data + 4, 2); 742 743 a->next = NULL; 744 *pp = a; 745 pp = &a->next; 746 747 if ((a->flags & ACC_LAST) != 0) 748 break; 749 750 data += 8; 751 length -= 8; 752 } 753 754 r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); 755 r->type = RES_TYPE_ACCELERATOR; 756 r->u.acc = first; 757 758 return r; 759 } 760 761 /* Convert an rcdata resource from binary. */ 762 763 static rc_res_resource * 764 bin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, 765 rc_uint_type length, int rctyp) 766 { 767 rc_rcdata_item *ri; 768 rc_res_resource *r; 769 770 ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); 771 772 ri->next = NULL; 773 ri->type = RCDATA_BUFFER; 774 ri->u.buffer.length = length; 775 ri->u.buffer.data = data; 776 777 r = (rc_res_resource *) res_alloc (sizeof *r); 778 r->type = rctyp; 779 r->u.rcdata = ri; 780 781 return r; 782 } 783 784 /* Convert a group cursor resource from binary. */ 785 786 static rc_res_resource * 787 bin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 788 { 789 int type, c, i; 790 rc_group_cursor *first, **pp; 791 rc_res_resource *r; 792 793 if (length < 6) 794 toosmall (_("group cursor header")); 795 796 type = windres_get_16 (wrbfd, data + 2, 2); 797 if (type != 2) 798 fatal (_("unexpected group cursor type %d"), type); 799 800 c = windres_get_16 (wrbfd, data + 4, 2); 801 802 data += 6; 803 length -= 6; 804 805 first = NULL; 806 pp = &first; 807 808 for (i = 0; i < c; i++) 809 { 810 rc_group_cursor *gc; 811 812 if (length < 14) 813 toosmall (_("group cursor")); 814 815 gc = (rc_group_cursor *) res_alloc (sizeof *gc); 816 817 gc->width = windres_get_16 (wrbfd, data, 2); 818 gc->height = windres_get_16 (wrbfd, data + 2, 2); 819 gc->planes = windres_get_16 (wrbfd, data + 4, 2); 820 gc->bits = windres_get_16 (wrbfd, data + 6, 2); 821 gc->bytes = windres_get_32 (wrbfd, data + 8, 4); 822 gc->index = windres_get_16 (wrbfd, data + 12, 2); 823 824 gc->next = NULL; 825 *pp = gc; 826 pp = &gc->next; 827 828 data += 14; 829 length -= 14; 830 } 831 832 r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); 833 r->type = RES_TYPE_GROUP_CURSOR; 834 r->u.group_cursor = first; 835 836 return r; 837 } 838 839 /* Convert a group icon resource from binary. */ 840 841 static rc_res_resource * 842 bin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 843 { 844 int type, c, i; 845 rc_group_icon *first, **pp; 846 rc_res_resource *r; 847 848 if (length < 6) 849 toosmall (_("group icon header")); 850 851 type = windres_get_16 (wrbfd, data + 2, 2); 852 if (type != 1) 853 fatal (_("unexpected group icon type %d"), type); 854 855 c = windres_get_16 (wrbfd, data + 4, 2); 856 857 data += 6; 858 length -= 6; 859 860 first = NULL; 861 pp = &first; 862 863 for (i = 0; i < c; i++) 864 { 865 rc_group_icon *gi; 866 867 if (length < 14) 868 toosmall (_("group icon")); 869 870 gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon)); 871 872 gi->width = windres_get_8 (wrbfd, data, 1); 873 gi->height = windres_get_8 (wrbfd, data + 1, 1); 874 gi->colors = windres_get_8 (wrbfd, data + 2, 1); 875 gi->planes = windres_get_16 (wrbfd, data + 4, 2); 876 gi->bits = windres_get_16 (wrbfd, data + 6, 2); 877 gi->bytes = windres_get_32 (wrbfd, data + 8, 4); 878 gi->index = windres_get_16 (wrbfd, data + 12, 2); 879 880 gi->next = NULL; 881 *pp = gi; 882 pp = &gi->next; 883 884 data += 14; 885 length -= 14; 886 } 887 888 r = (rc_res_resource *) res_alloc (sizeof *r); 889 r->type = RES_TYPE_GROUP_ICON; 890 r->u.group_icon = first; 891 892 return r; 893 } 894 895 /* Extract data from a version header. If KEY is not NULL, then the 896 key must be KEY; otherwise, the key is returned in *PKEY. This 897 sets *LEN to the total length, *VALLEN to the value length, *TYPE 898 to the type, and *OFF to the offset to the children. */ 899 900 static void 901 get_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, 902 const char *key, unichar **pkey, 903 rc_uint_type *len, rc_uint_type *vallen, rc_uint_type *type, 904 rc_uint_type *off) 905 { 906 if (length < 8) 907 toosmall (key); 908 909 *len = (windres_get_16 (wrbfd, data, 2) + 3) & ~3; 910 *vallen = windres_get_16 (wrbfd, data + 2, 2); 911 *type = windres_get_16 (wrbfd, data + 4, 2); 912 913 *off = 6; 914 915 length -= 6; 916 data += 6; 917 918 if (key == NULL) 919 { 920 rc_uint_type sublen; 921 922 *pkey = get_unicode (wrbfd, data, length, &sublen); 923 *off += (sublen + 1) * sizeof (unichar); 924 } 925 else 926 { 927 while (1) 928 { 929 if (length < 2) 930 toosmall (key); 931 if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key) 932 fatal (_("unexpected version string")); 933 934 *off += 2; 935 length -= 2; 936 data += 2; 937 938 if (*key == '\0') 939 break; 940 941 ++key; 942 } 943 } 944 945 *off = (*off + 3) &~ 3; 946 } 947 948 /* Convert a version resource from binary. */ 949 950 static rc_res_resource * 951 bin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 952 { 953 rc_uint_type verlen, vallen, type, off; 954 rc_fixed_versioninfo *fi; 955 rc_ver_info *first, **pp; 956 rc_versioninfo *v; 957 rc_res_resource *r; 958 959 get_version_header (wrbfd, data, length, "VS_VERSION_INFO", 960 (unichar **) NULL, &verlen, &vallen, &type, &off); 961 962 /* PR 17512: The verlen field does not include padding length. */ 963 if (verlen > length) 964 fatal (_("version length %lu greater than resource length %lu"), 965 (unsigned long) verlen, (unsigned long) length); 966 967 if (type != 0) 968 fatal (_("unexpected version type %d"), (int) type); 969 970 /* PR 27686: Ignore any padding bytes after the end of the version structure. */ 971 length = verlen; 972 973 data += off; 974 length -= off; 975 976 if (vallen == 0) 977 fi = NULL; 978 else 979 { 980 unsigned long signature, fiv; 981 982 if (vallen != 52) 983 fatal (_("unexpected fixed version information length %ld"), (long) vallen); 984 985 if (length < 52) 986 toosmall (_("fixed version info")); 987 988 signature = windres_get_32 (wrbfd, data, 4); 989 if (signature != 0xfeef04bd) 990 fatal (_("unexpected fixed version signature %lu"), signature); 991 992 fiv = windres_get_32 (wrbfd, data + 4, 4); 993 if (fiv != 0 && fiv != 0x10000) 994 fatal (_("unexpected fixed version info version %lu"), fiv); 995 996 fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo)); 997 998 fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4); 999 fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4); 1000 fi->product_version_ms = windres_get_32 (wrbfd, data + 16, 4); 1001 fi->product_version_ls = windres_get_32 (wrbfd, data + 20, 4); 1002 fi->file_flags_mask = windres_get_32 (wrbfd, data + 24, 4); 1003 fi->file_flags = windres_get_32 (wrbfd, data + 28, 4); 1004 fi->file_os = windres_get_32 (wrbfd, data + 32, 4); 1005 fi->file_type = windres_get_32 (wrbfd, data + 36, 4); 1006 fi->file_subtype = windres_get_32 (wrbfd, data + 40, 4); 1007 fi->file_date_ms = windres_get_32 (wrbfd, data + 44, 4); 1008 fi->file_date_ls = windres_get_32 (wrbfd, data + 48, 4); 1009 1010 data += 52; 1011 length -= 52; 1012 } 1013 1014 first = NULL; 1015 pp = &first; 1016 1017 while (length > 0) 1018 { 1019 rc_ver_info *vi; 1020 int ch; 1021 1022 if (length < 8) 1023 toosmall (_("version var info")); 1024 1025 vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info)); 1026 1027 ch = windres_get_16 (wrbfd, data + 6, 2); 1028 1029 if (ch == 'S') 1030 { 1031 rc_ver_stringtable **ppvst; 1032 1033 vi->type = VERINFO_STRING; 1034 1035 get_version_header (wrbfd, data, length, "StringFileInfo", 1036 (unichar **) NULL, &verlen, &vallen, &type, 1037 &off); 1038 1039 if (vallen != 0) 1040 fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen); 1041 1042 data += off; 1043 length -= off; 1044 1045 verlen -= off; 1046 1047 vi->u.string.stringtables = NULL; 1048 ppvst = &vi->u.string.stringtables; 1049 1050 while (verlen > 0) 1051 { 1052 rc_ver_stringtable *vst; 1053 rc_uint_type stverlen; 1054 rc_ver_stringinfo **ppvs; 1055 1056 if (length < 8) 1057 toosmall (_("version stringtable")); 1058 1059 vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable)); 1060 1061 get_version_header (wrbfd, data, length, (const char *) NULL, 1062 &vst->language, &stverlen, &vallen, &type, &off); 1063 1064 if (vallen != 0) 1065 fatal (_("unexpected version stringtable value length %ld"), (long) vallen); 1066 1067 data += off; 1068 length -= off; 1069 verlen -= off; 1070 1071 stverlen -= off; 1072 1073 vst->strings = NULL; 1074 ppvs = &vst->strings; 1075 1076 while (stverlen > 0) 1077 { 1078 rc_ver_stringinfo *vs; 1079 rc_uint_type sverlen, vslen, valoff; 1080 1081 if (length < 8) 1082 toosmall (_("version string")); 1083 1084 vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo)); 1085 1086 get_version_header (wrbfd, data, length, (const char *) NULL, 1087 &vs->key, &sverlen, &vallen, &type, &off); 1088 1089 data += off; 1090 length -= off; 1091 1092 vs->value = get_unicode (wrbfd, data, length, &vslen); 1093 valoff = vslen * 2 + 2; 1094 valoff = (valoff + 3) & ~3; 1095 1096 if (off + valoff != sverlen) 1097 fatal (_("unexpected version string length %ld != %ld + %ld"), 1098 (long) sverlen, (long) off, (long) valoff); 1099 1100 data += valoff; 1101 length -= valoff; 1102 1103 if (stverlen < sverlen) 1104 fatal (_("unexpected version string length %ld < %ld"), 1105 (long) verlen, (long) sverlen); 1106 stverlen -= sverlen; 1107 verlen -= sverlen; 1108 1109 vs->next = NULL; 1110 *ppvs = vs; 1111 ppvs = &vs->next; 1112 } 1113 1114 vst->next = NULL; 1115 *ppvst = vst; 1116 ppvst = &vst->next; 1117 } 1118 } 1119 else if (ch == 'V') 1120 { 1121 rc_ver_varinfo **ppvv; 1122 1123 vi->type = VERINFO_VAR; 1124 1125 get_version_header (wrbfd, data, length, "VarFileInfo", 1126 (unichar **) NULL, &verlen, &vallen, &type, 1127 &off); 1128 1129 if (vallen != 0) 1130 fatal (_("unexpected varfileinfo value length %ld"), (long) vallen); 1131 1132 data += off; 1133 length -= off; 1134 1135 get_version_header (wrbfd, data, length, (const char *) NULL, 1136 &vi->u.var.key, &verlen, &vallen, &type, &off); 1137 1138 data += off; 1139 length -= off; 1140 1141 vi->u.var.var = NULL; 1142 ppvv = &vi->u.var.var; 1143 1144 while (vallen > 0) 1145 { 1146 rc_ver_varinfo *vv; 1147 1148 if (length < 4) 1149 toosmall (_("version varfileinfo")); 1150 1151 vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo)); 1152 1153 vv->language = windres_get_16 (wrbfd, data, 2); 1154 vv->charset = windres_get_16 (wrbfd, data + 2, 2); 1155 1156 vv->next = NULL; 1157 *ppvv = vv; 1158 ppvv = &vv->next; 1159 1160 data += 4; 1161 length -= 4; 1162 1163 if (vallen < 4) 1164 fatal (_("unexpected version value length %ld"), (long) vallen); 1165 1166 vallen -= 4; 1167 } 1168 } 1169 else if (ch == 0) 1170 { 1171 if (length == 8) 1172 /* Padding - skip. */ 1173 break; 1174 fatal (_("nul bytes found in version string")); 1175 } 1176 else 1177 fatal (_("unexpected version string character: %x"), ch); 1178 1179 vi->next = NULL; 1180 *pp = vi; 1181 pp = &vi->next; 1182 } 1183 1184 v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo)); 1185 v->fixed = fi; 1186 v->var = first; 1187 1188 r = (rc_res_resource *) res_alloc (sizeof *r); 1189 r->type = RES_TYPE_VERSIONINFO; 1190 r->u.versioninfo = v; 1191 1192 return r; 1193 } 1194 1195 /* Convert an arbitrary user defined resource from binary. */ 1196 1197 static rc_res_resource * 1198 bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, 1199 rc_uint_type length) 1200 { 1201 rc_rcdata_item *ri; 1202 rc_res_resource *r; 1203 1204 ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); 1205 1206 ri->next = NULL; 1207 ri->type = RCDATA_BUFFER; 1208 ri->u.buffer.length = length; 1209 ri->u.buffer.data = data; 1210 1211 r = (rc_res_resource *) res_alloc (sizeof *r); 1212 r->type = RES_TYPE_USERDATA; 1213 r->u.rcdata = ri; 1214 1215 return r; 1216 } 1217 1218 static rc_res_resource * 1219 bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data) 1220 { 1221 rc_toolbar *ri; 1222 rc_res_resource *r; 1223 rc_uint_type i; 1224 1225 ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar)); 1226 ri->button_width = windres_get_32 (wrbfd, data, 4); 1227 ri->button_height = windres_get_32 (wrbfd, data + 4, 4); 1228 ri->nitems = windres_get_32 (wrbfd, data + 8, 4); 1229 ri->items = NULL; 1230 1231 data += 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 if(ri->items) { 1241 rc_toolbar_item *ii = ri->items; 1242 while (ii->next != NULL) 1243 ii = ii->next; 1244 it->prev = ii; 1245 ii->next = it; 1246 } 1247 else 1248 ri->items = it; 1249 } 1250 r = (rc_res_resource *) res_alloc (sizeof *r); 1251 r->type = RES_TYPE_TOOLBAR; 1252 r->u.toolbar = ri; 1253 return r; 1254 } 1255 1256 1257 /* Local functions used to convert resources to binary format. */ 1258 1259 static rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id); 1260 static rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *); 1261 static rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *); 1262 static rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *); 1263 static rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *); 1264 static rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *); 1265 static rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *); 1266 static rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *); 1267 static rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *); 1268 static rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *); 1269 static rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *); 1270 static rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *); 1271 static rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *); 1272 static rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *); 1273 static rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb); 1274 static rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *); 1275 static rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type, 1276 const bfd_byte *); 1277 1278 /* Convert a resource to binary. */ 1279 1280 rc_uint_type 1281 res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res) 1282 { 1283 switch (res->type) 1284 { 1285 case RES_TYPE_BITMAP: 1286 case RES_TYPE_FONT: 1287 case RES_TYPE_ICON: 1288 case RES_TYPE_MESSAGETABLE: 1289 return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data); 1290 case RES_TYPE_ACCELERATOR: 1291 return res_to_bin_accelerator (wrbfd, off, res->u.acc); 1292 case RES_TYPE_CURSOR: 1293 return res_to_bin_cursor (wrbfd, off, res->u.cursor); 1294 case RES_TYPE_GROUP_CURSOR: 1295 return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor); 1296 case RES_TYPE_DIALOG: 1297 return res_to_bin_dialog (wrbfd, off, res->u.dialog); 1298 case RES_TYPE_FONTDIR: 1299 return res_to_bin_fontdir (wrbfd, off, res->u.fontdir); 1300 case RES_TYPE_GROUP_ICON: 1301 return res_to_bin_group_icon (wrbfd, off, res->u.group_icon); 1302 case RES_TYPE_MENU: 1303 return res_to_bin_menu (wrbfd, off, res->u.menu); 1304 case RES_TYPE_STRINGTABLE: 1305 return res_to_bin_stringtable (wrbfd, off, res->u.stringtable); 1306 case RES_TYPE_VERSIONINFO: 1307 return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo); 1308 case RES_TYPE_TOOLBAR: 1309 return res_to_bin_toolbar (wrbfd, off, res->u.toolbar); 1310 case RES_TYPE_USERDATA: 1311 case RES_TYPE_RCDATA: 1312 default: 1313 return res_to_bin_rcdata (wrbfd, off, res->u.rcdata); 1314 } 1315 } 1316 1317 /* Convert a resource ID to binary. This always returns exactly one 1318 bindata structure. */ 1319 1320 static rc_uint_type 1321 resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id) 1322 { 1323 if (! id.named) 1324 { 1325 if (wrbfd) 1326 { 1327 struct bin_res_id bri; 1328 1329 windres_put_16 (wrbfd, bri.sig, 0xffff); 1330 windres_put_16 (wrbfd, bri.id, id.u.id); 1331 set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID); 1332 } 1333 off += BIN_RES_ID; 1334 } 1335 else 1336 { 1337 rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0); 1338 if (wrbfd) 1339 { 1340 bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); 1341 rc_uint_type i; 1342 for (i = 0; i < len; i++) 1343 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]); 1344 windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); 1345 set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); 1346 } 1347 off += (rc_uint_type) ((len + 1) * sizeof (unichar)); 1348 } 1349 return off; 1350 } 1351 1352 /* Convert a null terminated unicode string to binary. This always 1353 returns exactly one bindata structure. */ 1354 1355 static rc_uint_type 1356 unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str) 1357 { 1358 rc_uint_type len = 0; 1359 1360 if (str != NULL) 1361 len = unichar_len (str); 1362 1363 if (wrbfd) 1364 { 1365 bfd_byte *d; 1366 rc_uint_type i; 1367 d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar)); 1368 for (i = 0; i < len; i++) 1369 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]); 1370 windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); 1371 set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); 1372 } 1373 off += (rc_uint_type) ((len + 1) * sizeof (unichar)); 1374 1375 return off; 1376 } 1377 1378 /* Convert an accelerator resource to binary. */ 1379 1380 static rc_uint_type 1381 res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off, 1382 const rc_accelerator *accelerators) 1383 { 1384 const rc_accelerator *a; 1385 1386 for (a = accelerators; a != NULL; a = a->next) 1387 { 1388 if (wrbfd) 1389 { 1390 struct bin_accelerator ba; 1391 1392 windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST)); 1393 windres_put_16 (wrbfd, ba.key, a->key); 1394 windres_put_16 (wrbfd, ba.id, a->id); 1395 windres_put_16 (wrbfd, ba.pad, 0); 1396 set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE); 1397 } 1398 off += BIN_ACCELERATOR_SIZE; 1399 } 1400 return off; 1401 } 1402 1403 /* Convert a cursor resource to binary. */ 1404 1405 static rc_uint_type 1406 res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c) 1407 { 1408 if (wrbfd) 1409 { 1410 struct bin_cursor bc; 1411 1412 windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot); 1413 windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot); 1414 set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE); 1415 if (c->length) 1416 set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length); 1417 } 1418 off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length); 1419 return off; 1420 } 1421 1422 /* Convert a group cursor resource to binary. */ 1423 1424 static rc_uint_type 1425 res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off, 1426 const rc_group_cursor *group_cursors) 1427 { 1428 int c = 0; 1429 const rc_group_cursor *gc; 1430 struct bin_group_cursor bgc; 1431 struct bin_group_cursor_item bgci; 1432 rc_uint_type start = off; 1433 1434 off += BIN_GROUP_CURSOR_SIZE; 1435 1436 for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++) 1437 { 1438 if (wrbfd) 1439 { 1440 windres_put_16 (wrbfd, bgci.width, gc->width); 1441 windres_put_16 (wrbfd, bgci.height, gc->height); 1442 windres_put_16 (wrbfd, bgci.planes, gc->planes); 1443 windres_put_16 (wrbfd, bgci.bits, gc->bits); 1444 windres_put_32 (wrbfd, bgci.bytes, gc->bytes); 1445 windres_put_16 (wrbfd, bgci.index, gc->index); 1446 set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE); 1447 } 1448 1449 off += BIN_GROUP_CURSOR_ITEM_SIZE; 1450 } 1451 if (wrbfd) 1452 { 1453 windres_put_16 (wrbfd, bgc.sig1, 0); 1454 windres_put_16 (wrbfd, bgc.sig2, 2); 1455 windres_put_16 (wrbfd, bgc.nitems, c); 1456 set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE); 1457 } 1458 return off; 1459 } 1460 1461 /* Convert a dialog resource to binary. */ 1462 1463 static rc_uint_type 1464 res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog) 1465 { 1466 rc_uint_type off_delta; 1467 rc_uint_type start, marker; 1468 int dialogex; 1469 int c; 1470 rc_dialog_control *dc; 1471 struct bin_dialogex bdx; 1472 struct bin_dialog bd; 1473 1474 off_delta = off; 1475 start = off; 1476 dialogex = extended_dialog (dialog); 1477 1478 if (wrbfd) 1479 { 1480 if (! dialogex) 1481 { 1482 windres_put_32 (wrbfd, bd.style, dialog->style); 1483 windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle); 1484 windres_put_16 (wrbfd, bd.x, dialog->x); 1485 windres_put_16 (wrbfd, bd.y, dialog->y); 1486 windres_put_16 (wrbfd, bd.width, dialog->width); 1487 windres_put_16 (wrbfd, bd.height, dialog->height); 1488 } 1489 else 1490 { 1491 windres_put_16 (wrbfd, bdx.sig1, 1); 1492 windres_put_16 (wrbfd, bdx.sig2, 0xffff); 1493 windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0)); 1494 windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle); 1495 windres_put_32 (wrbfd, bdx.style, dialog->style); 1496 windres_put_16 (wrbfd, bdx.x, dialog->x); 1497 windres_put_16 (wrbfd, bdx.y, dialog->y); 1498 windres_put_16 (wrbfd, bdx.width, dialog->width); 1499 windres_put_16 (wrbfd, bdx.height, dialog->height); 1500 } 1501 } 1502 1503 off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE); 1504 1505 off = resid_to_bin (wrbfd, off, dialog->menu); 1506 off = resid_to_bin (wrbfd, off, dialog->class); 1507 off = unicode_to_bin (wrbfd, off, dialog->caption); 1508 1509 if ((dialog->style & DS_SETFONT) != 0) 1510 { 1511 if (wrbfd) 1512 { 1513 if (! dialogex) 1514 { 1515 struct bin_dialogfont bdf; 1516 windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize); 1517 set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE); 1518 } 1519 else 1520 { 1521 struct bin_dialogexfont bdxf; 1522 windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize); 1523 windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight)); 1524 windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic)); 1525 windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset)); 1526 set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE); 1527 } 1528 } 1529 off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE); 1530 off = unicode_to_bin (wrbfd, off, dialog->font); 1531 } 1532 for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++) 1533 { 1534 bfd_byte dc_rclen[2]; 1535 1536 off += (4 - ((off - off_delta) & 3)) & 3; 1537 if (wrbfd) 1538 { 1539 if (! dialogex) 1540 { 1541 struct bin_dialog_control bdc; 1542 1543 windres_put_32 (wrbfd, bdc.style, dc->style); 1544 windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle); 1545 windres_put_16 (wrbfd, bdc.x, dc->x); 1546 windres_put_16 (wrbfd, bdc.y, dc->y); 1547 windres_put_16 (wrbfd, bdc.width, dc->width); 1548 windres_put_16 (wrbfd, bdc.height, dc->height); 1549 windres_put_16 (wrbfd, bdc.id, dc->id); 1550 set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE); 1551 } 1552 else 1553 { 1554 struct bin_dialogex_control bdc; 1555 1556 windres_put_32 (wrbfd, bdc.help, dc->help); 1557 windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle); 1558 windres_put_32 (wrbfd, bdc.style, dc->style); 1559 windres_put_16 (wrbfd, bdc.x, dc->x); 1560 windres_put_16 (wrbfd, bdc.y, dc->y); 1561 windres_put_16 (wrbfd, bdc.width, dc->width); 1562 windres_put_16 (wrbfd, bdc.height, dc->height); 1563 windres_put_32 (wrbfd, bdc.id, dc->id); 1564 set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE); 1565 } 1566 } 1567 off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE); 1568 1569 off = resid_to_bin (wrbfd, off, dc->class); 1570 off = resid_to_bin (wrbfd, off, dc->text); 1571 1572 marker = off; /* Save two bytes for size of optional data. */ 1573 off += 2; 1574 1575 if (dc->data == NULL) 1576 { 1577 if (wrbfd) 1578 windres_put_16 (wrbfd, dc_rclen, 0); 1579 } 1580 else 1581 { 1582 rc_uint_type saved_off = off; 1583 rc_uint_type old_off; 1584 1585 old_off = off; 1586 off = res_to_bin_rcdata (wrbfd, off, dc->data); 1587 if ((off - old_off) == 0) 1588 old_off = off = saved_off; 1589 if (wrbfd) 1590 windres_put_16 (wrbfd, dc_rclen, off - old_off); 1591 } 1592 if (wrbfd) 1593 set_windres_bfd_content (wrbfd, dc_rclen, marker, 2); 1594 } 1595 1596 if (wrbfd) 1597 { 1598 windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c); 1599 if (! dialogex) 1600 set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE); 1601 else 1602 set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE); 1603 } 1604 1605 return off; 1606 } 1607 1608 /* Convert a fontdir resource to binary. */ 1609 static rc_uint_type 1610 res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs) 1611 { 1612 rc_uint_type start; 1613 int c; 1614 const rc_fontdir *fd; 1615 1616 start = off; 1617 off += 2; 1618 1619 for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++) 1620 { 1621 if (wrbfd) 1622 { 1623 bfd_byte d[2]; 1624 windres_put_16 (wrbfd, d, fd->index); 1625 set_windres_bfd_content (wrbfd, d, off, 2); 1626 if (fd->length) 1627 set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length); 1628 } 1629 off += (rc_uint_type) fd->length + 2; 1630 } 1631 1632 if (wrbfd) 1633 { 1634 bfd_byte d[2]; 1635 windres_put_16 (wrbfd, d, c); 1636 set_windres_bfd_content (wrbfd, d, start, 2); 1637 } 1638 return off; 1639 } 1640 1641 /* Convert a group icon resource to binary. */ 1642 1643 static rc_uint_type 1644 res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons) 1645 { 1646 rc_uint_type start; 1647 struct bin_group_icon bgi; 1648 int c; 1649 const rc_group_icon *gi; 1650 1651 start = off; 1652 off += BIN_GROUP_ICON_SIZE; 1653 1654 for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++) 1655 { 1656 struct bin_group_icon_item bgii; 1657 1658 if (wrbfd) 1659 { 1660 windres_put_8 (wrbfd, bgii.width, gi->width); 1661 windres_put_8 (wrbfd, bgii.height, gi->height); 1662 windres_put_8 (wrbfd, bgii.colors, gi->colors); 1663 windres_put_8 (wrbfd, bgii.pad, 0); 1664 windres_put_16 (wrbfd, bgii.planes, gi->planes); 1665 windres_put_16 (wrbfd, bgii.bits, gi->bits); 1666 windres_put_32 (wrbfd, bgii.bytes, gi->bytes); 1667 windres_put_16 (wrbfd, bgii.index, gi->index); 1668 set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE); 1669 } 1670 off += BIN_GROUP_ICON_ITEM_SIZE; 1671 } 1672 1673 if (wrbfd) 1674 { 1675 windres_put_16 (wrbfd, bgi.sig1, 0); 1676 windres_put_16 (wrbfd, bgi.sig2, 1); 1677 windres_put_16 (wrbfd, bgi.count, c); 1678 set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE); 1679 } 1680 return off; 1681 } 1682 1683 /* Convert a menu resource to binary. */ 1684 1685 static rc_uint_type 1686 res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu) 1687 { 1688 int menuex; 1689 1690 menuex = extended_menu (menu); 1691 1692 if (wrbfd) 1693 { 1694 if (! menuex) 1695 { 1696 struct bin_menu bm; 1697 windres_put_16 (wrbfd, bm.sig1, 0); 1698 windres_put_16 (wrbfd, bm.sig2, 0); 1699 set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE); 1700 } 1701 else 1702 { 1703 struct bin_menuex bm; 1704 windres_put_16 (wrbfd, bm.sig1, 1); 1705 windres_put_16 (wrbfd, bm.sig2, 4); 1706 windres_put_32 (wrbfd, bm.help, menu->help); 1707 set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE); 1708 } 1709 } 1710 off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE); 1711 if (! menuex) 1712 { 1713 off = res_to_bin_menuitems (wrbfd, off, menu->items); 1714 } 1715 else 1716 { 1717 off = res_to_bin_menuexitems (wrbfd, off, menu->items); 1718 } 1719 return off; 1720 } 1721 1722 /* Convert menu items to binary. */ 1723 1724 static rc_uint_type 1725 res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) 1726 { 1727 const rc_menuitem *mi; 1728 1729 for (mi = items; mi != NULL; mi = mi->next) 1730 { 1731 struct bin_menuitem bmi; 1732 int flags; 1733 1734 flags = mi->type; 1735 if (mi->next == NULL) 1736 flags |= MENUITEM_ENDMENU; 1737 if (mi->popup != NULL) 1738 flags |= MENUITEM_POPUP; 1739 1740 if (wrbfd) 1741 { 1742 windres_put_16 (wrbfd, bmi.flags, flags); 1743 if (mi->popup == NULL) 1744 windres_put_16 (wrbfd, bmi.id, mi->id); 1745 set_windres_bfd_content (wrbfd, &bmi, off, 1746 mi->popup == NULL ? BIN_MENUITEM_SIZE 1747 : BIN_MENUITEM_POPUP_SIZE); 1748 } 1749 off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE); 1750 1751 off = unicode_to_bin (wrbfd, off, mi->text); 1752 1753 if (mi->popup != NULL) 1754 { 1755 off = res_to_bin_menuitems (wrbfd, off, mi->popup); 1756 } 1757 } 1758 return off; 1759 } 1760 1761 /* Convert menuex items to binary. */ 1762 1763 static rc_uint_type 1764 res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) 1765 { 1766 rc_uint_type off_delta = off; 1767 const rc_menuitem *mi; 1768 1769 for (mi = items; mi != NULL; mi = mi->next) 1770 { 1771 struct bin_menuitemex bmi; 1772 int flags; 1773 1774 off += (4 - ((off - off_delta) & 3)) & 3; 1775 1776 flags = 0; 1777 if (mi->next == NULL) 1778 flags |= 0x80; 1779 if (mi->popup != NULL) 1780 flags |= 1; 1781 1782 if (wrbfd) 1783 { 1784 windres_put_32 (wrbfd, bmi.type, mi->type); 1785 windres_put_32 (wrbfd, bmi.state, mi->state); 1786 windres_put_32 (wrbfd, bmi.id, mi->id); 1787 windres_put_16 (wrbfd, bmi.flags, flags); 1788 set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE); 1789 } 1790 off += BIN_MENUITEMEX_SIZE; 1791 1792 off = unicode_to_bin (wrbfd, off, mi->text); 1793 1794 if (mi->popup != NULL) 1795 { 1796 bfd_byte help[4]; 1797 1798 off += (4 - ((off - off_delta) & 3)) & 3; 1799 1800 if (wrbfd) 1801 { 1802 windres_put_32 (wrbfd, help, mi->help); 1803 set_windres_bfd_content (wrbfd, help, off, 4); 1804 } 1805 off += 4; 1806 off = res_to_bin_menuexitems (wrbfd, off, mi->popup); 1807 } 1808 } 1809 return off; 1810 } 1811 1812 /* Convert an rcdata resource to binary. This is also used to convert 1813 other information which happens to be stored in rc_rcdata_item lists 1814 to binary. */ 1815 1816 static rc_uint_type 1817 res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items) 1818 { 1819 const rc_rcdata_item *ri; 1820 1821 for (ri = items; ri != NULL; ri = ri->next) 1822 { 1823 rc_uint_type len; 1824 switch (ri->type) 1825 { 1826 default: 1827 abort (); 1828 case RCDATA_WORD: 1829 len = 2; 1830 break; 1831 case RCDATA_DWORD: 1832 len = 4; 1833 break; 1834 case RCDATA_STRING: 1835 len = ri->u.string.length; 1836 break; 1837 case RCDATA_WSTRING: 1838 len = ri->u.wstring.length * sizeof (unichar); 1839 break; 1840 case RCDATA_BUFFER: 1841 len = ri->u.buffer.length; 1842 break; 1843 } 1844 if (wrbfd) 1845 { 1846 bfd_byte h[4]; 1847 bfd_byte *hp = &h[0]; 1848 switch (ri->type) 1849 { 1850 case RCDATA_WORD: 1851 windres_put_16 (wrbfd, hp, ri->u.word); 1852 break; 1853 case RCDATA_DWORD: 1854 windres_put_32 (wrbfd, hp, ri->u.dword); 1855 break; 1856 case RCDATA_STRING: 1857 hp = (bfd_byte *) ri->u.string.s; 1858 break; 1859 case RCDATA_WSTRING: 1860 { 1861 rc_uint_type i; 1862 1863 hp = (bfd_byte *) reswr_alloc (len); 1864 for (i = 0; i < ri->u.wstring.length; i++) 1865 windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]); 1866 } 1867 break; 1868 case RCDATA_BUFFER: 1869 hp = (bfd_byte *) ri->u.buffer.data; 1870 break; 1871 } 1872 set_windres_bfd_content (wrbfd, hp, off, len); 1873 } 1874 off += len; 1875 } 1876 return off; 1877 } 1878 1879 /* Convert a stringtable resource to binary. */ 1880 1881 static rc_uint_type 1882 res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off, 1883 const rc_stringtable *st) 1884 { 1885 int i; 1886 1887 for (i = 0; i < 16; i++) 1888 { 1889 rc_uint_type slen, length; 1890 unichar *s; 1891 1892 slen = (rc_uint_type) st->strings[i].length; 1893 if (slen == 0xffffffff) slen = 0; 1894 s = st->strings[i].string; 1895 1896 length = 2 + slen * 2; 1897 if (wrbfd) 1898 { 1899 bfd_byte *hp; 1900 rc_uint_type j; 1901 1902 hp = (bfd_byte *) reswr_alloc (length); 1903 windres_put_16 (wrbfd, hp, slen); 1904 1905 for (j = 0; j < slen; j++) 1906 windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]); 1907 set_windres_bfd_content (wrbfd, hp, off, length); 1908 } 1909 off += length; 1910 } 1911 return off; 1912 } 1913 1914 /* Convert an ASCII string to a unicode binary string. This always 1915 returns exactly one bindata structure. */ 1916 1917 static rc_uint_type 1918 string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s) 1919 { 1920 rc_uint_type len; 1921 1922 len = (rc_uint_type) strlen (s); 1923 1924 if (wrbfd) 1925 { 1926 rc_uint_type i; 1927 bfd_byte *hp; 1928 1929 hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); 1930 1931 for (i = 0; i < len; i++) 1932 windres_put_16 (wrbfd, hp + i * 2, s[i]); 1933 windres_put_16 (wrbfd, hp + i * 2, 0); 1934 set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar)); 1935 } 1936 off += (rc_uint_type) ((len + 1) * sizeof (unichar)); 1937 return off; 1938 } 1939 1940 static rc_uint_type 1941 res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb) 1942 { 1943 if (wrbfd) 1944 { 1945 struct bin_toolbar bt; 1946 windres_put_32 (wrbfd, bt.button_width, tb->button_width); 1947 windres_put_32 (wrbfd, bt.button_height, tb->button_height); 1948 windres_put_32 (wrbfd, bt.nitems, tb->nitems); 1949 set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE); 1950 if (tb->nitems > 0) 1951 { 1952 rc_toolbar_item *it; 1953 bfd_byte *ids; 1954 rc_uint_type i = 0; 1955 1956 ids = (bfd_byte *) reswr_alloc (tb->nitems * 4); 1957 it=tb->items; 1958 while(it != NULL) 1959 { 1960 windres_put_32 (wrbfd, ids + i, it->id.u.id); 1961 i += 4; 1962 it = it->next; 1963 } 1964 set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i); 1965 } 1966 } 1967 off += BIN_TOOLBAR_SIZE + tb->nitems * 4; 1968 1969 return off; 1970 } 1971 1972 /* Convert a versioninfo resource to binary. */ 1973 1974 static rc_uint_type 1975 res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, 1976 const rc_versioninfo *versioninfo) 1977 { 1978 rc_uint_type off_delta = off; 1979 rc_uint_type start; 1980 struct bin_versioninfo bvi; 1981 rc_ver_info *vi; 1982 1983 start = off; 1984 off += BIN_VERSIONINFO_SIZE; 1985 off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO"); 1986 off += (4 - ((off - off_delta) & 3)) & 3; 1987 1988 if (versioninfo->fixed != NULL) 1989 { 1990 if (wrbfd) 1991 { 1992 struct bin_fixed_versioninfo bfv; 1993 const rc_fixed_versioninfo *fi; 1994 1995 fi = versioninfo->fixed; 1996 windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd); 1997 windres_put_32 (wrbfd, bfv.sig2, 0x10000); 1998 windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms); 1999 windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls); 2000 windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms); 2001 windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls); 2002 windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask); 2003 windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags); 2004 windres_put_32 (wrbfd, bfv.file_os, fi->file_os); 2005 windres_put_32 (wrbfd, bfv.file_type, fi->file_type); 2006 windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype); 2007 windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms); 2008 windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls); 2009 set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE); 2010 } 2011 off += BIN_FIXED_VERSIONINFO_SIZE; 2012 } 2013 2014 for (vi = versioninfo->var; vi != NULL; vi = vi->next) 2015 { 2016 struct bin_ver_info bv; 2017 rc_uint_type bv_off; 2018 2019 off += (4 - ((off - off_delta) & 3)) & 3; 2020 2021 bv_off = off; 2022 2023 off += BIN_VER_INFO_SIZE; 2024 2025 switch (vi->type) 2026 { 2027 default: 2028 abort (); 2029 case VERINFO_STRING: 2030 { 2031 const rc_ver_stringtable *vst; 2032 2033 off = string_to_unicode_bin (wrbfd, off, "StringFileInfo"); 2034 2035 if (!vi->u.string.stringtables) 2036 off += (4 - ((off - off_delta) & 3)) & 3; 2037 2038 for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next) 2039 { 2040 struct bin_ver_info bvst; 2041 rc_uint_type vst_off; 2042 const rc_ver_stringinfo *vs; 2043 2044 off += (4 - ((off - off_delta) & 3)) & 3; 2045 2046 vst_off = off; 2047 off += BIN_VER_INFO_SIZE; 2048 2049 off = unicode_to_bin (wrbfd, off, vst->language); 2050 2051 for (vs = vst->strings; vs != NULL; vs = vs->next) 2052 { 2053 struct bin_ver_info bvs; 2054 rc_uint_type vs_off, str_off; 2055 2056 off += (4 - ((off - off_delta) & 3)) & 3; 2057 2058 vs_off = off; 2059 off += BIN_VER_INFO_SIZE; 2060 2061 off = unicode_to_bin (wrbfd, off, vs->key); 2062 2063 off += (4 - ((off - off_delta) & 3)) & 3; 2064 2065 str_off = off; 2066 off = unicode_to_bin (wrbfd, off, vs->value); 2067 2068 if (wrbfd) 2069 { 2070 windres_put_16 (wrbfd, bvs.size, off - vs_off); 2071 windres_put_16 (wrbfd, bvs.sig1, (off - str_off) / 2); 2072 windres_put_16 (wrbfd, bvs.sig2, 1); 2073 set_windres_bfd_content (wrbfd, &bvs, vs_off, 2074 BIN_VER_INFO_SIZE); 2075 } 2076 } 2077 2078 if (wrbfd) 2079 { 2080 windres_put_16 (wrbfd, bvst.size, off - vst_off); 2081 windres_put_16 (wrbfd, bvst.sig1, 0); 2082 windres_put_16 (wrbfd, bvst.sig2, 1); 2083 set_windres_bfd_content (wrbfd, &bvst, vst_off, 2084 BIN_VER_INFO_SIZE); 2085 } 2086 } 2087 break; 2088 } 2089 2090 case VERINFO_VAR: 2091 { 2092 rc_uint_type vvd_off, vvvd_off; 2093 struct bin_ver_info bvvd; 2094 const rc_ver_varinfo *vv; 2095 2096 off = string_to_unicode_bin (wrbfd, off, "VarFileInfo"); 2097 2098 off += (4 - ((off - off_delta) & 3)) & 3; 2099 2100 vvd_off = off; 2101 off += BIN_VER_INFO_SIZE; 2102 2103 off = unicode_to_bin (wrbfd, off, vi->u.var.key); 2104 2105 off += (4 - ((off - off_delta) & 3)) & 3; 2106 2107 vvvd_off = off; 2108 2109 for (vv = vi->u.var.var; vv != NULL; vv = vv->next) 2110 { 2111 if (wrbfd) 2112 { 2113 bfd_byte vvsd[4]; 2114 2115 windres_put_16 (wrbfd, &vvsd[0], vv->language); 2116 windres_put_16 (wrbfd, &vvsd[2], vv->charset); 2117 set_windres_bfd_content (wrbfd, vvsd, off, 4); 2118 } 2119 off += 4; 2120 } 2121 if (wrbfd) 2122 { 2123 windres_put_16 (wrbfd, bvvd.size, off - vvd_off); 2124 windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off); 2125 windres_put_16 (wrbfd, bvvd.sig2, 0); 2126 set_windres_bfd_content (wrbfd, &bvvd, vvd_off, 2127 BIN_VER_INFO_SIZE); 2128 } 2129 2130 break; 2131 } 2132 } 2133 2134 if (wrbfd) 2135 { 2136 windres_put_16 (wrbfd, bv.size, off - bv_off); 2137 windres_put_16 (wrbfd, bv.sig1, 0); 2138 windres_put_16 (wrbfd, bv.sig2, 1); 2139 set_windres_bfd_content (wrbfd, &bv, bv_off, 2140 BIN_VER_INFO_SIZE); 2141 } 2142 } 2143 2144 if (wrbfd) 2145 { 2146 windres_put_16 (wrbfd, bvi.size, off - start); 2147 windres_put_16 (wrbfd, bvi.fixed_size, 2148 versioninfo->fixed == NULL ? 0 2149 : BIN_FIXED_VERSIONINFO_SIZE); 2150 windres_put_16 (wrbfd, bvi.sig2, 0); 2151 set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE); 2152 } 2153 return off; 2154 } 2155 2156 /* Convert a generic resource to binary. */ 2157 2158 static rc_uint_type 2159 res_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length, 2160 const bfd_byte *data) 2161 { 2162 if (wrbfd && length != 0) 2163 set_windres_bfd_content (wrbfd, data, off, length); 2164 return off + (rc_uint_type) length; 2165 } 2166