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