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