1 /* resbin.c -- manipulate the Windows binary resource format. 2 Copyright (C) 1997-2016 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 *, rc_uint_type); 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, length); 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 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 606 static rc_res_resource * 607 bin_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 652 static rc_res_resource * 653 bin_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 723 static rc_res_resource * 724 bin_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 765 static rc_res_resource * 766 bin_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 788 static rc_res_resource * 789 bin_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 843 static rc_res_resource * 844 bin_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 902 static void 903 get_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 952 static rc_res_resource * 953 bin_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 if ((unsigned int) verlen != length) 965 fatal (_("version length %d does not match resource length %lu"), 966 (int) verlen, (unsigned long) length); 967 968 if (type != 0) 969 fatal (_("unexpected version type %d"), (int) type); 970 971 data += off; 972 length -= off; 973 974 if (vallen == 0) 975 fi = NULL; 976 else 977 { 978 unsigned long signature, fiv; 979 980 if (vallen != 52) 981 fatal (_("unexpected fixed version information length %ld"), (long) vallen); 982 983 if (length < 52) 984 toosmall (_("fixed version info")); 985 986 signature = windres_get_32 (wrbfd, data, 4); 987 if (signature != 0xfeef04bd) 988 fatal (_("unexpected fixed version signature %lu"), signature); 989 990 fiv = windres_get_32 (wrbfd, data + 4, 4); 991 if (fiv != 0 && fiv != 0x10000) 992 fatal (_("unexpected fixed version info version %lu"), fiv); 993 994 fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo)); 995 996 fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4); 997 fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4); 998 fi->product_version_ms = windres_get_32 (wrbfd, data + 16, 4); 999 fi->product_version_ls = windres_get_32 (wrbfd, data + 20, 4); 1000 fi->file_flags_mask = windres_get_32 (wrbfd, data + 24, 4); 1001 fi->file_flags = windres_get_32 (wrbfd, data + 28, 4); 1002 fi->file_os = windres_get_32 (wrbfd, data + 32, 4); 1003 fi->file_type = windres_get_32 (wrbfd, data + 36, 4); 1004 fi->file_subtype = windres_get_32 (wrbfd, data + 40, 4); 1005 fi->file_date_ms = windres_get_32 (wrbfd, data + 44, 4); 1006 fi->file_date_ls = windres_get_32 (wrbfd, data + 48, 4); 1007 1008 data += 52; 1009 length -= 52; 1010 } 1011 1012 first = NULL; 1013 pp = &first; 1014 1015 while (length > 0) 1016 { 1017 rc_ver_info *vi; 1018 int ch; 1019 1020 if (length < 8) 1021 toosmall (_("version var info")); 1022 1023 vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info)); 1024 1025 ch = windres_get_16 (wrbfd, data + 6, 2); 1026 1027 if (ch == 'S') 1028 { 1029 rc_ver_stringtable **ppvst; 1030 1031 vi->type = VERINFO_STRING; 1032 1033 get_version_header (wrbfd, data, length, "StringFileInfo", 1034 (unichar **) NULL, &verlen, &vallen, &type, 1035 &off); 1036 1037 if (vallen != 0) 1038 fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen); 1039 1040 data += off; 1041 length -= off; 1042 1043 verlen -= off; 1044 1045 vi->u.string.stringtables = NULL; 1046 ppvst = &vi->u.string.stringtables; 1047 1048 while (verlen > 0) 1049 { 1050 rc_ver_stringtable *vst; 1051 rc_uint_type stverlen; 1052 rc_ver_stringinfo **ppvs; 1053 1054 if (length < 8) 1055 toosmall (_("version stringtable")); 1056 1057 vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable)); 1058 1059 get_version_header (wrbfd, data, length, (const char *) NULL, 1060 &vst->language, &stverlen, &vallen, &type, &off); 1061 1062 if (vallen != 0) 1063 fatal (_("unexpected version stringtable value length %ld"), (long) vallen); 1064 1065 data += off; 1066 length -= off; 1067 verlen -= off; 1068 1069 stverlen -= off; 1070 1071 vst->strings = NULL; 1072 ppvs = &vst->strings; 1073 1074 while (stverlen > 0) 1075 { 1076 rc_ver_stringinfo *vs; 1077 rc_uint_type sverlen, vslen, valoff; 1078 1079 if (length < 8) 1080 toosmall (_("version string")); 1081 1082 vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo)); 1083 1084 get_version_header (wrbfd, data, length, (const char *) NULL, 1085 &vs->key, &sverlen, &vallen, &type, &off); 1086 1087 data += off; 1088 length -= off; 1089 1090 vs->value = get_unicode (wrbfd, data, length, &vslen); 1091 valoff = vslen * 2 + 2; 1092 valoff = (valoff + 3) & ~3; 1093 1094 if (off + valoff != sverlen) 1095 fatal (_("unexpected version string length %ld != %ld + %ld"), 1096 (long) sverlen, (long) off, (long) valoff); 1097 1098 data += valoff; 1099 length -= valoff; 1100 1101 if (stverlen < sverlen) 1102 fatal (_("unexpected version string length %ld < %ld"), 1103 (long) verlen, (long) sverlen); 1104 stverlen -= sverlen; 1105 verlen -= sverlen; 1106 1107 vs->next = NULL; 1108 *ppvs = vs; 1109 ppvs = &vs->next; 1110 } 1111 1112 vst->next = NULL; 1113 *ppvst = vst; 1114 ppvst = &vst->next; 1115 } 1116 } 1117 else if (ch == 'V') 1118 { 1119 rc_ver_varinfo **ppvv; 1120 1121 vi->type = VERINFO_VAR; 1122 1123 get_version_header (wrbfd, data, length, "VarFileInfo", 1124 (unichar **) NULL, &verlen, &vallen, &type, 1125 &off); 1126 1127 if (vallen != 0) 1128 fatal (_("unexpected varfileinfo value length %ld"), (long) vallen); 1129 1130 data += off; 1131 length -= off; 1132 1133 get_version_header (wrbfd, data, length, (const char *) NULL, 1134 &vi->u.var.key, &verlen, &vallen, &type, &off); 1135 1136 data += off; 1137 length -= off; 1138 1139 vi->u.var.var = NULL; 1140 ppvv = &vi->u.var.var; 1141 1142 while (vallen > 0) 1143 { 1144 rc_ver_varinfo *vv; 1145 1146 if (length < 4) 1147 toosmall (_("version varfileinfo")); 1148 1149 vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo)); 1150 1151 vv->language = windres_get_16 (wrbfd, data, 2); 1152 vv->charset = windres_get_16 (wrbfd, data + 2, 2); 1153 1154 vv->next = NULL; 1155 *ppvv = vv; 1156 ppvv = &vv->next; 1157 1158 data += 4; 1159 length -= 4; 1160 1161 if (vallen < 4) 1162 fatal (_("unexpected version value length %ld"), (long) vallen); 1163 1164 vallen -= 4; 1165 } 1166 } 1167 else 1168 fatal (_("unexpected version string")); 1169 1170 vi->next = NULL; 1171 *pp = vi; 1172 pp = &vi->next; 1173 } 1174 1175 v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo)); 1176 v->fixed = fi; 1177 v->var = first; 1178 1179 r = (rc_res_resource *) res_alloc (sizeof *r); 1180 r->type = RES_TYPE_VERSIONINFO; 1181 r->u.versioninfo = v; 1182 1183 return r; 1184 } 1185 1186 /* Convert an arbitrary user defined resource from binary. */ 1187 1188 static rc_res_resource * 1189 bin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, 1190 rc_uint_type length) 1191 { 1192 rc_rcdata_item *ri; 1193 rc_res_resource *r; 1194 1195 ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); 1196 1197 ri->next = NULL; 1198 ri->type = RCDATA_BUFFER; 1199 ri->u.buffer.length = length; 1200 ri->u.buffer.data = data; 1201 1202 r = (rc_res_resource *) res_alloc (sizeof *r); 1203 r->type = RES_TYPE_USERDATA; 1204 r->u.rcdata = ri; 1205 1206 return r; 1207 } 1208 1209 static rc_res_resource * 1210 bin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 1211 { 1212 rc_toolbar *ri; 1213 rc_res_resource *r; 1214 rc_uint_type i; 1215 1216 ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar)); 1217 ri->button_width = windres_get_32 (wrbfd, data, 4); 1218 ri->button_height = windres_get_32 (wrbfd, data + 4, 4); 1219 ri->nitems = windres_get_32 (wrbfd, data + 8, 4); 1220 ri->items = NULL; 1221 1222 data += 12; 1223 length -= 12; 1224 for (i=0 ; i < ri->nitems; i++) 1225 { 1226 rc_toolbar_item *it; 1227 it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item)); 1228 it->id.named = 0; 1229 it->id.u.id = (int) windres_get_32 (wrbfd, data, 4); 1230 it->prev = it->next = NULL; 1231 data += 4; 1232 length -= 4; 1233 if(ri->items) { 1234 rc_toolbar_item *ii = ri->items; 1235 while (ii->next != NULL) 1236 ii = ii->next; 1237 it->prev = ii; 1238 ii->next = it; 1239 } 1240 else 1241 ri->items = it; 1242 } 1243 r = (rc_res_resource *) res_alloc (sizeof *r); 1244 r->type = RES_TYPE_TOOLBAR; 1245 r->u.toolbar = ri; 1246 return r; 1247 } 1248 1249 1250 /* Local functions used to convert resources to binary format. */ 1251 1252 static rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id); 1253 static rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *); 1254 static rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *); 1255 static rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *); 1256 static rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *); 1257 static rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *); 1258 static rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *); 1259 static rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *); 1260 static rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *); 1261 static rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *); 1262 static rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *); 1263 static rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *); 1264 static rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *); 1265 static rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *); 1266 static rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb); 1267 static rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *); 1268 static rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type, 1269 const bfd_byte *); 1270 1271 /* Convert a resource to binary. */ 1272 1273 rc_uint_type 1274 res_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res) 1275 { 1276 switch (res->type) 1277 { 1278 case RES_TYPE_BITMAP: 1279 case RES_TYPE_FONT: 1280 case RES_TYPE_ICON: 1281 case RES_TYPE_MESSAGETABLE: 1282 return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data); 1283 case RES_TYPE_ACCELERATOR: 1284 return res_to_bin_accelerator (wrbfd, off, res->u.acc); 1285 case RES_TYPE_CURSOR: 1286 return res_to_bin_cursor (wrbfd, off, res->u.cursor); 1287 case RES_TYPE_GROUP_CURSOR: 1288 return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor); 1289 case RES_TYPE_DIALOG: 1290 return res_to_bin_dialog (wrbfd, off, res->u.dialog); 1291 case RES_TYPE_FONTDIR: 1292 return res_to_bin_fontdir (wrbfd, off, res->u.fontdir); 1293 case RES_TYPE_GROUP_ICON: 1294 return res_to_bin_group_icon (wrbfd, off, res->u.group_icon); 1295 case RES_TYPE_MENU: 1296 return res_to_bin_menu (wrbfd, off, res->u.menu); 1297 case RES_TYPE_STRINGTABLE: 1298 return res_to_bin_stringtable (wrbfd, off, res->u.stringtable); 1299 case RES_TYPE_VERSIONINFO: 1300 return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo); 1301 case RES_TYPE_TOOLBAR: 1302 return res_to_bin_toolbar (wrbfd, off, res->u.toolbar); 1303 case RES_TYPE_USERDATA: 1304 case RES_TYPE_RCDATA: 1305 default: 1306 return res_to_bin_rcdata (wrbfd, off, res->u.rcdata); 1307 } 1308 } 1309 1310 /* Convert a resource ID to binary. This always returns exactly one 1311 bindata structure. */ 1312 1313 static rc_uint_type 1314 resid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id) 1315 { 1316 if (! id.named) 1317 { 1318 if (wrbfd) 1319 { 1320 struct bin_res_id bri; 1321 1322 windres_put_16 (wrbfd, bri.sig, 0xffff); 1323 windres_put_16 (wrbfd, bri.id, id.u.id); 1324 set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID); 1325 } 1326 off += BIN_RES_ID; 1327 } 1328 else 1329 { 1330 rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0); 1331 if (wrbfd) 1332 { 1333 bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); 1334 rc_uint_type i; 1335 for (i = 0; i < len; i++) 1336 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]); 1337 windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); 1338 set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); 1339 } 1340 off += (rc_uint_type) ((len + 1) * sizeof (unichar)); 1341 } 1342 return off; 1343 } 1344 1345 /* Convert a null terminated unicode string to binary. This always 1346 returns exactly one bindata structure. */ 1347 1348 static rc_uint_type 1349 unicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str) 1350 { 1351 rc_uint_type len = 0; 1352 1353 if (str != NULL) 1354 len = unichar_len (str); 1355 1356 if (wrbfd) 1357 { 1358 bfd_byte *d; 1359 rc_uint_type i; 1360 d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar)); 1361 for (i = 0; i < len; i++) 1362 windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]); 1363 windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); 1364 set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); 1365 } 1366 off += (rc_uint_type) ((len + 1) * sizeof (unichar)); 1367 1368 return off; 1369 } 1370 1371 /* Convert an accelerator resource to binary. */ 1372 1373 static rc_uint_type 1374 res_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off, 1375 const rc_accelerator *accelerators) 1376 { 1377 const rc_accelerator *a; 1378 1379 for (a = accelerators; a != NULL; a = a->next) 1380 { 1381 if (wrbfd) 1382 { 1383 struct bin_accelerator ba; 1384 1385 windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST)); 1386 windres_put_16 (wrbfd, ba.key, a->key); 1387 windres_put_16 (wrbfd, ba.id, a->id); 1388 windres_put_16 (wrbfd, ba.pad, 0); 1389 set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE); 1390 } 1391 off += BIN_ACCELERATOR_SIZE; 1392 } 1393 return off; 1394 } 1395 1396 /* Convert a cursor resource to binary. */ 1397 1398 static rc_uint_type 1399 res_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c) 1400 { 1401 if (wrbfd) 1402 { 1403 struct bin_cursor bc; 1404 1405 windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot); 1406 windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot); 1407 set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE); 1408 if (c->length) 1409 set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length); 1410 } 1411 off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length); 1412 return off; 1413 } 1414 1415 /* Convert a group cursor resource to binary. */ 1416 1417 static rc_uint_type 1418 res_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off, 1419 const rc_group_cursor *group_cursors) 1420 { 1421 int c = 0; 1422 const rc_group_cursor *gc; 1423 struct bin_group_cursor bgc; 1424 struct bin_group_cursor_item bgci; 1425 rc_uint_type start = off; 1426 1427 off += BIN_GROUP_CURSOR_SIZE; 1428 1429 for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++) 1430 { 1431 if (wrbfd) 1432 { 1433 windres_put_16 (wrbfd, bgci.width, gc->width); 1434 windres_put_16 (wrbfd, bgci.height, gc->height); 1435 windres_put_16 (wrbfd, bgci.planes, gc->planes); 1436 windres_put_16 (wrbfd, bgci.bits, gc->bits); 1437 windres_put_32 (wrbfd, bgci.bytes, gc->bytes); 1438 windres_put_16 (wrbfd, bgci.index, gc->index); 1439 set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE); 1440 } 1441 1442 off += BIN_GROUP_CURSOR_ITEM_SIZE; 1443 } 1444 if (wrbfd) 1445 { 1446 windres_put_16 (wrbfd, bgc.sig1, 0); 1447 windres_put_16 (wrbfd, bgc.sig2, 2); 1448 windres_put_16 (wrbfd, bgc.nitems, c); 1449 set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE); 1450 } 1451 return off; 1452 } 1453 1454 /* Convert a dialog resource to binary. */ 1455 1456 static rc_uint_type 1457 res_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog) 1458 { 1459 rc_uint_type off_delta; 1460 rc_uint_type start, marker; 1461 int dialogex; 1462 int c; 1463 rc_dialog_control *dc; 1464 struct bin_dialogex bdx; 1465 struct bin_dialog bd; 1466 1467 off_delta = off; 1468 start = off; 1469 dialogex = extended_dialog (dialog); 1470 1471 if (wrbfd) 1472 { 1473 if (! dialogex) 1474 { 1475 windres_put_32 (wrbfd, bd.style, dialog->style); 1476 windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle); 1477 windres_put_16 (wrbfd, bd.x, dialog->x); 1478 windres_put_16 (wrbfd, bd.y, dialog->y); 1479 windres_put_16 (wrbfd, bd.width, dialog->width); 1480 windres_put_16 (wrbfd, bd.height, dialog->height); 1481 } 1482 else 1483 { 1484 windres_put_16 (wrbfd, bdx.sig1, 1); 1485 windres_put_16 (wrbfd, bdx.sig2, 0xffff); 1486 windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0)); 1487 windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle); 1488 windres_put_32 (wrbfd, bdx.style, dialog->style); 1489 windres_put_16 (wrbfd, bdx.x, dialog->x); 1490 windres_put_16 (wrbfd, bdx.y, dialog->y); 1491 windres_put_16 (wrbfd, bdx.width, dialog->width); 1492 windres_put_16 (wrbfd, bdx.height, dialog->height); 1493 } 1494 } 1495 1496 off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE); 1497 1498 off = resid_to_bin (wrbfd, off, dialog->menu); 1499 off = resid_to_bin (wrbfd, off, dialog->class); 1500 off = unicode_to_bin (wrbfd, off, dialog->caption); 1501 1502 if ((dialog->style & DS_SETFONT) != 0) 1503 { 1504 if (wrbfd) 1505 { 1506 if (! dialogex) 1507 { 1508 struct bin_dialogfont bdf; 1509 windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize); 1510 set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE); 1511 } 1512 else 1513 { 1514 struct bin_dialogexfont bdxf; 1515 windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize); 1516 windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight)); 1517 windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic)); 1518 windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset)); 1519 set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE); 1520 } 1521 } 1522 off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE); 1523 off = unicode_to_bin (wrbfd, off, dialog->font); 1524 } 1525 for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++) 1526 { 1527 bfd_byte dc_rclen[2]; 1528 1529 off += (4 - ((off - off_delta) & 3)) & 3; 1530 if (wrbfd) 1531 { 1532 if (! dialogex) 1533 { 1534 struct bin_dialog_control bdc; 1535 1536 windres_put_32 (wrbfd, bdc.style, dc->style); 1537 windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle); 1538 windres_put_16 (wrbfd, bdc.x, dc->x); 1539 windres_put_16 (wrbfd, bdc.y, dc->y); 1540 windres_put_16 (wrbfd, bdc.width, dc->width); 1541 windres_put_16 (wrbfd, bdc.height, dc->height); 1542 windres_put_16 (wrbfd, bdc.id, dc->id); 1543 set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE); 1544 } 1545 else 1546 { 1547 struct bin_dialogex_control bdc; 1548 1549 windres_put_32 (wrbfd, bdc.help, dc->help); 1550 windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle); 1551 windres_put_32 (wrbfd, bdc.style, dc->style); 1552 windres_put_16 (wrbfd, bdc.x, dc->x); 1553 windres_put_16 (wrbfd, bdc.y, dc->y); 1554 windres_put_16 (wrbfd, bdc.width, dc->width); 1555 windres_put_16 (wrbfd, bdc.height, dc->height); 1556 windres_put_32 (wrbfd, bdc.id, dc->id); 1557 set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE); 1558 } 1559 } 1560 off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE); 1561 1562 off = resid_to_bin (wrbfd, off, dc->class); 1563 off = resid_to_bin (wrbfd, off, dc->text); 1564 1565 marker = off; /* Save two bytes for size of optional data. */ 1566 off += 2; 1567 1568 if (dc->data == NULL) 1569 { 1570 if (wrbfd) 1571 windres_put_16 (wrbfd, dc_rclen, 0); 1572 } 1573 else 1574 { 1575 rc_uint_type saved_off = off; 1576 rc_uint_type old_off; 1577 off += (4 - ((off - off_delta) & 3)) & 3; 1578 1579 old_off = off; 1580 off = res_to_bin_rcdata (wrbfd, off, dc->data); 1581 if ((off - old_off) == 0) 1582 old_off = off = saved_off; 1583 if (wrbfd) 1584 windres_put_16 (wrbfd, dc_rclen, off - old_off); 1585 } 1586 if (wrbfd) 1587 set_windres_bfd_content (wrbfd, dc_rclen, marker, 2); 1588 } 1589 1590 if (wrbfd) 1591 { 1592 windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c); 1593 if (! dialogex) 1594 set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE); 1595 else 1596 set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE); 1597 } 1598 1599 return off; 1600 } 1601 1602 /* Convert a fontdir resource to binary. */ 1603 static rc_uint_type 1604 res_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs) 1605 { 1606 rc_uint_type start; 1607 int c; 1608 const rc_fontdir *fd; 1609 1610 start = off; 1611 off += 2; 1612 1613 for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++) 1614 { 1615 if (wrbfd) 1616 { 1617 bfd_byte d[2]; 1618 windres_put_16 (wrbfd, d, fd->index); 1619 set_windres_bfd_content (wrbfd, d, off, 2); 1620 if (fd->length) 1621 set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length); 1622 } 1623 off += (rc_uint_type) fd->length + 2; 1624 } 1625 1626 if (wrbfd) 1627 { 1628 bfd_byte d[2]; 1629 windres_put_16 (wrbfd, d, c); 1630 set_windres_bfd_content (wrbfd, d, start, 2); 1631 } 1632 return off; 1633 } 1634 1635 /* Convert a group icon resource to binary. */ 1636 1637 static rc_uint_type 1638 res_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons) 1639 { 1640 rc_uint_type start; 1641 struct bin_group_icon bgi; 1642 int c; 1643 const rc_group_icon *gi; 1644 1645 start = off; 1646 off += BIN_GROUP_ICON_SIZE; 1647 1648 for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++) 1649 { 1650 struct bin_group_icon_item bgii; 1651 1652 if (wrbfd) 1653 { 1654 windres_put_8 (wrbfd, bgii.width, gi->width); 1655 windres_put_8 (wrbfd, bgii.height, gi->height); 1656 windres_put_8 (wrbfd, bgii.colors, gi->colors); 1657 windres_put_8 (wrbfd, bgii.pad, 0); 1658 windres_put_16 (wrbfd, bgii.planes, gi->planes); 1659 windres_put_16 (wrbfd, bgii.bits, gi->bits); 1660 windres_put_32 (wrbfd, bgii.bytes, gi->bytes); 1661 windres_put_16 (wrbfd, bgii.index, gi->index); 1662 set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE); 1663 } 1664 off += BIN_GROUP_ICON_ITEM_SIZE; 1665 } 1666 1667 if (wrbfd) 1668 { 1669 windres_put_16 (wrbfd, bgi.sig1, 0); 1670 windres_put_16 (wrbfd, bgi.sig2, 1); 1671 windres_put_16 (wrbfd, bgi.count, c); 1672 set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE); 1673 } 1674 return off; 1675 } 1676 1677 /* Convert a menu resource to binary. */ 1678 1679 static rc_uint_type 1680 res_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu) 1681 { 1682 int menuex; 1683 1684 menuex = extended_menu (menu); 1685 1686 if (wrbfd) 1687 { 1688 if (! menuex) 1689 { 1690 struct bin_menu bm; 1691 windres_put_16 (wrbfd, bm.sig1, 0); 1692 windres_put_16 (wrbfd, bm.sig2, 0); 1693 set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE); 1694 } 1695 else 1696 { 1697 struct bin_menuex bm; 1698 windres_put_16 (wrbfd, bm.sig1, 1); 1699 windres_put_16 (wrbfd, bm.sig2, 4); 1700 windres_put_32 (wrbfd, bm.help, menu->help); 1701 set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE); 1702 } 1703 } 1704 off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE); 1705 if (! menuex) 1706 { 1707 off = res_to_bin_menuitems (wrbfd, off, menu->items); 1708 } 1709 else 1710 { 1711 off = res_to_bin_menuexitems (wrbfd, off, menu->items); 1712 } 1713 return off; 1714 } 1715 1716 /* Convert menu items to binary. */ 1717 1718 static rc_uint_type 1719 res_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) 1720 { 1721 const rc_menuitem *mi; 1722 1723 for (mi = items; mi != NULL; mi = mi->next) 1724 { 1725 struct bin_menuitem bmi; 1726 int flags; 1727 1728 flags = mi->type; 1729 if (mi->next == NULL) 1730 flags |= MENUITEM_ENDMENU; 1731 if (mi->popup != NULL) 1732 flags |= MENUITEM_POPUP; 1733 1734 if (wrbfd) 1735 { 1736 windres_put_16 (wrbfd, bmi.flags, flags); 1737 if (mi->popup == NULL) 1738 windres_put_16 (wrbfd, bmi.id, mi->id); 1739 set_windres_bfd_content (wrbfd, &bmi, off, 1740 mi->popup == NULL ? BIN_MENUITEM_SIZE 1741 : BIN_MENUITEM_POPUP_SIZE); 1742 } 1743 off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE); 1744 1745 off = unicode_to_bin (wrbfd, off, mi->text); 1746 1747 if (mi->popup != NULL) 1748 { 1749 off = res_to_bin_menuitems (wrbfd, off, mi->popup); 1750 } 1751 } 1752 return off; 1753 } 1754 1755 /* Convert menuex items to binary. */ 1756 1757 static rc_uint_type 1758 res_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) 1759 { 1760 rc_uint_type off_delta = off; 1761 const rc_menuitem *mi; 1762 1763 for (mi = items; mi != NULL; mi = mi->next) 1764 { 1765 struct bin_menuitemex bmi; 1766 int flags; 1767 1768 off += (4 - ((off - off_delta) & 3)) & 3; 1769 1770 flags = 0; 1771 if (mi->next == NULL) 1772 flags |= 0x80; 1773 if (mi->popup != NULL) 1774 flags |= 1; 1775 1776 if (wrbfd) 1777 { 1778 windres_put_32 (wrbfd, bmi.type, mi->type); 1779 windres_put_32 (wrbfd, bmi.state, mi->state); 1780 windres_put_32 (wrbfd, bmi.id, mi->id); 1781 windres_put_16 (wrbfd, bmi.flags, flags); 1782 set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE); 1783 } 1784 off += BIN_MENUITEMEX_SIZE; 1785 1786 off = unicode_to_bin (wrbfd, off, mi->text); 1787 1788 if (mi->popup != NULL) 1789 { 1790 bfd_byte help[4]; 1791 1792 off += (4 - ((off - off_delta) & 3)) & 3; 1793 1794 if (wrbfd) 1795 { 1796 windres_put_32 (wrbfd, help, mi->help); 1797 set_windres_bfd_content (wrbfd, help, off, 4); 1798 } 1799 off += 4; 1800 off = res_to_bin_menuexitems (wrbfd, off, mi->popup); 1801 } 1802 } 1803 return off; 1804 } 1805 1806 /* Convert an rcdata resource to binary. This is also used to convert 1807 other information which happens to be stored in rc_rcdata_item lists 1808 to binary. */ 1809 1810 static rc_uint_type 1811 res_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items) 1812 { 1813 const rc_rcdata_item *ri; 1814 1815 for (ri = items; ri != NULL; ri = ri->next) 1816 { 1817 rc_uint_type len; 1818 switch (ri->type) 1819 { 1820 default: 1821 abort (); 1822 case RCDATA_WORD: 1823 len = 2; 1824 break; 1825 case RCDATA_DWORD: 1826 len = 4; 1827 break; 1828 case RCDATA_STRING: 1829 len = ri->u.string.length; 1830 break; 1831 case RCDATA_WSTRING: 1832 len = ri->u.wstring.length * sizeof (unichar); 1833 break; 1834 case RCDATA_BUFFER: 1835 len = ri->u.buffer.length; 1836 break; 1837 } 1838 if (wrbfd) 1839 { 1840 bfd_byte h[4]; 1841 bfd_byte *hp = &h[0]; 1842 switch (ri->type) 1843 { 1844 case RCDATA_WORD: 1845 windres_put_16 (wrbfd, hp, ri->u.word); 1846 break; 1847 case RCDATA_DWORD: 1848 windres_put_32 (wrbfd, hp, ri->u.dword); 1849 break; 1850 case RCDATA_STRING: 1851 hp = (bfd_byte *) ri->u.string.s; 1852 break; 1853 case RCDATA_WSTRING: 1854 { 1855 rc_uint_type i; 1856 1857 hp = (bfd_byte *) reswr_alloc (len); 1858 for (i = 0; i < ri->u.wstring.length; i++) 1859 windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]); 1860 } 1861 break; 1862 case RCDATA_BUFFER: 1863 hp = (bfd_byte *) ri->u.buffer.data; 1864 break; 1865 } 1866 set_windres_bfd_content (wrbfd, hp, off, len); 1867 } 1868 off += len; 1869 } 1870 return off; 1871 } 1872 1873 /* Convert a stringtable resource to binary. */ 1874 1875 static rc_uint_type 1876 res_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off, 1877 const rc_stringtable *st) 1878 { 1879 int i; 1880 1881 for (i = 0; i < 16; i++) 1882 { 1883 rc_uint_type slen, length; 1884 unichar *s; 1885 1886 slen = (rc_uint_type) st->strings[i].length; 1887 if (slen == 0xffffffff) slen = 0; 1888 s = st->strings[i].string; 1889 1890 length = 2 + slen * 2; 1891 if (wrbfd) 1892 { 1893 bfd_byte *hp; 1894 rc_uint_type j; 1895 1896 hp = (bfd_byte *) reswr_alloc (length); 1897 windres_put_16 (wrbfd, hp, slen); 1898 1899 for (j = 0; j < slen; j++) 1900 windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]); 1901 set_windres_bfd_content (wrbfd, hp, off, length); 1902 } 1903 off += length; 1904 } 1905 return off; 1906 } 1907 1908 /* Convert an ASCII string to a unicode binary string. This always 1909 returns exactly one bindata structure. */ 1910 1911 static rc_uint_type 1912 string_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s) 1913 { 1914 rc_uint_type len; 1915 1916 len = (rc_uint_type) strlen (s); 1917 1918 if (wrbfd) 1919 { 1920 rc_uint_type i; 1921 bfd_byte *hp; 1922 1923 hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); 1924 1925 for (i = 0; i < len; i++) 1926 windres_put_16 (wrbfd, hp + i * 2, s[i]); 1927 windres_put_16 (wrbfd, hp + i * 2, 0); 1928 set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar)); 1929 } 1930 off += (rc_uint_type) ((len + 1) * sizeof (unichar)); 1931 return off; 1932 } 1933 1934 static rc_uint_type 1935 res_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb) 1936 { 1937 if (wrbfd) 1938 { 1939 struct bin_toolbar bt; 1940 windres_put_32 (wrbfd, bt.button_width, tb->button_width); 1941 windres_put_32 (wrbfd, bt.button_height, tb->button_height); 1942 windres_put_32 (wrbfd, bt.nitems, tb->nitems); 1943 set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE); 1944 if (tb->nitems > 0) 1945 { 1946 rc_toolbar_item *it; 1947 bfd_byte *ids; 1948 rc_uint_type i = 0; 1949 1950 ids = (bfd_byte *) reswr_alloc (tb->nitems * 4); 1951 it=tb->items; 1952 while(it != NULL) 1953 { 1954 windres_put_32 (wrbfd, ids + i, it->id.u.id); 1955 i += 4; 1956 it = it->next; 1957 } 1958 set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i); 1959 } 1960 } 1961 off += BIN_TOOLBAR_SIZE + tb->nitems * 4; 1962 1963 return off; 1964 } 1965 1966 /* Convert a versioninfo resource to binary. */ 1967 1968 static rc_uint_type 1969 res_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, 1970 const rc_versioninfo *versioninfo) 1971 { 1972 rc_uint_type off_delta = off; 1973 rc_uint_type start; 1974 struct bin_versioninfo bvi; 1975 rc_ver_info *vi; 1976 1977 start = off; 1978 off += BIN_VERSIONINFO_SIZE; 1979 off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO"); 1980 off += (4 - ((off - off_delta) & 3)) & 3; 1981 1982 if (versioninfo->fixed != NULL) 1983 { 1984 if (wrbfd) 1985 { 1986 struct bin_fixed_versioninfo bfv; 1987 const rc_fixed_versioninfo *fi; 1988 1989 fi = versioninfo->fixed; 1990 windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd); 1991 windres_put_32 (wrbfd, bfv.sig2, 0x10000); 1992 windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms); 1993 windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls); 1994 windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms); 1995 windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls); 1996 windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask); 1997 windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags); 1998 windres_put_32 (wrbfd, bfv.file_os, fi->file_os); 1999 windres_put_32 (wrbfd, bfv.file_type, fi->file_type); 2000 windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype); 2001 windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms); 2002 windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls); 2003 set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE); 2004 } 2005 off += BIN_FIXED_VERSIONINFO_SIZE; 2006 } 2007 2008 for (vi = versioninfo->var; vi != NULL; vi = vi->next) 2009 { 2010 struct bin_ver_info bv; 2011 rc_uint_type bv_off; 2012 2013 off += (4 - ((off - off_delta) & 3)) & 3; 2014 2015 bv_off = off; 2016 2017 off += BIN_VER_INFO_SIZE; 2018 2019 switch (vi->type) 2020 { 2021 default: 2022 abort (); 2023 case VERINFO_STRING: 2024 { 2025 const rc_ver_stringtable *vst; 2026 2027 off = string_to_unicode_bin (wrbfd, off, "StringFileInfo"); 2028 2029 if (!vi->u.string.stringtables) 2030 off += (4 - ((off - off_delta) & 3)) & 3; 2031 2032 for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next) 2033 { 2034 struct bin_ver_info bvst; 2035 rc_uint_type vst_off; 2036 const rc_ver_stringinfo *vs; 2037 2038 off += (4 - ((off - off_delta) & 3)) & 3; 2039 2040 vst_off = off; 2041 off += BIN_VER_INFO_SIZE; 2042 2043 off = unicode_to_bin (wrbfd, off, vst->language); 2044 2045 for (vs = vst->strings; vs != NULL; vs = vs->next) 2046 { 2047 struct bin_ver_info bvs; 2048 rc_uint_type vs_off, str_off; 2049 2050 off += (4 - ((off - off_delta) & 3)) & 3; 2051 2052 vs_off = off; 2053 off += BIN_VER_INFO_SIZE; 2054 2055 off = unicode_to_bin (wrbfd, off, vs->key); 2056 2057 off += (4 - ((off - off_delta) & 3)) & 3; 2058 2059 str_off = off; 2060 off = unicode_to_bin (wrbfd, off, vs->value); 2061 2062 if (wrbfd) 2063 { 2064 windres_put_16 (wrbfd, bvs.size, off - vs_off); 2065 windres_put_16 (wrbfd, bvs.sig1, (off - str_off) / 2); 2066 windres_put_16 (wrbfd, bvs.sig2, 1); 2067 set_windres_bfd_content (wrbfd, &bvs, vs_off, 2068 BIN_VER_INFO_SIZE); 2069 } 2070 } 2071 2072 if (wrbfd) 2073 { 2074 windres_put_16 (wrbfd, bvst.size, off - vst_off); 2075 windres_put_16 (wrbfd, bvst.sig1, 0); 2076 windres_put_16 (wrbfd, bvst.sig2, 1); 2077 set_windres_bfd_content (wrbfd, &bvst, vst_off, 2078 BIN_VER_INFO_SIZE); 2079 } 2080 } 2081 break; 2082 } 2083 2084 case VERINFO_VAR: 2085 { 2086 rc_uint_type vvd_off, vvvd_off; 2087 struct bin_ver_info bvvd; 2088 const rc_ver_varinfo *vv; 2089 2090 off = string_to_unicode_bin (wrbfd, off, "VarFileInfo"); 2091 2092 off += (4 - ((off - off_delta) & 3)) & 3; 2093 2094 vvd_off = off; 2095 off += BIN_VER_INFO_SIZE; 2096 2097 off = unicode_to_bin (wrbfd, off, vi->u.var.key); 2098 2099 off += (4 - ((off - off_delta) & 3)) & 3; 2100 2101 vvvd_off = off; 2102 2103 for (vv = vi->u.var.var; vv != NULL; vv = vv->next) 2104 { 2105 if (wrbfd) 2106 { 2107 bfd_byte vvsd[4]; 2108 2109 windres_put_16 (wrbfd, &vvsd[0], vv->language); 2110 windres_put_16 (wrbfd, &vvsd[2], vv->charset); 2111 set_windres_bfd_content (wrbfd, vvsd, off, 4); 2112 } 2113 off += 4; 2114 } 2115 if (wrbfd) 2116 { 2117 windres_put_16 (wrbfd, bvvd.size, off - vvd_off); 2118 windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off); 2119 windres_put_16 (wrbfd, bvvd.sig2, 0); 2120 set_windres_bfd_content (wrbfd, &bvvd, vvd_off, 2121 BIN_VER_INFO_SIZE); 2122 } 2123 2124 break; 2125 } 2126 } 2127 2128 if (wrbfd) 2129 { 2130 windres_put_16 (wrbfd, bv.size, off - bv_off); 2131 windres_put_16 (wrbfd, bv.sig1, 0); 2132 windres_put_16 (wrbfd, bv.sig2, 1); 2133 set_windres_bfd_content (wrbfd, &bv, bv_off, 2134 BIN_VER_INFO_SIZE); 2135 } 2136 } 2137 2138 if (wrbfd) 2139 { 2140 windres_put_16 (wrbfd, bvi.size, off - start); 2141 windres_put_16 (wrbfd, bvi.fixed_size, 2142 versioninfo->fixed == NULL ? 0 2143 : BIN_FIXED_VERSIONINFO_SIZE); 2144 windres_put_16 (wrbfd, bvi.sig2, 0); 2145 set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE); 2146 } 2147 return off; 2148 } 2149 2150 /* Convert a generic resource to binary. */ 2151 2152 static rc_uint_type 2153 res_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length, 2154 const bfd_byte *data) 2155 { 2156 if (wrbfd && length != 0) 2157 set_windres_bfd_content (wrbfd, data, off, length); 2158 return off + (rc_uint_type) length; 2159 } 2160