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