138889Sjdp/* resbin.c -- manipulate the Windows binary resource format. 2218822Sdim Copyright 1997, 1998, 1999, 2002, 2003, 2007 3130561Sobrien Free Software Foundation, Inc. 438889Sjdp Written by Ian Lance Taylor, Cygnus Support. 5218822Sdim Rewritten by Kai Tietz, Onevision. 638889Sjdp 738889Sjdp This file is part of GNU Binutils. 838889Sjdp 938889Sjdp This program is free software; you can redistribute it and/or modify 1038889Sjdp it under the terms of the GNU General Public License as published by 1138889Sjdp the Free Software Foundation; either version 2 of the License, or 1238889Sjdp (at your option) any later version. 1338889Sjdp 1438889Sjdp This program is distributed in the hope that it will be useful, 1538889Sjdp but WITHOUT ANY WARRANTY; without even the implied warranty of 1638889Sjdp MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1738889Sjdp GNU General Public License for more details. 1838889Sjdp 1938889Sjdp You should have received a copy of the GNU General Public License 2038889Sjdp along with this program; if not, write to the Free Software 21218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 22218822Sdim 02110-1301, USA. */ 2338889Sjdp 2438889Sjdp/* This file contains functions to convert between the binary resource 2538889Sjdp format and the internal structures that we want to use. The same 2638889Sjdp binary resource format is used in both res and COFF files. */ 2738889Sjdp 28218822Sdim#include "sysdep.h" 2938889Sjdp#include "bfd.h" 3038889Sjdp#include "bucomm.h" 3138889Sjdp#include "libiberty.h" 3238889Sjdp#include "windres.h" 3338889Sjdp 3438889Sjdp/* Local functions. */ 3538889Sjdp 36130561Sobrienstatic void toosmall (const char *); 37130561Sobrien 38218822Sdimstatic unichar *get_unicode (windres_bfd *, const bfd_byte *, rc_uint_type, rc_uint_type *); 39218822Sdimstatic int get_resid (windres_bfd *, rc_res_id *, const bfd_byte *, rc_uint_type); 40218822Sdimstatic rc_res_resource *bin_to_res_generic (windres_bfd *, enum rc_res_type, 41218822Sdim const bfd_byte *, rc_uint_type); 42218822Sdimstatic rc_res_resource *bin_to_res_cursor (windres_bfd *, const bfd_byte *, rc_uint_type); 43218822Sdimstatic rc_res_resource *bin_to_res_menu (windres_bfd *,const bfd_byte *, rc_uint_type); 44218822Sdimstatic rc_menuitem *bin_to_res_menuitems (windres_bfd *, const bfd_byte *, rc_uint_type, 45218822Sdim rc_uint_type *); 46218822Sdimstatic rc_menuitem *bin_to_res_menuexitems (windres_bfd *, const bfd_byte *, rc_uint_type, 47218822Sdim rc_uint_type *); 48218822Sdimstatic rc_res_resource *bin_to_res_dialog (windres_bfd *, const bfd_byte *, rc_uint_type); 49218822Sdimstatic rc_res_resource *bin_to_res_string (windres_bfd *,const bfd_byte *, rc_uint_type); 50218822Sdimstatic rc_res_resource *bin_to_res_fontdir (windres_bfd *, const bfd_byte *, rc_uint_type); 51218822Sdimstatic rc_res_resource *bin_to_res_accelerators (windres_bfd *, const bfd_byte *, rc_uint_type); 52218822Sdimstatic rc_res_resource *bin_to_res_rcdata (windres_bfd *, const bfd_byte *, rc_uint_type, int); 53218822Sdimstatic rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *, rc_uint_type); 54218822Sdimstatic rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type); 55218822Sdimstatic rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type); 56218822Sdimstatic rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type); 57218822Sdimstatic rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type); 58218822Sdimstatic void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *, 59218822Sdim unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *, 60218822Sdim rc_uint_type *); 6138889Sjdp 6238889Sjdp/* Given a resource type ID, a pointer to data, a length, return a 63218822Sdim rc_res_resource structure which represents that resource. The caller 6438889Sjdp is responsible for initializing the res_info and coff_info fields 6538889Sjdp of the returned structure. */ 6638889Sjdp 67218822Sdimrc_res_resource * 68218822Sdimbin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data, 69218822Sdim rc_uint_type length) 7038889Sjdp{ 7138889Sjdp if (type.named) 72218822Sdim return bin_to_res_userdata (wrbfd, data, length); 7338889Sjdp else 7438889Sjdp { 7538889Sjdp switch (type.u.id) 7638889Sjdp { 7738889Sjdp default: 78218822Sdim return bin_to_res_userdata (wrbfd, data, length); 7938889Sjdp case RT_CURSOR: 80218822Sdim return bin_to_res_cursor (wrbfd, data, length); 8138889Sjdp case RT_BITMAP: 82218822Sdim return bin_to_res_generic (wrbfd, RES_TYPE_BITMAP, data, length); 8338889Sjdp case RT_ICON: 84218822Sdim return bin_to_res_generic (wrbfd, RES_TYPE_ICON, data, length); 8538889Sjdp case RT_MENU: 86218822Sdim return bin_to_res_menu (wrbfd, data, length); 8738889Sjdp case RT_DIALOG: 88218822Sdim return bin_to_res_dialog (wrbfd, data, length); 8938889Sjdp case RT_STRING: 90218822Sdim return bin_to_res_string (wrbfd, data, length); 9138889Sjdp case RT_FONTDIR: 92218822Sdim return bin_to_res_fontdir (wrbfd, data, length); 9338889Sjdp case RT_FONT: 94218822Sdim return bin_to_res_generic (wrbfd, RES_TYPE_FONT, data, length); 9560484Sobrien case RT_ACCELERATOR: 96218822Sdim return bin_to_res_accelerators (wrbfd, data, length); 9738889Sjdp case RT_RCDATA: 98218822Sdim return bin_to_res_rcdata (wrbfd, data, length, RES_TYPE_RCDATA); 9938889Sjdp case RT_MESSAGETABLE: 100218822Sdim return bin_to_res_generic (wrbfd, RES_TYPE_MESSAGETABLE, data, length); 10138889Sjdp case RT_GROUP_CURSOR: 102218822Sdim return bin_to_res_group_cursor (wrbfd, data, length); 10338889Sjdp case RT_GROUP_ICON: 104218822Sdim return bin_to_res_group_icon (wrbfd, data, length); 10538889Sjdp case RT_VERSION: 106218822Sdim return bin_to_res_version (wrbfd, data, length); 107218822Sdim case RT_TOOLBAR: 108218822Sdim return bin_to_res_toolbar (wrbfd, data, length); 109218822Sdim 11038889Sjdp } 11138889Sjdp } 11238889Sjdp} 11338889Sjdp 11438889Sjdp/* Give an error if the binary data is too small. */ 11538889Sjdp 11638889Sjdpstatic void 117130561Sobrientoosmall (const char *msg) 11838889Sjdp{ 11960484Sobrien fatal (_("%s: not enough binary data"), msg); 12038889Sjdp} 12138889Sjdp 12238889Sjdp/* Swap in a NULL terminated unicode string. */ 12338889Sjdp 12438889Sjdpstatic unichar * 125218822Sdimget_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, 126218822Sdim rc_uint_type *retlen) 12738889Sjdp{ 128218822Sdim rc_uint_type c, i; 12938889Sjdp unichar *ret; 13038889Sjdp 13138889Sjdp c = 0; 13238889Sjdp while (1) 13338889Sjdp { 134218822Sdim if (length < c * 2 + 2) 13560484Sobrien toosmall (_("null terminated unicode string")); 136218822Sdim if (windres_get_16 (wrbfd, data + c * 2, 2) == 0) 13738889Sjdp break; 13838889Sjdp ++c; 13938889Sjdp } 14038889Sjdp 14138889Sjdp ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar)); 14238889Sjdp 14338889Sjdp for (i = 0; i < c; i++) 144218822Sdim ret[i] = windres_get_16 (wrbfd, data + i * 2, 2); 14538889Sjdp ret[i] = 0; 14638889Sjdp 14738889Sjdp if (retlen != NULL) 14838889Sjdp *retlen = c; 14938889Sjdp 15038889Sjdp return ret; 15138889Sjdp} 15238889Sjdp 15338889Sjdp/* Get a resource identifier. This returns the number of bytes used. */ 15438889Sjdp 15538889Sjdpstatic int 156218822Sdimget_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data, 157218822Sdim rc_uint_type length) 15838889Sjdp{ 159218822Sdim rc_uint_type first; 16038889Sjdp 16138889Sjdp if (length < 2) 16260484Sobrien toosmall (_("resource ID")); 16338889Sjdp 164218822Sdim first = windres_get_16 (wrbfd, data, 2); 16538889Sjdp if (first == 0xffff) 16638889Sjdp { 16738889Sjdp if (length < 4) 16860484Sobrien toosmall (_("resource ID")); 16938889Sjdp id->named = 0; 170218822Sdim id->u.id = windres_get_16 (wrbfd, data + 2, 2); 17138889Sjdp return 4; 17238889Sjdp } 17338889Sjdp else 17438889Sjdp { 17538889Sjdp id->named = 1; 176218822Sdim id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length); 17738889Sjdp return id->u.n.length * 2 + 2; 17838889Sjdp } 17938889Sjdp} 18038889Sjdp 18138889Sjdp/* Convert a resource which just stores uninterpreted data from 18238889Sjdp binary. */ 18338889Sjdp 184218822Sdimrc_res_resource * 185218822Sdimbin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type, 186218822Sdim const bfd_byte *data, rc_uint_type length) 18738889Sjdp{ 188218822Sdim rc_res_resource *r; 18938889Sjdp 190218822Sdim r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); 19138889Sjdp r->type = type; 19238889Sjdp r->u.data.data = data; 19338889Sjdp r->u.data.length = length; 19438889Sjdp 19538889Sjdp return r; 19638889Sjdp} 19738889Sjdp 19838889Sjdp/* Convert a cursor resource from binary. */ 19938889Sjdp 200218822Sdimrc_res_resource * 201218822Sdimbin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 20238889Sjdp{ 203218822Sdim rc_cursor *c; 204218822Sdim rc_res_resource *r; 20538889Sjdp 20638889Sjdp if (length < 4) 20760484Sobrien toosmall (_("cursor")); 20838889Sjdp 209218822Sdim c = (rc_cursor *) res_alloc (sizeof (rc_cursor)); 210218822Sdim c->xhotspot = windres_get_16 (wrbfd, data, 2); 211218822Sdim c->yhotspot = windres_get_16 (wrbfd, data + 2, 2); 21238889Sjdp c->length = length - 4; 21338889Sjdp c->data = data + 4; 21438889Sjdp 215218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 21638889Sjdp r->type = RES_TYPE_CURSOR; 21738889Sjdp r->u.cursor = c; 21838889Sjdp 21938889Sjdp return r; 22038889Sjdp} 22138889Sjdp 22238889Sjdp/* Convert a menu resource from binary. */ 22338889Sjdp 224218822Sdimrc_res_resource * 225218822Sdimbin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 22638889Sjdp{ 227218822Sdim rc_res_resource *r; 228218822Sdim rc_menu *m; 229218822Sdim rc_uint_type version, read; 23038889Sjdp 231218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 23238889Sjdp r->type = RES_TYPE_MENU; 23338889Sjdp 234218822Sdim m = (rc_menu *) res_alloc (sizeof (rc_menu)); 23538889Sjdp r->u.menu = m; 23638889Sjdp 23738889Sjdp if (length < 2) 23860484Sobrien toosmall (_("menu header")); 23938889Sjdp 240218822Sdim version = windres_get_16 (wrbfd, data, 2); 24138889Sjdp 24238889Sjdp if (version == 0) 24338889Sjdp { 24438889Sjdp if (length < 4) 24560484Sobrien toosmall (_("menu header")); 24638889Sjdp m->help = 0; 247218822Sdim m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &read); 24838889Sjdp } 24938889Sjdp else if (version == 1) 25038889Sjdp { 251218822Sdim rc_uint_type offset; 25238889Sjdp 25338889Sjdp if (length < 8) 25460484Sobrien toosmall (_("menuex header")); 255218822Sdim m->help = windres_get_32 (wrbfd, data + 4, 4); 256218822Sdim offset = windres_get_16 (wrbfd, data + 2, 2); 25738889Sjdp if (offset + 4 >= length) 25860484Sobrien toosmall (_("menuex offset")); 259218822Sdim m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset, 260218822Sdim length - (4 + offset), &read); 26138889Sjdp } 26238889Sjdp else 263218822Sdim fatal (_("unsupported menu version %d"), (int) version); 26438889Sjdp 26538889Sjdp return r; 26638889Sjdp} 26738889Sjdp 26838889Sjdp/* Convert menu items from binary. */ 26938889Sjdp 270218822Sdimstatic rc_menuitem * 271218822Sdimbin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, 272218822Sdim rc_uint_type *read) 27338889Sjdp{ 274218822Sdim rc_menuitem *first, **pp; 27538889Sjdp 27638889Sjdp first = NULL; 27738889Sjdp pp = &first; 27838889Sjdp 27938889Sjdp *read = 0; 28038889Sjdp 28138889Sjdp while (length > 0) 28238889Sjdp { 283218822Sdim rc_uint_type flags, slen, itemlen; 284218822Sdim rc_uint_type stroff; 285218822Sdim rc_menuitem *mi; 28638889Sjdp 28738889Sjdp if (length < 4) 28860484Sobrien toosmall (_("menuitem header")); 28938889Sjdp 290218822Sdim mi = (rc_menuitem *) res_alloc (sizeof *mi); 29138889Sjdp mi->state = 0; 29238889Sjdp mi->help = 0; 29338889Sjdp 294218822Sdim flags = windres_get_16 (wrbfd, data, 2); 29538889Sjdp mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU); 29638889Sjdp 29738889Sjdp if ((flags & MENUITEM_POPUP) == 0) 29838889Sjdp stroff = 4; 29938889Sjdp else 30038889Sjdp stroff = 2; 30138889Sjdp 30238889Sjdp if (length < stroff + 2) 30360484Sobrien toosmall (_("menuitem header")); 30438889Sjdp 305218822Sdim if (windres_get_16 (wrbfd, data + stroff, 2) == 0) 30638889Sjdp { 30738889Sjdp slen = 0; 30838889Sjdp mi->text = NULL; 30938889Sjdp } 31038889Sjdp else 311218822Sdim mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen); 31238889Sjdp 31338889Sjdp itemlen = stroff + slen * 2 + 2; 31438889Sjdp 31538889Sjdp if ((flags & MENUITEM_POPUP) == 0) 31638889Sjdp { 31738889Sjdp mi->popup = NULL; 318218822Sdim mi->id = windres_get_16 (wrbfd, data + 2, 2); 31938889Sjdp } 32038889Sjdp else 32138889Sjdp { 322218822Sdim rc_uint_type subread; 32338889Sjdp 32438889Sjdp mi->id = 0; 325218822Sdim mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen, 326218822Sdim &subread); 32738889Sjdp itemlen += subread; 32838889Sjdp } 32938889Sjdp 33038889Sjdp mi->next = NULL; 33138889Sjdp *pp = mi; 33238889Sjdp pp = &mi->next; 33338889Sjdp 33438889Sjdp data += itemlen; 33538889Sjdp length -= itemlen; 33638889Sjdp *read += itemlen; 33738889Sjdp 33838889Sjdp if ((flags & MENUITEM_ENDMENU) != 0) 33938889Sjdp return first; 34038889Sjdp } 34138889Sjdp 34238889Sjdp return first; 34338889Sjdp} 34438889Sjdp 34538889Sjdp/* Convert menuex items from binary. */ 34638889Sjdp 347218822Sdimstatic rc_menuitem * 348218822Sdimbin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, 349218822Sdim rc_uint_type *read) 35038889Sjdp{ 351218822Sdim rc_menuitem *first, **pp; 35238889Sjdp 35338889Sjdp first = NULL; 35438889Sjdp pp = &first; 35538889Sjdp 35638889Sjdp *read = 0; 35738889Sjdp 35838889Sjdp while (length > 0) 35938889Sjdp { 360218822Sdim rc_uint_type flags, slen; 361218822Sdim rc_uint_type itemlen; 362218822Sdim rc_menuitem *mi; 36338889Sjdp 364218822Sdim if (length < 16) 36560484Sobrien toosmall (_("menuitem header")); 36638889Sjdp 367218822Sdim mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem)); 368218822Sdim mi->type = windres_get_32 (wrbfd, data, 4); 369218822Sdim mi->state = windres_get_32 (wrbfd, data + 4, 4); 370218822Sdim mi->id = windres_get_32 (wrbfd, data + 8, 4); 37138889Sjdp 372218822Sdim flags = windres_get_16 (wrbfd, data + 12, 2); 37338889Sjdp 374218822Sdim if (windres_get_16 (wrbfd, data + 14, 2) == 0) 37538889Sjdp { 37638889Sjdp slen = 0; 37738889Sjdp mi->text = NULL; 37838889Sjdp } 37938889Sjdp else 380218822Sdim mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen); 38138889Sjdp 382218822Sdim itemlen = 14 + slen * 2 + 2; 38338889Sjdp itemlen = (itemlen + 3) &~ 3; 38438889Sjdp 38538889Sjdp if ((flags & 1) == 0) 38638889Sjdp { 38738889Sjdp mi->popup = NULL; 38838889Sjdp mi->help = 0; 38938889Sjdp } 39038889Sjdp else 39138889Sjdp { 392218822Sdim rc_uint_type subread; 39338889Sjdp 39438889Sjdp if (length < itemlen + 4) 39560484Sobrien toosmall (_("menuitem")); 396218822Sdim mi->help = windres_get_32 (wrbfd, data + itemlen, 4); 39738889Sjdp itemlen += 4; 39838889Sjdp 399218822Sdim mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen, 400218822Sdim length - itemlen, &subread); 40138889Sjdp itemlen += subread; 40238889Sjdp } 40338889Sjdp 40438889Sjdp mi->next = NULL; 40538889Sjdp *pp = mi; 40638889Sjdp pp = &mi->next; 40738889Sjdp 40838889Sjdp data += itemlen; 40938889Sjdp length -= itemlen; 41038889Sjdp *read += itemlen; 41138889Sjdp 41238889Sjdp if ((flags & 0x80) != 0) 41338889Sjdp return first; 41438889Sjdp } 41538889Sjdp 41638889Sjdp return first; 41738889Sjdp} 41838889Sjdp 41938889Sjdp/* Convert a dialog resource from binary. */ 42038889Sjdp 421218822Sdimstatic rc_res_resource * 422218822Sdimbin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 42338889Sjdp{ 424218822Sdim rc_uint_type signature; 425218822Sdim rc_dialog *d; 426218822Sdim rc_uint_type c, sublen, i; 427218822Sdim rc_uint_type off; 428218822Sdim rc_dialog_control **pp; 429218822Sdim rc_res_resource *r; 43038889Sjdp 43138889Sjdp if (length < 18) 43260484Sobrien toosmall (_("dialog header")); 43338889Sjdp 434218822Sdim d = (rc_dialog *) res_alloc (sizeof (rc_dialog)); 43538889Sjdp 436218822Sdim signature = windres_get_16 (wrbfd, data + 2, 2); 43799461Sobrien if (signature != 0xffff) 43838889Sjdp { 43938889Sjdp d->ex = NULL; 440218822Sdim d->style = windres_get_32 (wrbfd, data, 4); 441218822Sdim d->exstyle = windres_get_32 (wrbfd, data + 4, 4); 44238889Sjdp off = 8; 44338889Sjdp } 44438889Sjdp else 44538889Sjdp { 44699461Sobrien int version; 44738889Sjdp 448218822Sdim version = windres_get_16 (wrbfd, data, 2); 44999461Sobrien if (version != 1) 45099461Sobrien fatal (_("unexpected DIALOGEX version %d"), version); 45138889Sjdp 452218822Sdim d->ex = (rc_dialog_ex *) res_alloc (sizeof (rc_dialog_ex)); 453218822Sdim d->ex->help = windres_get_32 (wrbfd, data + 4, 4); 454218822Sdim d->exstyle = windres_get_32 (wrbfd, data + 8, 4); 455218822Sdim d->style = windres_get_32 (wrbfd, data + 12, 4); 45638889Sjdp off = 16; 45738889Sjdp } 45838889Sjdp 45938889Sjdp if (length < off + 10) 46060484Sobrien toosmall (_("dialog header")); 46138889Sjdp 462218822Sdim c = windres_get_16 (wrbfd, data + off, 2); 463218822Sdim d->x = windres_get_16 (wrbfd, data + off + 2, 2); 464218822Sdim d->y = windres_get_16 (wrbfd, data + off + 4, 2); 465218822Sdim d->width = windres_get_16 (wrbfd, data + off + 6, 2); 466218822Sdim d->height = windres_get_16 (wrbfd, data + off + 8, 2); 46738889Sjdp 46838889Sjdp off += 10; 46938889Sjdp 470218822Sdim sublen = get_resid (wrbfd, &d->menu, data + off, length - off); 47138889Sjdp off += sublen; 47238889Sjdp 473218822Sdim sublen = get_resid (wrbfd, &d->class, data + off, length - off); 47438889Sjdp off += sublen; 47538889Sjdp 476218822Sdim d->caption = get_unicode (wrbfd, data + off, length - off, &sublen); 47738889Sjdp off += sublen * 2 + 2; 478104834Sobrien if (sublen == 0) 47999461Sobrien d->caption = NULL; 48038889Sjdp 48138889Sjdp if ((d->style & DS_SETFONT) == 0) 48238889Sjdp { 48338889Sjdp d->pointsize = 0; 48438889Sjdp d->font = NULL; 48538889Sjdp if (d->ex != NULL) 48638889Sjdp { 48738889Sjdp d->ex->weight = 0; 48838889Sjdp d->ex->italic = 0; 48999461Sobrien d->ex->charset = 1; /* Default charset. */ 49038889Sjdp } 49138889Sjdp } 49238889Sjdp else 49338889Sjdp { 49438889Sjdp if (length < off + 2) 49560484Sobrien toosmall (_("dialog font point size")); 49638889Sjdp 497218822Sdim d->pointsize = windres_get_16 (wrbfd, data + off, 2); 49838889Sjdp off += 2; 49938889Sjdp 50038889Sjdp if (d->ex != NULL) 50138889Sjdp { 50238889Sjdp if (length < off + 4) 50360484Sobrien toosmall (_("dialogex font information")); 504218822Sdim d->ex->weight = windres_get_16 (wrbfd, data + off, 2); 505218822Sdim d->ex->italic = windres_get_8 (wrbfd, data + off + 2, 1); 506218822Sdim d->ex->charset = windres_get_8 (wrbfd, data + off + 3, 1); 50738889Sjdp off += 4; 50838889Sjdp } 50938889Sjdp 510218822Sdim d->font = get_unicode (wrbfd, data + off, length - off, &sublen); 51138889Sjdp off += sublen * 2 + 2; 51238889Sjdp } 51338889Sjdp 51438889Sjdp d->controls = NULL; 51538889Sjdp pp = &d->controls; 51638889Sjdp 51738889Sjdp for (i = 0; i < c; i++) 51838889Sjdp { 519218822Sdim rc_dialog_control *dc; 52038889Sjdp int datalen; 52138889Sjdp 52238889Sjdp off = (off + 3) &~ 3; 52338889Sjdp 524218822Sdim dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control)); 52538889Sjdp 52638889Sjdp if (d->ex == NULL) 52738889Sjdp { 52838889Sjdp if (length < off + 8) 52960484Sobrien toosmall (_("dialog control")); 53038889Sjdp 531218822Sdim dc->style = windres_get_32 (wrbfd, data + off, 4); 532218822Sdim dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4); 53338889Sjdp dc->help = 0; 53438889Sjdp off += 8; 53538889Sjdp } 53638889Sjdp else 53738889Sjdp { 53838889Sjdp if (length < off + 12) 53960484Sobrien toosmall (_("dialogex control")); 540218822Sdim dc->help = windres_get_32 (wrbfd, data + off, 4); 541218822Sdim dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4); 542218822Sdim dc->style = windres_get_32 (wrbfd, data + off + 8, 4); 54338889Sjdp off += 12; 54438889Sjdp } 54538889Sjdp 546218822Sdim if (length < off + (d->ex != NULL ? 2 : 0) + 10) 54760484Sobrien toosmall (_("dialog control")); 54838889Sjdp 549218822Sdim dc->x = windres_get_16 (wrbfd, data + off, 2); 550218822Sdim dc->y = windres_get_16 (wrbfd, data + off + 2, 2); 551218822Sdim dc->width = windres_get_16 (wrbfd, data + off + 4, 2); 552218822Sdim dc->height = windres_get_16 (wrbfd, data + off + 6, 2); 55338889Sjdp 55460484Sobrien if (d->ex != NULL) 555218822Sdim dc->id = windres_get_32 (wrbfd, data + off + 8, 4); 55660484Sobrien else 557218822Sdim dc->id = windres_get_16 (wrbfd, data + off + 8, 2); 55838889Sjdp 55960484Sobrien off += 10 + (d->ex != NULL ? 2 : 0); 56060484Sobrien 561218822Sdim sublen = get_resid (wrbfd, &dc->class, data + off, length - off); 56238889Sjdp off += sublen; 56338889Sjdp 564218822Sdim sublen = get_resid (wrbfd, &dc->text, data + off, length - off); 56538889Sjdp off += sublen; 56638889Sjdp 56738889Sjdp if (length < off + 2) 56860484Sobrien toosmall (_("dialog control end")); 56938889Sjdp 570218822Sdim datalen = windres_get_16 (wrbfd, data + off, 2); 57138889Sjdp off += 2; 57238889Sjdp 57338889Sjdp if (datalen == 0) 57438889Sjdp dc->data = NULL; 57538889Sjdp else 57638889Sjdp { 57738889Sjdp off = (off + 3) &~ 3; 57838889Sjdp 57938889Sjdp if (length < off + datalen) 58060484Sobrien toosmall (_("dialog control data")); 58138889Sjdp 582218822Sdim dc->data = ((rc_rcdata_item *) 583218822Sdim res_alloc (sizeof (rc_rcdata_item))); 58438889Sjdp dc->data->next = NULL; 58538889Sjdp dc->data->type = RCDATA_BUFFER; 58638889Sjdp dc->data->u.buffer.length = datalen; 58738889Sjdp dc->data->u.buffer.data = data + off; 58838889Sjdp 589104834Sobrien off += datalen; 59038889Sjdp } 59138889Sjdp 59238889Sjdp dc->next = NULL; 59338889Sjdp *pp = dc; 59438889Sjdp pp = &dc->next; 59538889Sjdp } 59638889Sjdp 597218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 59838889Sjdp r->type = RES_TYPE_DIALOG; 59938889Sjdp r->u.dialog = d; 60038889Sjdp 60138889Sjdp return r; 60238889Sjdp} 60338889Sjdp 60438889Sjdp/* Convert a stringtable resource from binary. */ 60538889Sjdp 606218822Sdimstatic rc_res_resource * 607218822Sdimbin_to_res_string (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 60838889Sjdp{ 609218822Sdim rc_stringtable *st; 61038889Sjdp int i; 611218822Sdim rc_res_resource *r; 61238889Sjdp 613218822Sdim st = (rc_stringtable *) res_alloc (sizeof (rc_stringtable)); 61438889Sjdp 61538889Sjdp for (i = 0; i < 16; i++) 61638889Sjdp { 61760484Sobrien unsigned int slen; 61838889Sjdp 61938889Sjdp if (length < 2) 62060484Sobrien toosmall (_("stringtable string length")); 621218822Sdim slen = windres_get_16 (wrbfd, data, 2); 62238889Sjdp st->strings[i].length = slen; 62338889Sjdp 62438889Sjdp if (slen > 0) 62538889Sjdp { 62638889Sjdp unichar *s; 62760484Sobrien unsigned int j; 62838889Sjdp 62938889Sjdp if (length < 2 + 2 * slen) 63060484Sobrien toosmall (_("stringtable string")); 63138889Sjdp 63238889Sjdp s = (unichar *) res_alloc (slen * sizeof (unichar)); 63338889Sjdp st->strings[i].string = s; 63438889Sjdp 63538889Sjdp for (j = 0; j < slen; j++) 636218822Sdim s[j] = windres_get_16 (wrbfd, data + 2 + j * 2, 2); 63738889Sjdp } 63838889Sjdp 63938889Sjdp data += 2 + 2 * slen; 64038889Sjdp length -= 2 + 2 * slen; 64138889Sjdp } 64238889Sjdp 643218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 64438889Sjdp r->type = RES_TYPE_STRINGTABLE; 64538889Sjdp r->u.stringtable = st; 64638889Sjdp 64738889Sjdp return r; 64838889Sjdp} 64938889Sjdp 65038889Sjdp/* Convert a fontdir resource from binary. */ 65138889Sjdp 652218822Sdimstatic rc_res_resource * 653218822Sdimbin_to_res_fontdir (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 65438889Sjdp{ 655218822Sdim rc_uint_type c, i; 656218822Sdim rc_fontdir *first, **pp; 657218822Sdim rc_res_resource *r; 65838889Sjdp 65938889Sjdp if (length < 2) 66060484Sobrien toosmall (_("fontdir header")); 66138889Sjdp 662218822Sdim c = windres_get_16 (wrbfd, data, 2); 66338889Sjdp 66438889Sjdp first = NULL; 66538889Sjdp pp = &first; 66638889Sjdp 66738889Sjdp for (i = 0; i < c; i++) 66838889Sjdp { 669218822Sdim const struct bin_fontdir_item *bfi; 670218822Sdim rc_fontdir *fd; 67160484Sobrien unsigned int off; 67238889Sjdp 67338889Sjdp if (length < 56) 67460484Sobrien toosmall (_("fontdir")); 67538889Sjdp 676218822Sdim bfi = (const struct bin_fontdir_item *) data; 677218822Sdim fd = (rc_fontdir *) res_alloc (sizeof *fd); 678218822Sdim fd->index = windres_get_16 (wrbfd, bfi->index, 2); 67938889Sjdp 68038889Sjdp /* To work out the length of the fontdir data, we must get the 68138889Sjdp length of the device name and face name strings, even though 682218822Sdim we don't store them in the rc_fontdir. The 68338889Sjdp documentation says that these are NULL terminated char 68438889Sjdp strings, not Unicode strings. */ 68538889Sjdp 68638889Sjdp off = 56; 68738889Sjdp 68838889Sjdp while (off < length && data[off] != '\0') 68938889Sjdp ++off; 69038889Sjdp if (off >= length) 69160484Sobrien toosmall (_("fontdir device name")); 69238889Sjdp ++off; 69338889Sjdp 69438889Sjdp while (off < length && data[off] != '\0') 69538889Sjdp ++off; 69638889Sjdp if (off >= length) 69760484Sobrien toosmall (_("fontdir face name")); 69838889Sjdp ++off; 69938889Sjdp 70038889Sjdp fd->length = off; 70138889Sjdp fd->data = data; 70238889Sjdp 70338889Sjdp fd->next = NULL; 70438889Sjdp *pp = fd; 70538889Sjdp pp = &fd->next; 70638889Sjdp 70738889Sjdp /* The documentation does not indicate that any rounding is 70838889Sjdp required. */ 70938889Sjdp 71038889Sjdp data += off; 71138889Sjdp length -= off; 71238889Sjdp } 71338889Sjdp 714218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 71538889Sjdp r->type = RES_TYPE_FONTDIR; 71638889Sjdp r->u.fontdir = first; 71738889Sjdp 71838889Sjdp return r; 71938889Sjdp} 72038889Sjdp 72138889Sjdp/* Convert an accelerators resource from binary. */ 72238889Sjdp 723218822Sdimstatic rc_res_resource * 724218822Sdimbin_to_res_accelerators (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 72538889Sjdp{ 726218822Sdim rc_accelerator *first, **pp; 727218822Sdim rc_res_resource *r; 72838889Sjdp 72938889Sjdp first = NULL; 73038889Sjdp pp = &first; 73138889Sjdp 73238889Sjdp while (1) 73338889Sjdp { 734218822Sdim rc_accelerator *a; 73538889Sjdp 73638889Sjdp if (length < 8) 73760484Sobrien toosmall (_("accelerator")); 73838889Sjdp 739218822Sdim a = (rc_accelerator *) res_alloc (sizeof (rc_accelerator)); 74038889Sjdp 741218822Sdim a->flags = windres_get_16 (wrbfd, data, 2); 742218822Sdim a->key = windres_get_16 (wrbfd, data + 2, 2); 743218822Sdim a->id = windres_get_16 (wrbfd, data + 4, 2); 74438889Sjdp 74538889Sjdp a->next = NULL; 74638889Sjdp *pp = a; 74738889Sjdp pp = &a->next; 74838889Sjdp 74938889Sjdp if ((a->flags & ACC_LAST) != 0) 75038889Sjdp break; 75138889Sjdp 75238889Sjdp data += 8; 75338889Sjdp length -= 8; 75438889Sjdp } 75538889Sjdp 756218822Sdim r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); 75738889Sjdp r->type = RES_TYPE_ACCELERATOR; 75838889Sjdp r->u.acc = first; 75938889Sjdp 76038889Sjdp return r; 76138889Sjdp} 76238889Sjdp 76338889Sjdp/* Convert an rcdata resource from binary. */ 76438889Sjdp 765218822Sdimstatic rc_res_resource * 766218822Sdimbin_to_res_rcdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, 767218822Sdim rc_uint_type length, int rctyp) 76838889Sjdp{ 769218822Sdim rc_rcdata_item *ri; 770218822Sdim rc_res_resource *r; 77138889Sjdp 772218822Sdim ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); 77338889Sjdp 77438889Sjdp ri->next = NULL; 77538889Sjdp ri->type = RCDATA_BUFFER; 77638889Sjdp ri->u.buffer.length = length; 77738889Sjdp ri->u.buffer.data = data; 77838889Sjdp 779218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 780218822Sdim r->type = rctyp; 78138889Sjdp r->u.rcdata = ri; 78238889Sjdp 78338889Sjdp return r; 78438889Sjdp} 78538889Sjdp 78638889Sjdp/* Convert a group cursor resource from binary. */ 78738889Sjdp 788218822Sdimstatic rc_res_resource * 789218822Sdimbin_to_res_group_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 79038889Sjdp{ 79138889Sjdp int type, c, i; 792218822Sdim rc_group_cursor *first, **pp; 793218822Sdim rc_res_resource *r; 79438889Sjdp 79538889Sjdp if (length < 6) 79660484Sobrien toosmall (_("group cursor header")); 79738889Sjdp 798218822Sdim type = windres_get_16 (wrbfd, data + 2, 2); 79938889Sjdp if (type != 2) 80060484Sobrien fatal (_("unexpected group cursor type %d"), type); 80138889Sjdp 802218822Sdim c = windres_get_16 (wrbfd, data + 4, 2); 80338889Sjdp 80438889Sjdp data += 6; 80538889Sjdp length -= 6; 80638889Sjdp 80738889Sjdp first = NULL; 80838889Sjdp pp = &first; 80938889Sjdp 81038889Sjdp for (i = 0; i < c; i++) 81138889Sjdp { 812218822Sdim rc_group_cursor *gc; 81338889Sjdp 81438889Sjdp if (length < 14) 81560484Sobrien toosmall (_("group cursor")); 81638889Sjdp 817218822Sdim gc = (rc_group_cursor *) res_alloc (sizeof *gc); 81838889Sjdp 819218822Sdim gc->width = windres_get_16 (wrbfd, data, 2); 820218822Sdim gc->height = windres_get_16 (wrbfd, data + 2, 2); 821218822Sdim gc->planes = windres_get_16 (wrbfd, data + 4, 2); 822218822Sdim gc->bits = windres_get_16 (wrbfd, data + 6, 2); 823218822Sdim gc->bytes = windres_get_32 (wrbfd, data + 8, 4); 824218822Sdim gc->index = windres_get_16 (wrbfd, data + 12, 2); 82538889Sjdp 82638889Sjdp gc->next = NULL; 82738889Sjdp *pp = gc; 82838889Sjdp pp = &gc->next; 82938889Sjdp 83038889Sjdp data += 14; 83138889Sjdp length -= 14; 83238889Sjdp } 83338889Sjdp 834218822Sdim r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource)); 83538889Sjdp r->type = RES_TYPE_GROUP_CURSOR; 83638889Sjdp r->u.group_cursor = first; 83738889Sjdp 83838889Sjdp return r; 83938889Sjdp} 84038889Sjdp 84138889Sjdp/* Convert a group icon resource from binary. */ 84238889Sjdp 843218822Sdimstatic rc_res_resource * 844218822Sdimbin_to_res_group_icon (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 84538889Sjdp{ 84638889Sjdp int type, c, i; 847218822Sdim rc_group_icon *first, **pp; 848218822Sdim rc_res_resource *r; 84938889Sjdp 85038889Sjdp if (length < 6) 85160484Sobrien toosmall (_("group icon header")); 85238889Sjdp 853218822Sdim type = windres_get_16 (wrbfd, data + 2, 2); 85438889Sjdp if (type != 1) 85560484Sobrien fatal (_("unexpected group icon type %d"), type); 85638889Sjdp 857218822Sdim c = windres_get_16 (wrbfd, data + 4, 2); 85838889Sjdp 85938889Sjdp data += 6; 86038889Sjdp length -= 6; 86138889Sjdp 86238889Sjdp first = NULL; 86338889Sjdp pp = &first; 86438889Sjdp 86538889Sjdp for (i = 0; i < c; i++) 86638889Sjdp { 867218822Sdim rc_group_icon *gi; 86838889Sjdp 86938889Sjdp if (length < 14) 87060484Sobrien toosmall (_("group icon")); 87138889Sjdp 872218822Sdim gi = (rc_group_icon *) res_alloc (sizeof (rc_group_icon)); 87338889Sjdp 874218822Sdim gi->width = windres_get_8 (wrbfd, data, 1); 875218822Sdim gi->height = windres_get_8 (wrbfd, data + 1, 1); 876218822Sdim gi->colors = windres_get_8 (wrbfd, data + 2, 1); 877218822Sdim gi->planes = windres_get_16 (wrbfd, data + 4, 2); 878218822Sdim gi->bits = windres_get_16 (wrbfd, data + 6, 2); 879218822Sdim gi->bytes = windres_get_32 (wrbfd, data + 8, 4); 880218822Sdim gi->index = windres_get_16 (wrbfd, data + 12, 2); 88138889Sjdp 88238889Sjdp gi->next = NULL; 88338889Sjdp *pp = gi; 88438889Sjdp pp = &gi->next; 88538889Sjdp 88638889Sjdp data += 14; 88738889Sjdp length -= 14; 88838889Sjdp } 88938889Sjdp 890218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 89138889Sjdp r->type = RES_TYPE_GROUP_ICON; 89238889Sjdp r->u.group_icon = first; 89338889Sjdp 89438889Sjdp return r; 89538889Sjdp} 89638889Sjdp 89738889Sjdp/* Extract data from a version header. If KEY is not NULL, then the 89838889Sjdp key must be KEY; otherwise, the key is returned in *PKEY. This 89938889Sjdp sets *LEN to the total length, *VALLEN to the value length, *TYPE 90038889Sjdp to the type, and *OFF to the offset to the children. */ 90138889Sjdp 90238889Sjdpstatic void 903218822Sdimget_version_header (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length, 904218822Sdim const char *key, unichar **pkey, 905218822Sdim rc_uint_type *len, rc_uint_type *vallen, rc_uint_type *type, 906218822Sdim rc_uint_type *off) 90738889Sjdp{ 90838889Sjdp if (length < 8) 90938889Sjdp toosmall (key); 91038889Sjdp 911218822Sdim *len = windres_get_16 (wrbfd, data, 2); 912218822Sdim *vallen = windres_get_16 (wrbfd, data + 2, 2); 913218822Sdim *type = windres_get_16 (wrbfd, data + 4, 2); 91438889Sjdp 91538889Sjdp *off = 6; 91638889Sjdp 91738889Sjdp length -= 6; 91838889Sjdp data += 6; 91938889Sjdp 92038889Sjdp if (key == NULL) 92138889Sjdp { 922218822Sdim rc_uint_type sublen; 92338889Sjdp 924218822Sdim *pkey = get_unicode (wrbfd, data, length, &sublen); 925218822Sdim *off += (sublen + 1) * sizeof (unichar); 92638889Sjdp } 92738889Sjdp else 92838889Sjdp { 92938889Sjdp while (1) 93038889Sjdp { 93138889Sjdp if (length < 2) 93238889Sjdp toosmall (key); 933218822Sdim if (windres_get_16 (wrbfd, data, 2) != (bfd_byte) *key) 93460484Sobrien fatal (_("unexpected version string")); 93538889Sjdp 93638889Sjdp *off += 2; 93738889Sjdp length -= 2; 93838889Sjdp data += 2; 93938889Sjdp 94038889Sjdp if (*key == '\0') 94138889Sjdp break; 94238889Sjdp 94338889Sjdp ++key; 94438889Sjdp } 94538889Sjdp } 94638889Sjdp 94738889Sjdp *off = (*off + 3) &~ 3; 94838889Sjdp} 94938889Sjdp 95038889Sjdp/* Convert a version resource from binary. */ 95138889Sjdp 952218822Sdimstatic rc_res_resource * 953218822Sdimbin_to_res_version (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 95438889Sjdp{ 955218822Sdim rc_uint_type verlen, vallen, type, off; 956218822Sdim rc_fixed_versioninfo *fi; 957218822Sdim rc_ver_info *first, **pp; 958218822Sdim rc_versioninfo *v; 959218822Sdim rc_res_resource *r; 96038889Sjdp 961218822Sdim get_version_header (wrbfd, data, length, "VS_VERSION_INFO", 96299461Sobrien (unichar **) NULL, &verlen, &vallen, &type, &off); 96338889Sjdp 96460484Sobrien if ((unsigned int) verlen != length) 96560484Sobrien fatal (_("version length %d does not match resource length %lu"), 966218822Sdim (int) verlen, (unsigned long) length); 96738889Sjdp 96838889Sjdp if (type != 0) 969218822Sdim fatal (_("unexpected version type %d"), (int) type); 97038889Sjdp 97138889Sjdp data += off; 97238889Sjdp length -= off; 97338889Sjdp 97438889Sjdp if (vallen == 0) 97538889Sjdp fi = NULL; 97638889Sjdp else 97738889Sjdp { 97838889Sjdp unsigned long signature, fiv; 97938889Sjdp 98038889Sjdp if (vallen != 52) 981218822Sdim fatal (_("unexpected fixed version information length %ld"), (long) vallen); 98238889Sjdp 98338889Sjdp if (length < 52) 98460484Sobrien toosmall (_("fixed version info")); 98538889Sjdp 986218822Sdim signature = windres_get_32 (wrbfd, data, 4); 98738889Sjdp if (signature != 0xfeef04bd) 98860484Sobrien fatal (_("unexpected fixed version signature %lu"), signature); 98938889Sjdp 990218822Sdim fiv = windres_get_32 (wrbfd, data + 4, 4); 99138889Sjdp if (fiv != 0 && fiv != 0x10000) 99260484Sobrien fatal (_("unexpected fixed version info version %lu"), fiv); 99338889Sjdp 994218822Sdim fi = (rc_fixed_versioninfo *) res_alloc (sizeof (rc_fixed_versioninfo)); 99538889Sjdp 996218822Sdim fi->file_version_ms = windres_get_32 (wrbfd, data + 8, 4); 997218822Sdim fi->file_version_ls = windres_get_32 (wrbfd, data + 12, 4); 998218822Sdim fi->product_version_ms = windres_get_32 (wrbfd, data + 16, 4); 999218822Sdim fi->product_version_ls = windres_get_32 (wrbfd, data + 20, 4); 1000218822Sdim fi->file_flags_mask = windres_get_32 (wrbfd, data + 24, 4); 1001218822Sdim fi->file_flags = windres_get_32 (wrbfd, data + 28, 4); 1002218822Sdim fi->file_os = windres_get_32 (wrbfd, data + 32, 4); 1003218822Sdim fi->file_type = windres_get_32 (wrbfd, data + 36, 4); 1004218822Sdim fi->file_subtype = windres_get_32 (wrbfd, data + 40, 4); 1005218822Sdim fi->file_date_ms = windres_get_32 (wrbfd, data + 44, 4); 1006218822Sdim fi->file_date_ls = windres_get_32 (wrbfd, data + 48, 4); 100738889Sjdp 100838889Sjdp data += 52; 100938889Sjdp length -= 52; 101038889Sjdp } 101138889Sjdp 101238889Sjdp first = NULL; 101338889Sjdp pp = &first; 101438889Sjdp 101538889Sjdp while (length > 0) 101638889Sjdp { 1017218822Sdim rc_ver_info *vi; 101838889Sjdp int ch; 101938889Sjdp 102038889Sjdp if (length < 8) 102160484Sobrien toosmall (_("version var info")); 102238889Sjdp 1023218822Sdim vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info)); 102438889Sjdp 1025218822Sdim ch = windres_get_16 (wrbfd, data + 6, 2); 102638889Sjdp 102738889Sjdp if (ch == 'S') 102838889Sjdp { 1029218822Sdim rc_ver_stringinfo **ppvs; 103038889Sjdp 103138889Sjdp vi->type = VERINFO_STRING; 103238889Sjdp 1033218822Sdim get_version_header (wrbfd, data, length, "StringFileInfo", 103499461Sobrien (unichar **) NULL, &verlen, &vallen, &type, 103538889Sjdp &off); 103638889Sjdp 103738889Sjdp if (vallen != 0) 1038218822Sdim fatal (_("unexpected stringfileinfo value length %ld"), (long) vallen); 103938889Sjdp 104038889Sjdp data += off; 104138889Sjdp length -= off; 104238889Sjdp 1043218822Sdim get_version_header (wrbfd, data, length, (const char *) NULL, 104438889Sjdp &vi->u.string.language, &verlen, &vallen, 104538889Sjdp &type, &off); 104638889Sjdp 104738889Sjdp if (vallen != 0) 1048218822Sdim fatal (_("unexpected version stringtable value length %ld"), (long) vallen); 104938889Sjdp 105038889Sjdp data += off; 105138889Sjdp length -= off; 105238889Sjdp verlen -= off; 105338889Sjdp 105438889Sjdp vi->u.string.strings = NULL; 105538889Sjdp ppvs = &vi->u.string.strings; 105638889Sjdp 105738889Sjdp /* It's convenient to round verlen to a 4 byte alignment, 105838889Sjdp since we round the subvariables in the loop. */ 105938889Sjdp verlen = (verlen + 3) &~ 3; 106038889Sjdp 106138889Sjdp while (verlen > 0) 106238889Sjdp { 1063218822Sdim rc_ver_stringinfo *vs; 1064218822Sdim rc_uint_type subverlen, vslen, valoff; 106538889Sjdp 1066218822Sdim vs = (rc_ver_stringinfo *) res_alloc (sizeof *vs); 106738889Sjdp 1068218822Sdim get_version_header (wrbfd, data, length, 106938889Sjdp (const char *) NULL, &vs->key, &subverlen, 107038889Sjdp &vallen, &type, &off); 107138889Sjdp 107238889Sjdp subverlen = (subverlen + 3) &~ 3; 107338889Sjdp 107438889Sjdp data += off; 107538889Sjdp length -= off; 107638889Sjdp 1077218822Sdim vs->value = get_unicode (wrbfd, data, length, &vslen); 107838889Sjdp valoff = vslen * 2 + 2; 107938889Sjdp valoff = (valoff + 3) &~ 3; 108038889Sjdp 108138889Sjdp if (off + valoff != subverlen) 1082218822Sdim fatal (_("unexpected version string length %ld != %ld + %ld"), 1083218822Sdim (long) subverlen, (long) off, (long) valoff); 108438889Sjdp 108538889Sjdp vs->next = NULL; 108638889Sjdp *ppvs = vs; 108738889Sjdp ppvs = &vs->next; 108838889Sjdp 108938889Sjdp data += valoff; 109038889Sjdp length -= valoff; 109138889Sjdp 109238889Sjdp if (verlen < subverlen) 1093218822Sdim fatal (_("unexpected version string length %ld < %ld"), 1094218822Sdim (long) verlen, (long) subverlen); 109538889Sjdp 109638889Sjdp verlen -= subverlen; 109738889Sjdp } 109838889Sjdp } 109938889Sjdp else if (ch == 'V') 110038889Sjdp { 1101218822Sdim rc_ver_varinfo **ppvv; 110238889Sjdp 110338889Sjdp vi->type = VERINFO_VAR; 110438889Sjdp 1105218822Sdim get_version_header (wrbfd, data, length, "VarFileInfo", 110699461Sobrien (unichar **) NULL, &verlen, &vallen, &type, 110738889Sjdp &off); 110838889Sjdp 110938889Sjdp if (vallen != 0) 1110218822Sdim fatal (_("unexpected varfileinfo value length %ld"), (long) vallen); 111138889Sjdp 111238889Sjdp data += off; 111338889Sjdp length -= off; 111438889Sjdp 1115218822Sdim get_version_header (wrbfd, data, length, (const char *) NULL, 111638889Sjdp &vi->u.var.key, &verlen, &vallen, &type, &off); 111738889Sjdp 111838889Sjdp data += off; 111938889Sjdp length -= off; 112038889Sjdp 112138889Sjdp vi->u.var.var = NULL; 112238889Sjdp ppvv = &vi->u.var.var; 112338889Sjdp 112438889Sjdp while (vallen > 0) 112538889Sjdp { 1126218822Sdim rc_ver_varinfo *vv; 112738889Sjdp 112838889Sjdp if (length < 4) 112960484Sobrien toosmall (_("version varfileinfo")); 113038889Sjdp 1131218822Sdim vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo)); 113238889Sjdp 1133218822Sdim vv->language = windres_get_16 (wrbfd, data, 2); 1134218822Sdim vv->charset = windres_get_16 (wrbfd, data + 2, 2); 113538889Sjdp 113638889Sjdp vv->next = NULL; 113738889Sjdp *ppvv = vv; 113838889Sjdp ppvv = &vv->next; 113938889Sjdp 114038889Sjdp data += 4; 114138889Sjdp length -= 4; 114238889Sjdp 114338889Sjdp if (vallen < 4) 1144218822Sdim fatal (_("unexpected version value length %ld"), (long) vallen); 114538889Sjdp 114638889Sjdp vallen -= 4; 114738889Sjdp } 114838889Sjdp } 114938889Sjdp else 115060484Sobrien fatal (_("unexpected version string")); 115138889Sjdp 115238889Sjdp vi->next = NULL; 115338889Sjdp *pp = vi; 1154104834Sobrien pp = &vi->next; 115538889Sjdp } 115638889Sjdp 1157218822Sdim v = (rc_versioninfo *) res_alloc (sizeof (rc_versioninfo)); 115838889Sjdp v->fixed = fi; 115938889Sjdp v->var = first; 116038889Sjdp 1161218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 116238889Sjdp r->type = RES_TYPE_VERSIONINFO; 116338889Sjdp r->u.versioninfo = v; 116438889Sjdp 1165104834Sobrien return r; 116638889Sjdp} 116738889Sjdp 116838889Sjdp/* Convert an arbitrary user defined resource from binary. */ 116938889Sjdp 1170218822Sdimstatic rc_res_resource * 1171218822Sdimbin_to_res_userdata (windres_bfd *wrbfd ATTRIBUTE_UNUSED, const bfd_byte *data, 1172218822Sdim rc_uint_type length) 117338889Sjdp{ 1174218822Sdim rc_rcdata_item *ri; 1175218822Sdim rc_res_resource *r; 117638889Sjdp 1177218822Sdim ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item)); 117838889Sjdp 117938889Sjdp ri->next = NULL; 118038889Sjdp ri->type = RCDATA_BUFFER; 118138889Sjdp ri->u.buffer.length = length; 118238889Sjdp ri->u.buffer.data = data; 118338889Sjdp 1184218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 118538889Sjdp r->type = RES_TYPE_USERDATA; 118638889Sjdp r->u.rcdata = ri; 118738889Sjdp 118838889Sjdp return r; 118938889Sjdp} 119038889Sjdp 1191218822Sdimstatic rc_res_resource * 1192218822Sdimbin_to_res_toolbar (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length) 1193218822Sdim{ 1194218822Sdim rc_toolbar *ri; 1195218822Sdim rc_res_resource *r; 1196218822Sdim rc_uint_type i; 119738889Sjdp 1198218822Sdim ri = (rc_toolbar *) res_alloc (sizeof (rc_toolbar)); 1199218822Sdim ri->button_width = windres_get_32 (wrbfd, data, 4); 1200218822Sdim ri->button_height = windres_get_32 (wrbfd, data + 4, 4); 1201218822Sdim ri->nitems = windres_get_32 (wrbfd, data + 8, 4); 1202218822Sdim ri->items = NULL; 120338889Sjdp 1204218822Sdim data += 12; 1205218822Sdim length -= 12; 1206218822Sdim for (i=0 ; i < ri->nitems; i++) 1207218822Sdim { 1208218822Sdim rc_toolbar_item *it; 1209218822Sdim it = (rc_toolbar_item *) res_alloc (sizeof (rc_toolbar_item)); 1210218822Sdim it->id.named = 0; 1211218822Sdim it->id.u.id = (int) windres_get_32 (wrbfd, data, 4); 1212218822Sdim it->prev = it->next = NULL; 1213218822Sdim data += 4; 1214218822Sdim length -= 4; 1215218822Sdim if(ri->items) { 1216218822Sdim rc_toolbar_item *ii = ri->items; 1217218822Sdim while (ii->next != NULL) 1218218822Sdim ii = ii->next; 1219218822Sdim it->prev = ii; 1220218822Sdim ii->next = it; 1221218822Sdim } 1222218822Sdim else 1223218822Sdim ri->items = it; 1224218822Sdim } 1225218822Sdim r = (rc_res_resource *) res_alloc (sizeof *r); 1226218822Sdim r->type = RES_TYPE_TOOLBAR; 1227218822Sdim r->u.toolbar = ri; 1228218822Sdim return r; 1229218822Sdim} 1230218822Sdim 1231218822Sdim 123238889Sjdp/* Local functions used to convert resources to binary format. */ 123338889Sjdp 1234218822Sdimstatic rc_uint_type resid_to_bin (windres_bfd *, rc_uint_type, rc_res_id); 1235218822Sdimstatic rc_uint_type unicode_to_bin (windres_bfd *, rc_uint_type, const unichar *); 1236218822Sdimstatic rc_uint_type res_to_bin_accelerator (windres_bfd *, rc_uint_type, const rc_accelerator *); 1237218822Sdimstatic rc_uint_type res_to_bin_cursor (windres_bfd *, rc_uint_type, const rc_cursor *); 1238218822Sdimstatic rc_uint_type res_to_bin_group_cursor (windres_bfd *, rc_uint_type, const rc_group_cursor *); 1239218822Sdimstatic rc_uint_type res_to_bin_dialog (windres_bfd *, rc_uint_type, const rc_dialog *); 1240218822Sdimstatic rc_uint_type res_to_bin_fontdir (windres_bfd *, rc_uint_type, const rc_fontdir *); 1241218822Sdimstatic rc_uint_type res_to_bin_group_icon (windres_bfd *, rc_uint_type, const rc_group_icon *); 1242218822Sdimstatic rc_uint_type res_to_bin_menu (windres_bfd *, rc_uint_type, const rc_menu *); 1243218822Sdimstatic rc_uint_type res_to_bin_menuitems (windres_bfd *, rc_uint_type, const rc_menuitem *); 1244218822Sdimstatic rc_uint_type res_to_bin_menuexitems (windres_bfd *, rc_uint_type, const rc_menuitem *); 1245218822Sdimstatic rc_uint_type res_to_bin_rcdata (windres_bfd *, rc_uint_type, const rc_rcdata_item *); 1246218822Sdimstatic rc_uint_type res_to_bin_stringtable (windres_bfd *, rc_uint_type, const rc_stringtable *); 1247218822Sdimstatic rc_uint_type string_to_unicode_bin (windres_bfd *, rc_uint_type, const char *); 1248218822Sdimstatic rc_uint_type res_to_bin_toolbar (windres_bfd *, rc_uint_type, rc_toolbar *tb); 1249218822Sdimstatic rc_uint_type res_to_bin_versioninfo (windres_bfd *, rc_uint_type, const rc_versioninfo *); 1250218822Sdimstatic rc_uint_type res_to_bin_generic (windres_bfd *, rc_uint_type, rc_uint_type, 1251218822Sdim const bfd_byte *); 125238889Sjdp 125338889Sjdp/* Convert a resource to binary. */ 125438889Sjdp 1255218822Sdimrc_uint_type 1256218822Sdimres_to_bin (windres_bfd *wrbfd, rc_uint_type off, const rc_res_resource *res) 125738889Sjdp{ 125838889Sjdp switch (res->type) 125938889Sjdp { 126038889Sjdp case RES_TYPE_BITMAP: 126138889Sjdp case RES_TYPE_FONT: 126238889Sjdp case RES_TYPE_ICON: 126338889Sjdp case RES_TYPE_MESSAGETABLE: 1264218822Sdim return res_to_bin_generic (wrbfd, off, res->u.data.length, res->u.data.data); 126538889Sjdp case RES_TYPE_ACCELERATOR: 1266218822Sdim return res_to_bin_accelerator (wrbfd, off, res->u.acc); 126738889Sjdp case RES_TYPE_CURSOR: 1268218822Sdim return res_to_bin_cursor (wrbfd, off, res->u.cursor); 126938889Sjdp case RES_TYPE_GROUP_CURSOR: 1270218822Sdim return res_to_bin_group_cursor (wrbfd, off, res->u.group_cursor); 127138889Sjdp case RES_TYPE_DIALOG: 1272218822Sdim return res_to_bin_dialog (wrbfd, off, res->u.dialog); 127338889Sjdp case RES_TYPE_FONTDIR: 1274218822Sdim return res_to_bin_fontdir (wrbfd, off, res->u.fontdir); 127538889Sjdp case RES_TYPE_GROUP_ICON: 1276218822Sdim return res_to_bin_group_icon (wrbfd, off, res->u.group_icon); 127738889Sjdp case RES_TYPE_MENU: 1278218822Sdim return res_to_bin_menu (wrbfd, off, res->u.menu); 127938889Sjdp case RES_TYPE_STRINGTABLE: 1280218822Sdim return res_to_bin_stringtable (wrbfd, off, res->u.stringtable); 1281218822Sdim case RES_TYPE_VERSIONINFO: 1282218822Sdim return res_to_bin_versioninfo (wrbfd, off, res->u.versioninfo); 1283218822Sdim case RES_TYPE_TOOLBAR: 1284218822Sdim return res_to_bin_toolbar (wrbfd, off, res->u.toolbar); 128538889Sjdp case RES_TYPE_USERDATA: 1286218822Sdim case RES_TYPE_RCDATA: 1287218822Sdim default: 1288218822Sdim return res_to_bin_rcdata (wrbfd, off, res->u.rcdata); 128938889Sjdp } 129038889Sjdp} 129138889Sjdp 129238889Sjdp/* Convert a resource ID to binary. This always returns exactly one 129338889Sjdp bindata structure. */ 129438889Sjdp 1295218822Sdimstatic rc_uint_type 1296218822Sdimresid_to_bin (windres_bfd *wrbfd, rc_uint_type off, rc_res_id id) 129738889Sjdp{ 129838889Sjdp if (! id.named) 129938889Sjdp { 1300218822Sdim if (wrbfd) 1301218822Sdim { 1302218822Sdim struct bin_res_id bri; 1303218822Sdim 1304218822Sdim windres_put_16 (wrbfd, bri.sig, 0xffff); 1305218822Sdim windres_put_16 (wrbfd, bri.id, id.u.id); 1306218822Sdim set_windres_bfd_content (wrbfd, &bri, off, BIN_RES_ID); 1307218822Sdim } 1308218822Sdim off += BIN_RES_ID; 130938889Sjdp } 131038889Sjdp else 131138889Sjdp { 1312218822Sdim rc_uint_type len = (id.u.n.name ? unichar_len (id.u.n.name) : 0); 1313218822Sdim if (wrbfd) 1314218822Sdim { 1315218822Sdim bfd_byte *d = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); 1316218822Sdim rc_uint_type i; 1317218822Sdim for (i = 0; i < len; i++) 1318218822Sdim windres_put_16 (wrbfd, d + (i * sizeof (unichar)), id.u.n.name[i]); 1319218822Sdim windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); 1320218822Sdim set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); 132138889Sjdp } 1322218822Sdim off += (rc_uint_type) ((len + 1) * sizeof (unichar)); 1323218822Sdim } 1324218822Sdim return off; 132538889Sjdp} 132638889Sjdp 132738889Sjdp/* Convert a null terminated unicode string to binary. This always 132838889Sjdp returns exactly one bindata structure. */ 132938889Sjdp 1330218822Sdimstatic rc_uint_type 1331218822Sdimunicode_to_bin (windres_bfd *wrbfd, rc_uint_type off, const unichar *str) 133238889Sjdp{ 1333218822Sdim rc_uint_type len = 0; 133438889Sjdp 133538889Sjdp if (str != NULL) 1336218822Sdim len = unichar_len (str); 133738889Sjdp 1338218822Sdim if (wrbfd) 133938889Sjdp { 1340218822Sdim bfd_byte *d; 1341218822Sdim rc_uint_type i; 1342218822Sdim d = (bfd_byte *) reswr_alloc ( (len + 1) * sizeof (unichar)); 1343218822Sdim for (i = 0; i < len; i++) 1344218822Sdim windres_put_16 (wrbfd, d + (i * sizeof (unichar)), str[i]); 1345218822Sdim windres_put_16 (wrbfd, d + (len * sizeof (unichar)), 0); 1346218822Sdim set_windres_bfd_content (wrbfd, d, off, (len + 1) * sizeof (unichar)); 134738889Sjdp } 1348218822Sdim off += (rc_uint_type) ((len + 1) * sizeof (unichar)); 134938889Sjdp 1350218822Sdim return off; 135138889Sjdp} 135238889Sjdp 135338889Sjdp/* Convert an accelerator resource to binary. */ 135438889Sjdp 1355218822Sdimstatic rc_uint_type 1356218822Sdimres_to_bin_accelerator (windres_bfd *wrbfd, rc_uint_type off, 1357218822Sdim const rc_accelerator *accelerators) 135838889Sjdp{ 1359218822Sdim bindata *first, **pp; 1360218822Sdim const rc_accelerator *a; 136138889Sjdp 136238889Sjdp first = NULL; 136338889Sjdp pp = &first; 136438889Sjdp 136538889Sjdp for (a = accelerators; a != NULL; a = a->next) 136638889Sjdp { 1367218822Sdim if (wrbfd) 1368218822Sdim { 1369218822Sdim struct bin_accelerator ba; 137038889Sjdp 1371218822Sdim windres_put_16 (wrbfd, ba.flags, a->flags | (a->next != NULL ? 0 : ACC_LAST)); 1372218822Sdim windres_put_16 (wrbfd, ba.key, a->key); 1373218822Sdim windres_put_16 (wrbfd, ba.id, a->id); 1374218822Sdim windres_put_16 (wrbfd, ba.pad, 0); 1375218822Sdim set_windres_bfd_content (wrbfd, &ba, off, BIN_ACCELERATOR_SIZE); 137638889Sjdp } 1377218822Sdim off += BIN_ACCELERATOR_SIZE; 1378218822Sdim } 1379218822Sdim return off; 138038889Sjdp} 138138889Sjdp 138238889Sjdp/* Convert a cursor resource to binary. */ 138338889Sjdp 1384218822Sdimstatic rc_uint_type 1385218822Sdimres_to_bin_cursor (windres_bfd *wrbfd, rc_uint_type off, const rc_cursor *c) 138638889Sjdp{ 1387218822Sdim if (wrbfd) 1388218822Sdim { 1389218822Sdim struct bin_cursor bc; 139038889Sjdp 1391218822Sdim windres_put_16 (wrbfd, bc.xhotspot, c->xhotspot); 1392218822Sdim windres_put_16 (wrbfd, bc.yhotspot, c->yhotspot); 1393218822Sdim set_windres_bfd_content (wrbfd, &bc, off, BIN_CURSOR_SIZE); 1394218822Sdim if (c->length) 1395218822Sdim set_windres_bfd_content (wrbfd, c->data, off + BIN_CURSOR_SIZE, c->length); 1396218822Sdim } 1397218822Sdim off = (off + BIN_CURSOR_SIZE + (rc_uint_type) c->length); 1398218822Sdim return off; 139938889Sjdp} 140038889Sjdp 140138889Sjdp/* Convert a group cursor resource to binary. */ 140238889Sjdp 1403218822Sdimstatic rc_uint_type 1404218822Sdimres_to_bin_group_cursor (windres_bfd *wrbfd, rc_uint_type off, 1405218822Sdim const rc_group_cursor *group_cursors) 140638889Sjdp{ 1407218822Sdim int c = 0; 1408218822Sdim const rc_group_cursor *gc; 1409218822Sdim struct bin_group_cursor bgc; 1410218822Sdim struct bin_group_cursor_item bgci; 1411218822Sdim rc_uint_type start = off; 141238889Sjdp 1413218822Sdim off += BIN_GROUP_CURSOR_SIZE; 141438889Sjdp 1415218822Sdim for (c = 0, gc = group_cursors; gc != NULL; gc = gc->next, c++) 141638889Sjdp { 1417218822Sdim if (wrbfd) 1418218822Sdim { 1419218822Sdim windres_put_16 (wrbfd, bgci.width, gc->width); 1420218822Sdim windres_put_16 (wrbfd, bgci.height, gc->height); 1421218822Sdim windres_put_16 (wrbfd, bgci.planes, gc->planes); 1422218822Sdim windres_put_16 (wrbfd, bgci.bits, gc->bits); 1423218822Sdim windres_put_32 (wrbfd, bgci.bytes, gc->bytes); 1424218822Sdim windres_put_16 (wrbfd, bgci.index, gc->index); 1425218822Sdim set_windres_bfd_content (wrbfd, &bgci, off, BIN_GROUP_CURSOR_ITEM_SIZE); 1426218822Sdim } 142738889Sjdp 1428218822Sdim off += BIN_GROUP_CURSOR_ITEM_SIZE; 142938889Sjdp } 1430218822Sdim if (wrbfd) 1431218822Sdim { 1432218822Sdim windres_put_16 (wrbfd, bgc.sig1, 0); 1433218822Sdim windres_put_16 (wrbfd, bgc.sig2, 2); 1434218822Sdim windres_put_16 (wrbfd, bgc.nitems, c); 1435218822Sdim set_windres_bfd_content (wrbfd, &bgc, start, BIN_GROUP_CURSOR_SIZE); 1436218822Sdim } 1437218822Sdim return off; 143838889Sjdp} 143938889Sjdp 144038889Sjdp/* Convert a dialog resource to binary. */ 144138889Sjdp 1442218822Sdimstatic rc_uint_type 1443218822Sdimres_to_bin_dialog (windres_bfd *wrbfd, rc_uint_type off, const rc_dialog *dialog) 144438889Sjdp{ 1445218822Sdim rc_uint_type off_delta; 1446218822Sdim rc_uint_type start, marker; 144738889Sjdp int dialogex; 1448218822Sdim int c; 1449218822Sdim rc_dialog_control *dc; 1450218822Sdim struct bin_dialogex bdx; 1451218822Sdim struct bin_dialog bd; 145238889Sjdp 1453218822Sdim off_delta = off; 1454218822Sdim start = off; 145538889Sjdp dialogex = extended_dialog (dialog); 145638889Sjdp 1457218822Sdim if (wrbfd) 1458218822Sdim { 145938889Sjdp if (! dialogex) 146038889Sjdp { 1461218822Sdim windres_put_32 (wrbfd, bd.style, dialog->style); 1462218822Sdim windres_put_32 (wrbfd, bd.exstyle, dialog->exstyle); 1463218822Sdim windres_put_16 (wrbfd, bd.x, dialog->x); 1464218822Sdim windres_put_16 (wrbfd, bd.y, dialog->y); 1465218822Sdim windres_put_16 (wrbfd, bd.width, dialog->width); 1466218822Sdim windres_put_16 (wrbfd, bd.height, dialog->height); 146738889Sjdp } 146838889Sjdp else 146938889Sjdp { 1470218822Sdim windres_put_16 (wrbfd, bdx.sig1, 1); 1471218822Sdim windres_put_16 (wrbfd, bdx.sig2, 0xffff); 1472218822Sdim windres_put_32 (wrbfd, bdx.help, (dialog->ex ? dialog->ex->help : 0)); 1473218822Sdim windres_put_32 (wrbfd, bdx.exstyle, dialog->exstyle); 1474218822Sdim windres_put_32 (wrbfd, bdx.style, dialog->style); 1475218822Sdim windres_put_16 (wrbfd, bdx.x, dialog->x); 1476218822Sdim windres_put_16 (wrbfd, bdx.y, dialog->y); 1477218822Sdim windres_put_16 (wrbfd, bdx.width, dialog->width); 1478218822Sdim windres_put_16 (wrbfd, bdx.height, dialog->height); 1479218822Sdim } 148038889Sjdp } 148138889Sjdp 1482218822Sdim off += (dialogex != 0 ? BIN_DIALOGEX_SIZE : BIN_DIALOG_SIZE); 148338889Sjdp 1484218822Sdim off = resid_to_bin (wrbfd, off, dialog->menu); 1485218822Sdim off = resid_to_bin (wrbfd, off, dialog->class); 1486218822Sdim off = unicode_to_bin (wrbfd, off, dialog->caption); 148738889Sjdp 148838889Sjdp if ((dialog->style & DS_SETFONT) != 0) 148938889Sjdp { 1490218822Sdim if (wrbfd) 149138889Sjdp { 1492218822Sdim if (! dialogex) 149338889Sjdp { 1494218822Sdim struct bin_dialogfont bdf; 1495218822Sdim windres_put_16 (wrbfd, bdf.pointsize, dialog->pointsize); 1496218822Sdim set_windres_bfd_content (wrbfd, &bdf, off, BIN_DIALOGFONT_SIZE); 149738889Sjdp } 149838889Sjdp else 149938889Sjdp { 1500218822Sdim struct bin_dialogexfont bdxf; 1501218822Sdim windres_put_16 (wrbfd, bdxf.pointsize, dialog->pointsize); 1502218822Sdim windres_put_16 (wrbfd, bdxf.weight, (dialog->ex == NULL ? 0 : dialog->ex->weight)); 1503218822Sdim windres_put_8 (wrbfd, bdxf.italic, (dialog->ex == NULL ? 0 : dialog->ex->italic)); 1504218822Sdim windres_put_8 (wrbfd, bdxf.charset, (dialog->ex == NULL ? 1 : dialog->ex->charset)); 1505218822Sdim set_windres_bfd_content (wrbfd, &bdxf, off, BIN_DIALOGEXFONT_SIZE); 150638889Sjdp } 150738889Sjdp } 1508218822Sdim off += (dialogex ? BIN_DIALOGEXFONT_SIZE : BIN_DIALOGFONT_SIZE); 1509218822Sdim off = unicode_to_bin (wrbfd, off, dialog->font); 151038889Sjdp } 1511218822Sdim for (c = 0, dc = dialog->controls; dc != NULL; dc = dc->next, c++) 151238889Sjdp { 1513218822Sdim bfd_byte dc_rclen[2]; 151438889Sjdp 1515218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 1516218822Sdim if (wrbfd) 1517218822Sdim { 151838889Sjdp if (! dialogex) 151938889Sjdp { 1520218822Sdim struct bin_dialog_control bdc; 1521218822Sdim 1522218822Sdim windres_put_32 (wrbfd, bdc.style, dc->style); 1523218822Sdim windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle); 1524218822Sdim windres_put_16 (wrbfd, bdc.x, dc->x); 1525218822Sdim windres_put_16 (wrbfd, bdc.y, dc->y); 1526218822Sdim windres_put_16 (wrbfd, bdc.width, dc->width); 1527218822Sdim windres_put_16 (wrbfd, bdc.height, dc->height); 1528218822Sdim windres_put_16 (wrbfd, bdc.id, dc->id); 1529218822Sdim set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOG_CONTROL_SIZE); 153038889Sjdp } 153138889Sjdp else 153238889Sjdp { 1533218822Sdim struct bin_dialogex_control bdc; 153438889Sjdp 1535218822Sdim windres_put_32 (wrbfd, bdc.help, dc->help); 1536218822Sdim windres_put_32 (wrbfd, bdc.exstyle, dc->exstyle); 1537218822Sdim windres_put_32 (wrbfd, bdc.style, dc->style); 1538218822Sdim windres_put_16 (wrbfd, bdc.x, dc->x); 1539218822Sdim windres_put_16 (wrbfd, bdc.y, dc->y); 1540218822Sdim windres_put_16 (wrbfd, bdc.width, dc->width); 1541218822Sdim windres_put_16 (wrbfd, bdc.height, dc->height); 1542218822Sdim windres_put_32 (wrbfd, bdc.id, dc->id); 1543218822Sdim set_windres_bfd_content (wrbfd, &bdc, off, BIN_DIALOGEX_CONTROL_SIZE); 1544218822Sdim } 1545218822Sdim } 1546218822Sdim off += (dialogex != 0 ? BIN_DIALOGEX_CONTROL_SIZE : BIN_DIALOG_CONTROL_SIZE); 154738889Sjdp 1548218822Sdim off = resid_to_bin (wrbfd, off, dc->class); 1549218822Sdim off = resid_to_bin (wrbfd, off, dc->text); 155060484Sobrien 1551218822Sdim marker = off; /* Save two bytes for size of optional data. */ 1552218822Sdim off += 2; 155338889Sjdp 155438889Sjdp if (dc->data == NULL) 1555218822Sdim { 1556218822Sdim if (wrbfd) 1557218822Sdim windres_put_16 (wrbfd, dc_rclen, 0); 1558218822Sdim } 155938889Sjdp else 156038889Sjdp { 1561218822Sdim rc_uint_type saved_off = off; 1562218822Sdim rc_uint_type old_off; 1563218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 156438889Sjdp 1565218822Sdim old_off = off; 1566218822Sdim off = res_to_bin_rcdata (wrbfd, off, dc->data); 1567218822Sdim if ((off - old_off) == 0) 1568218822Sdim old_off = off = saved_off; 1569218822Sdim if (wrbfd) 1570218822Sdim windres_put_16 (wrbfd, dc_rclen, off - old_off); 157138889Sjdp } 1572218822Sdim if (wrbfd) 1573218822Sdim set_windres_bfd_content (wrbfd, dc_rclen, marker, 2); 1574218822Sdim } 157538889Sjdp 1576218822Sdim if (wrbfd) 1577218822Sdim { 1578218822Sdim windres_put_16 (wrbfd, (dialogex != 0 ? bdx.off : bd.off), c); 1579218822Sdim if (! dialogex) 1580218822Sdim set_windres_bfd_content (wrbfd, &bd, start, BIN_DIALOG_SIZE); 1581218822Sdim else 1582218822Sdim set_windres_bfd_content (wrbfd, &bdx, start, BIN_DIALOGEX_SIZE); 158338889Sjdp } 158438889Sjdp 1585218822Sdim return off; 158638889Sjdp} 158738889Sjdp 158838889Sjdp/* Convert a fontdir resource to binary. */ 1589218822Sdimstatic rc_uint_type 1590218822Sdimres_to_bin_fontdir (windres_bfd *wrbfd, rc_uint_type off, const rc_fontdir *fontdirs) 159138889Sjdp{ 1592218822Sdim rc_uint_type start; 159338889Sjdp int c; 1594218822Sdim const rc_fontdir *fd; 159538889Sjdp 1596218822Sdim start = off; 1597218822Sdim off += 2; 159838889Sjdp 1599218822Sdim for (c = 0, fd = fontdirs; fd != NULL; fd = fd->next, c++) 1600218822Sdim { 1601218822Sdim if (wrbfd) 1602218822Sdim { 1603218822Sdim bfd_byte d[2]; 1604218822Sdim windres_put_16 (wrbfd, d, fd->index); 1605218822Sdim set_windres_bfd_content (wrbfd, d, off, 2); 1606218822Sdim if (fd->length) 1607218822Sdim set_windres_bfd_content (wrbfd, fd->data, off + 2, fd->length); 1608218822Sdim } 1609218822Sdim off += (rc_uint_type) fd->length + 2; 1610218822Sdim } 161138889Sjdp 1612218822Sdim if (wrbfd) 161338889Sjdp { 1614218822Sdim bfd_byte d[2]; 1615218822Sdim windres_put_16 (wrbfd, d, c); 1616218822Sdim set_windres_bfd_content (wrbfd, d, start, 2); 161738889Sjdp } 1618218822Sdim return off; 161938889Sjdp} 162038889Sjdp 162138889Sjdp/* Convert a group icon resource to binary. */ 162238889Sjdp 1623218822Sdimstatic rc_uint_type 1624218822Sdimres_to_bin_group_icon (windres_bfd *wrbfd, rc_uint_type off, const rc_group_icon *group_icons) 162538889Sjdp{ 1626218822Sdim rc_uint_type start; 1627218822Sdim struct bin_group_icon bgi; 162838889Sjdp int c; 1629218822Sdim const rc_group_icon *gi; 163038889Sjdp 1631218822Sdim start = off; 1632218822Sdim off += BIN_GROUP_ICON_SIZE; 163338889Sjdp 1634218822Sdim for (c = 0, gi = group_icons; gi != NULL; gi = gi->next, c++) 1635218822Sdim { 1636218822Sdim struct bin_group_icon_item bgii; 163738889Sjdp 1638218822Sdim if (wrbfd) 1639218822Sdim { 1640218822Sdim windres_put_8 (wrbfd, bgii.width, gi->width); 1641218822Sdim windres_put_8 (wrbfd, bgii.height, gi->height); 1642218822Sdim windres_put_8 (wrbfd, bgii.colors, gi->colors); 1643218822Sdim windres_put_8 (wrbfd, bgii.pad, 0); 1644218822Sdim windres_put_16 (wrbfd, bgii.planes, gi->planes); 1645218822Sdim windres_put_16 (wrbfd, bgii.bits, gi->bits); 1646218822Sdim windres_put_32 (wrbfd, bgii.bytes, gi->bytes); 1647218822Sdim windres_put_16 (wrbfd, bgii.index, gi->index); 1648218822Sdim set_windres_bfd_content (wrbfd, &bgii, off, BIN_GROUP_ICON_ITEM_SIZE); 1649218822Sdim } 1650218822Sdim off += BIN_GROUP_ICON_ITEM_SIZE; 1651218822Sdim } 165238889Sjdp 1653218822Sdim if (wrbfd) 165438889Sjdp { 1655218822Sdim windres_put_16 (wrbfd, bgi.sig1, 0); 1656218822Sdim windres_put_16 (wrbfd, bgi.sig2, 1); 1657218822Sdim windres_put_16 (wrbfd, bgi.count, c); 1658218822Sdim set_windres_bfd_content (wrbfd, &bgi, start, BIN_GROUP_ICON_SIZE); 165938889Sjdp } 1660218822Sdim return off; 166138889Sjdp} 166238889Sjdp 166338889Sjdp/* Convert a menu resource to binary. */ 166438889Sjdp 1665218822Sdimstatic rc_uint_type 1666218822Sdimres_to_bin_menu (windres_bfd *wrbfd, rc_uint_type off, const rc_menu *menu) 166738889Sjdp{ 166838889Sjdp int menuex; 166938889Sjdp 167038889Sjdp menuex = extended_menu (menu); 167138889Sjdp 1672218822Sdim if (wrbfd) 1673218822Sdim { 167438889Sjdp if (! menuex) 167538889Sjdp { 1676218822Sdim struct bin_menu bm; 1677218822Sdim windres_put_16 (wrbfd, bm.sig1, 0); 1678218822Sdim windres_put_16 (wrbfd, bm.sig2, 0); 1679218822Sdim set_windres_bfd_content (wrbfd, &bm, off, BIN_MENU_SIZE); 168038889Sjdp } 168138889Sjdp else 168238889Sjdp { 1683218822Sdim struct bin_menuex bm; 1684218822Sdim windres_put_16 (wrbfd, bm.sig1, 1); 1685218822Sdim windres_put_16 (wrbfd, bm.sig2, 4); 1686218822Sdim windres_put_32 (wrbfd, bm.help, menu->help); 1687218822Sdim set_windres_bfd_content (wrbfd, &bm, off, BIN_MENUEX_SIZE); 168838889Sjdp } 1689218822Sdim } 1690218822Sdim off += (menuex != 0 ? BIN_MENUEX_SIZE : BIN_MENU_SIZE); 1691218822Sdim if (! menuex) 1692218822Sdim { 1693218822Sdim off = res_to_bin_menuitems (wrbfd, off, menu->items); 1694218822Sdim } 1695218822Sdim else 1696218822Sdim { 1697218822Sdim off = res_to_bin_menuexitems (wrbfd, off, menu->items); 1698218822Sdim } 1699218822Sdim return off; 170038889Sjdp} 170138889Sjdp 170238889Sjdp/* Convert menu items to binary. */ 170338889Sjdp 1704218822Sdimstatic rc_uint_type 1705218822Sdimres_to_bin_menuitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) 170638889Sjdp{ 1707218822Sdim const rc_menuitem *mi; 170838889Sjdp 170938889Sjdp for (mi = items; mi != NULL; mi = mi->next) 171038889Sjdp { 1711218822Sdim struct bin_menuitem bmi; 171238889Sjdp int flags; 171338889Sjdp 171438889Sjdp flags = mi->type; 171538889Sjdp if (mi->next == NULL) 171638889Sjdp flags |= MENUITEM_ENDMENU; 171738889Sjdp if (mi->popup != NULL) 171838889Sjdp flags |= MENUITEM_POPUP; 171938889Sjdp 1720218822Sdim if (wrbfd) 1721218822Sdim { 1722218822Sdim windres_put_16 (wrbfd, bmi.flags, flags); 172338889Sjdp if (mi->popup == NULL) 1724218822Sdim windres_put_16 (wrbfd, bmi.id, mi->id); 1725218822Sdim set_windres_bfd_content (wrbfd, &bmi, off, 1726218822Sdim mi->popup == NULL ? BIN_MENUITEM_SIZE 1727218822Sdim : BIN_MENUITEM_POPUP_SIZE); 1728218822Sdim } 1729218822Sdim off += (mi->popup == NULL ? BIN_MENUITEM_SIZE : BIN_MENUITEM_POPUP_SIZE); 173038889Sjdp 1731218822Sdim off = unicode_to_bin (wrbfd, off, mi->text); 173238889Sjdp 173338889Sjdp if (mi->popup != NULL) 173438889Sjdp { 1735218822Sdim off = res_to_bin_menuitems (wrbfd, off, mi->popup); 173638889Sjdp } 173738889Sjdp } 1738218822Sdim return off; 173938889Sjdp} 174038889Sjdp 174138889Sjdp/* Convert menuex items to binary. */ 174238889Sjdp 1743218822Sdimstatic rc_uint_type 1744218822Sdimres_to_bin_menuexitems (windres_bfd *wrbfd, rc_uint_type off, const rc_menuitem *items) 174538889Sjdp{ 1746218822Sdim rc_uint_type off_delta = off; 1747218822Sdim const rc_menuitem *mi; 174838889Sjdp 174938889Sjdp for (mi = items; mi != NULL; mi = mi->next) 175038889Sjdp { 1751218822Sdim struct bin_menuitemex bmi; 175238889Sjdp int flags; 175338889Sjdp 1754218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 175538889Sjdp 175638889Sjdp flags = 0; 175738889Sjdp if (mi->next == NULL) 175838889Sjdp flags |= 0x80; 175938889Sjdp if (mi->popup != NULL) 176038889Sjdp flags |= 1; 176138889Sjdp 1762218822Sdim if (wrbfd) 1763218822Sdim { 1764218822Sdim windres_put_32 (wrbfd, bmi.type, mi->type); 1765218822Sdim windres_put_32 (wrbfd, bmi.state, mi->state); 1766218822Sdim windres_put_32 (wrbfd, bmi.id, mi->id); 1767218822Sdim windres_put_16 (wrbfd, bmi.flags, flags); 1768218822Sdim set_windres_bfd_content (wrbfd, &bmi, off, BIN_MENUITEMEX_SIZE); 1769218822Sdim } 1770218822Sdim off += BIN_MENUITEMEX_SIZE; 177138889Sjdp 1772218822Sdim off = unicode_to_bin (wrbfd, off, mi->text); 177338889Sjdp 177438889Sjdp if (mi->popup != NULL) 177538889Sjdp { 1776218822Sdim bfd_byte help[4]; 177738889Sjdp 1778218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 177938889Sjdp 1780218822Sdim if (wrbfd) 178138889Sjdp { 1782218822Sdim windres_put_32 (wrbfd, help, mi->help); 1783218822Sdim set_windres_bfd_content (wrbfd, help, off, 4); 178438889Sjdp } 1785218822Sdim off += 4; 1786218822Sdim off = res_to_bin_menuexitems (wrbfd, off, mi->popup); 178738889Sjdp } 178838889Sjdp } 1789218822Sdim return off; 179038889Sjdp} 179138889Sjdp 179238889Sjdp/* Convert an rcdata resource to binary. This is also used to convert 1793218822Sdim other information which happens to be stored in rc_rcdata_item lists 179438889Sjdp to binary. */ 179538889Sjdp 1796218822Sdimstatic rc_uint_type 1797218822Sdimres_to_bin_rcdata (windres_bfd *wrbfd, rc_uint_type off, const rc_rcdata_item *items) 179838889Sjdp{ 1799218822Sdim const rc_rcdata_item *ri; 180038889Sjdp 180138889Sjdp for (ri = items; ri != NULL; ri = ri->next) 180238889Sjdp { 1803218822Sdim rc_uint_type len; 180438889Sjdp switch (ri->type) 180538889Sjdp { 180638889Sjdp default: 180738889Sjdp abort (); 180838889Sjdp case RCDATA_WORD: 1809218822Sdim len = 2; 181038889Sjdp break; 181138889Sjdp case RCDATA_DWORD: 1812218822Sdim len = 4; 181338889Sjdp break; 181438889Sjdp case RCDATA_STRING: 1815218822Sdim len = ri->u.string.length; 181638889Sjdp break; 181738889Sjdp case RCDATA_WSTRING: 1818218822Sdim len = ri->u.wstring.length * sizeof (unichar); 1819218822Sdim break; 1820218822Sdim case RCDATA_BUFFER: 1821218822Sdim len = ri->u.buffer.length; 1822218822Sdim break; 1823218822Sdim } 1824218822Sdim if (wrbfd) 1825218822Sdim { 1826218822Sdim bfd_byte h[4]; 1827218822Sdim bfd_byte *hp = &h[0]; 1828218822Sdim switch (ri->type) 1829218822Sdim { 1830218822Sdim case RCDATA_WORD: 1831218822Sdim windres_put_16 (wrbfd, hp, ri->u.word); 1832218822Sdim break; 1833218822Sdim case RCDATA_DWORD: 1834218822Sdim windres_put_32 (wrbfd, hp, ri->u.dword); 1835218822Sdim break; 1836218822Sdim case RCDATA_STRING: 1837218822Sdim hp = (bfd_byte *) ri->u.string.s; 1838218822Sdim break; 1839218822Sdim case RCDATA_WSTRING: 184038889Sjdp { 1841218822Sdim rc_uint_type i; 184238889Sjdp 1843218822Sdim hp = (bfd_byte *) reswr_alloc (len); 184438889Sjdp for (i = 0; i < ri->u.wstring.length; i++) 1845218822Sdim windres_put_16 (wrbfd, hp + i * sizeof (unichar), ri->u.wstring.w[i]); 184638889Sjdp } 1847218822Sdim break; 184838889Sjdp case RCDATA_BUFFER: 1849218822Sdim hp = (bfd_byte *) ri->u.buffer.data; 185038889Sjdp break; 185138889Sjdp } 1852218822Sdim set_windres_bfd_content (wrbfd, hp, off, len); 185338889Sjdp } 1854218822Sdim off += len; 1855218822Sdim } 1856218822Sdim return off; 185738889Sjdp} 185838889Sjdp 185938889Sjdp/* Convert a stringtable resource to binary. */ 186038889Sjdp 1861218822Sdimstatic rc_uint_type 1862218822Sdimres_to_bin_stringtable (windres_bfd *wrbfd, rc_uint_type off, 1863218822Sdim const rc_stringtable *st) 186438889Sjdp{ 186538889Sjdp int i; 186638889Sjdp 186738889Sjdp for (i = 0; i < 16; i++) 186838889Sjdp { 1869218822Sdim rc_uint_type slen, length; 187038889Sjdp unichar *s; 187138889Sjdp 1872218822Sdim slen = (rc_uint_type) st->strings[i].length; 187338889Sjdp s = st->strings[i].string; 187438889Sjdp 1875218822Sdim length = 2 + slen * 2; 1876218822Sdim if (wrbfd) 1877218822Sdim { 1878218822Sdim bfd_byte *hp; 1879218822Sdim rc_uint_type j; 188038889Sjdp 1881218822Sdim hp = (bfd_byte *) reswr_alloc (length); 1882218822Sdim windres_put_16 (wrbfd, hp, slen); 188338889Sjdp 188438889Sjdp for (j = 0; j < slen; j++) 1885218822Sdim windres_put_16 (wrbfd, hp + 2 + j * 2, s[j]); 1886218822Sdim set_windres_bfd_content (wrbfd, hp, off, length); 188738889Sjdp } 1888218822Sdim off += length; 1889218822Sdim } 1890218822Sdim return off; 189138889Sjdp} 189238889Sjdp 189338889Sjdp/* Convert an ASCII string to a unicode binary string. This always 189438889Sjdp returns exactly one bindata structure. */ 189538889Sjdp 1896218822Sdimstatic rc_uint_type 1897218822Sdimstring_to_unicode_bin (windres_bfd *wrbfd, rc_uint_type off, const char *s) 189838889Sjdp{ 1899218822Sdim rc_uint_type len; 190038889Sjdp 1901218822Sdim len = (rc_uint_type) strlen (s); 190238889Sjdp 1903218822Sdim if (wrbfd) 1904218822Sdim { 1905218822Sdim rc_uint_type i; 1906218822Sdim bfd_byte *hp; 190738889Sjdp 1908218822Sdim hp = (bfd_byte *) reswr_alloc ((len + 1) * sizeof (unichar)); 190938889Sjdp 1910218822Sdim for (i = 0; i < len; i++) 1911218822Sdim windres_put_16 (wrbfd, hp + i * 2, s[i]); 1912218822Sdim windres_put_16 (wrbfd, hp + i * 2, 0); 1913218822Sdim set_windres_bfd_content (wrbfd, hp, off, (len + 1) * sizeof (unichar)); 1914218822Sdim } 1915218822Sdim off += (rc_uint_type) ((len + 1) * sizeof (unichar)); 1916218822Sdim return off; 191738889Sjdp} 191838889Sjdp 1919218822Sdimstatic rc_uint_type 1920218822Sdimres_to_bin_toolbar (windres_bfd *wrbfd, rc_uint_type off, rc_toolbar *tb) 192138889Sjdp{ 1922218822Sdim if (wrbfd) 1923218822Sdim { 1924218822Sdim struct bin_toolbar bt; 1925218822Sdim windres_put_32 (wrbfd, bt.button_width, tb->button_width); 1926218822Sdim windres_put_32 (wrbfd, bt.button_height, tb->button_height); 1927218822Sdim windres_put_32 (wrbfd, bt.nitems, tb->nitems); 1928218822Sdim set_windres_bfd_content (wrbfd, &bt, off, BIN_TOOLBAR_SIZE); 1929218822Sdim if (tb->nitems > 0) 1930218822Sdim { 1931218822Sdim rc_toolbar_item *it; 1932218822Sdim bfd_byte *ids; 1933218822Sdim rc_uint_type i = 0; 193438889Sjdp 1935218822Sdim ids = (bfd_byte *) reswr_alloc (tb->nitems * 4); 1936218822Sdim it=tb->items; 1937218822Sdim while(it != NULL) 1938218822Sdim { 1939218822Sdim windres_put_32 (wrbfd, ids + i, it->id.u.id); 1940218822Sdim i += 4; 1941218822Sdim it = it->next; 1942218822Sdim } 1943218822Sdim set_windres_bfd_content (wrbfd, ids, off + BIN_TOOLBAR_SIZE, i); 1944218822Sdim } 1945218822Sdim } 1946218822Sdim off += BIN_TOOLBAR_SIZE + tb->nitems * 4; 194738889Sjdp 1948218822Sdim return off; 1949218822Sdim} 195038889Sjdp 1951218822Sdim/* Convert a versioninfo resource to binary. */ 195238889Sjdp 1953218822Sdimstatic rc_uint_type 1954218822Sdimres_to_bin_versioninfo (windres_bfd *wrbfd, rc_uint_type off, 1955218822Sdim const rc_versioninfo *versioninfo) 1956218822Sdim{ 1957218822Sdim rc_uint_type off_delta = off; 1958218822Sdim rc_uint_type start; 1959218822Sdim struct bin_versioninfo bvi; 1960218822Sdim rc_ver_info *vi; 196138889Sjdp 1962218822Sdim start = off; 1963218822Sdim off += BIN_VERSIONINFO_SIZE; 1964218822Sdim off = string_to_unicode_bin (wrbfd, off, "VS_VERSION_INFO"); 1965218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 196638889Sjdp 196738889Sjdp if (versioninfo->fixed != NULL) 196838889Sjdp { 1969218822Sdim if (wrbfd) 1970218822Sdim { 1971218822Sdim struct bin_fixed_versioninfo bfv; 1972218822Sdim const rc_fixed_versioninfo *fi; 197338889Sjdp 197438889Sjdp fi = versioninfo->fixed; 1975218822Sdim windres_put_32 (wrbfd, bfv.sig1, 0xfeef04bd); 1976218822Sdim windres_put_32 (wrbfd, bfv.sig2, 0x10000); 1977218822Sdim windres_put_32 (wrbfd, bfv.file_version, fi->file_version_ms); 1978218822Sdim windres_put_32 (wrbfd, bfv.file_version_ls, fi->file_version_ls); 1979218822Sdim windres_put_32 (wrbfd, bfv.product_version_ms, fi->product_version_ms); 1980218822Sdim windres_put_32 (wrbfd, bfv.product_version_ls, fi->product_version_ls); 1981218822Sdim windres_put_32 (wrbfd, bfv.file_flags_mask, fi->file_flags_mask); 1982218822Sdim windres_put_32 (wrbfd, bfv.file_flags, fi->file_flags); 1983218822Sdim windres_put_32 (wrbfd, bfv.file_os, fi->file_os); 1984218822Sdim windres_put_32 (wrbfd, bfv.file_type, fi->file_type); 1985218822Sdim windres_put_32 (wrbfd, bfv.file_subtype, fi->file_subtype); 1986218822Sdim windres_put_32 (wrbfd, bfv.file_date_ms, fi->file_date_ms); 1987218822Sdim windres_put_32 (wrbfd, bfv.file_date_ls, fi->file_date_ls); 1988218822Sdim set_windres_bfd_content (wrbfd, &bfv, off, BIN_FIXED_VERSIONINFO_SIZE); 1989218822Sdim } 1990218822Sdim off += BIN_FIXED_VERSIONINFO_SIZE; 199138889Sjdp } 199238889Sjdp 199338889Sjdp for (vi = versioninfo->var; vi != NULL; vi = vi->next) 199438889Sjdp { 1995218822Sdim struct bin_ver_info bv; 1996218822Sdim rc_uint_type bv_off; 199738889Sjdp 1998218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 199938889Sjdp 2000218822Sdim bv_off = off; 200138889Sjdp 2002218822Sdim off += BIN_VER_INFO_SIZE; 200338889Sjdp 200438889Sjdp switch (vi->type) 200538889Sjdp { 200638889Sjdp default: 200738889Sjdp abort (); 200838889Sjdp case VERINFO_STRING: 200938889Sjdp { 2010218822Sdim struct bin_ver_info bvsd; 2011218822Sdim rc_uint_type vs_off; 2012218822Sdim const rc_ver_stringinfo *vs; 201338889Sjdp 2014218822Sdim off = string_to_unicode_bin (wrbfd, off, "StringFileInfo"); 2015218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 201638889Sjdp 2017218822Sdim vs_off = off; 201838889Sjdp 2019218822Sdim off += BIN_VER_INFO_SIZE; 202038889Sjdp 2021218822Sdim off = unicode_to_bin (wrbfd, off, vi->u.string.language); 202238889Sjdp 202338889Sjdp for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) 202438889Sjdp { 2025218822Sdim struct bin_ver_info bvss; 2026218822Sdim rc_uint_type vss_off,str_off; 202738889Sjdp 2028218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 202938889Sjdp 2030218822Sdim vss_off = off; 2031218822Sdim off += BIN_VER_INFO_SIZE; 203238889Sjdp 2033218822Sdim off = unicode_to_bin (wrbfd, off, vs->key); 203438889Sjdp 2035218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 203638889Sjdp 2037218822Sdim str_off = off; 2038218822Sdim off = unicode_to_bin (wrbfd, off, vs->value); 2039218822Sdim if (wrbfd) 2040218822Sdim { 2041218822Sdim windres_put_16 (wrbfd, bvss.size, off - vss_off); 2042218822Sdim windres_put_16 (wrbfd, bvss.sig1, (off - str_off) / 2); 2043218822Sdim windres_put_16 (wrbfd, bvss.sig2, 1); 2044218822Sdim set_windres_bfd_content (wrbfd, &bvss, vss_off, 2045218822Sdim BIN_VER_INFO_SIZE); 2046218822Sdim } 204738889Sjdp } 2048218822Sdim if (wrbfd) 2049218822Sdim { 2050218822Sdim windres_put_16 (wrbfd, bvsd.size, off - vs_off); 2051218822Sdim windres_put_16 (wrbfd, bvsd.sig1, 0); 2052218822Sdim windres_put_16 (wrbfd, bvsd.sig2, 0); 2053218822Sdim set_windres_bfd_content (wrbfd, &bvsd, vs_off, 2054218822Sdim BIN_VER_INFO_SIZE); 2055218822Sdim } 205638889Sjdp break; 205738889Sjdp } 205838889Sjdp 205938889Sjdp case VERINFO_VAR: 206038889Sjdp { 2061218822Sdim rc_uint_type vvd_off, vvvd_off; 2062218822Sdim struct bin_ver_info bvvd; 2063218822Sdim const rc_ver_varinfo *vv; 206438889Sjdp 2065218822Sdim off = string_to_unicode_bin (wrbfd, off, "VarFileInfo"); 206638889Sjdp 2067218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 206838889Sjdp 2069218822Sdim vvd_off = off; 2070218822Sdim off += BIN_VER_INFO_SIZE; 207138889Sjdp 2072218822Sdim off = unicode_to_bin (wrbfd, off, vi->u.var.key); 207338889Sjdp 2074218822Sdim off += (4 - ((off - off_delta) & 3)) & 3; 207538889Sjdp 2076218822Sdim vvvd_off = off; 207738889Sjdp 207838889Sjdp for (vv = vi->u.var.var; vv != NULL; vv = vv->next) 207938889Sjdp { 2080218822Sdim if (wrbfd) 2081218822Sdim { 2082218822Sdim bfd_byte vvsd[4]; 208338889Sjdp 2084218822Sdim windres_put_16 (wrbfd, &vvsd[0], vv->language); 2085218822Sdim windres_put_16 (wrbfd, &vvsd[2], vv->charset); 2086218822Sdim set_windres_bfd_content (wrbfd, vvsd, off, 4); 2087218822Sdim } 2088218822Sdim off += 4; 208938889Sjdp } 2090218822Sdim if (wrbfd) 2091218822Sdim { 2092218822Sdim windres_put_16 (wrbfd, bvvd.size, off - vvd_off); 2093218822Sdim windres_put_16 (wrbfd, bvvd.sig1, off - vvvd_off); 2094218822Sdim windres_put_16 (wrbfd, bvvd.sig2, 0); 2095218822Sdim set_windres_bfd_content (wrbfd, &bvvd, vvd_off, 2096218822Sdim BIN_VER_INFO_SIZE); 2097218822Sdim } 209838889Sjdp 209938889Sjdp break; 210038889Sjdp } 210138889Sjdp } 210238889Sjdp 2103218822Sdim if (wrbfd) 2104218822Sdim { 2105218822Sdim windres_put_16 (wrbfd, bv.size, off-bv_off); 2106218822Sdim windres_put_16 (wrbfd, bv.sig1, 0); 2107218822Sdim windres_put_16 (wrbfd, bv.sig2, 0); 2108218822Sdim set_windres_bfd_content (wrbfd, &bv, bv_off, 2109218822Sdim BIN_VER_INFO_SIZE); 2110218822Sdim } 211138889Sjdp } 211238889Sjdp 2113218822Sdim if (wrbfd) 2114218822Sdim { 2115218822Sdim windres_put_16 (wrbfd, bvi.size, off - start); 2116218822Sdim windres_put_16 (wrbfd, bvi.fixed_size, 2117218822Sdim versioninfo->fixed == NULL ? 0 2118218822Sdim : BIN_FIXED_VERSIONINFO_SIZE); 2119218822Sdim windres_put_16 (wrbfd, bvi.sig2, 0); 2120218822Sdim set_windres_bfd_content (wrbfd, &bvi, start, BIN_VER_INFO_SIZE); 2121218822Sdim } 2122218822Sdim return off; 212338889Sjdp} 212438889Sjdp 212538889Sjdp/* Convert a generic resource to binary. */ 212638889Sjdp 2127218822Sdimstatic rc_uint_type 2128218822Sdimres_to_bin_generic (windres_bfd *wrbfd, rc_uint_type off, rc_uint_type length, 2129218822Sdim const bfd_byte *data) 213038889Sjdp{ 2131218822Sdim if (wrbfd && length != 0) 2132218822Sdim set_windres_bfd_content (wrbfd, data, off, length); 2133218822Sdim return off + (rc_uint_type) length; 213438889Sjdp} 2135