diff options
Diffstat (limited to 'binutils/resbin.c')
-rw-r--r-- | binutils/resbin.c | 2387 |
1 files changed, 0 insertions, 2387 deletions
diff --git a/binutils/resbin.c b/binutils/resbin.c deleted file mode 100644 index 8fc07fbb292..00000000000 --- a/binutils/resbin.c +++ /dev/null @@ -1,2387 +0,0 @@ -/* resbin.c -- manipulate the Windows binary resource format. - Copyright 1997, 1998 Free Software Foundation, Inc. - Written by Ian Lance Taylor, Cygnus Support. - - This file is part of GNU Binutils. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -/* This file contains functions to convert between the binary resource - format and the internal structures that we want to use. The same - binary resource format is used in both res and COFF files. */ - -#include "bfd.h" -#include "bucomm.h" -#include "libiberty.h" -#include "windres.h" - -/* Macros to swap in values. */ - -#define get_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s)) -#define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s)) - -/* Local functions. */ - -static void toosmall PARAMS ((const char *)); -static unichar *get_unicode - PARAMS ((const unsigned char *, unsigned long, int, int *)); -static int get_resid - PARAMS ((struct res_id *, const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_generic - PARAMS ((enum res_type, const unsigned char *, unsigned long)); -static struct res_resource *bin_to_res_cursor - PARAMS ((const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_menu - PARAMS ((const unsigned char *, unsigned long, int)); -static struct menuitem *bin_to_res_menuitems - PARAMS ((const unsigned char *, unsigned long, int, int *)); -static struct menuitem *bin_to_res_menuexitems - PARAMS ((const unsigned char *, unsigned long, int, int *)); -static struct res_resource *bin_to_res_dialog - PARAMS ((const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_string - PARAMS ((const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_fontdir - PARAMS ((const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_accelerators - PARAMS ((const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_rcdata - PARAMS ((const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_group_cursor - PARAMS ((const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_group_icon - PARAMS ((const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_version - PARAMS ((const unsigned char *, unsigned long, int)); -static struct res_resource *bin_to_res_userdata - PARAMS ((const unsigned char *, unsigned long, int)); - -/* Given a resource type ID, a pointer to data, a length, return a - res_resource structure which represents that resource. The caller - is responsible for initializing the res_info and coff_info fields - of the returned structure. */ - -struct res_resource * -bin_to_res (type, data, length, big_endian) - struct res_id type; - const unsigned char *data; - unsigned long length; - int big_endian; -{ - if (type.named) - return bin_to_res_userdata (data, length, big_endian); - else - { - switch (type.u.id) - { - default: - return bin_to_res_userdata (data, length, big_endian); - case RT_CURSOR: - return bin_to_res_cursor (data, length, big_endian); - case RT_BITMAP: - return bin_to_res_generic (RES_TYPE_BITMAP, data, length); - case RT_ICON: - return bin_to_res_generic (RES_TYPE_ICON, data, length); - case RT_MENU: - return bin_to_res_menu (data, length, big_endian); - case RT_DIALOG: - return bin_to_res_dialog (data, length, big_endian); - case RT_STRING: - return bin_to_res_string (data, length, big_endian); - case RT_FONTDIR: - return bin_to_res_fontdir (data, length, big_endian); - case RT_FONT: - return bin_to_res_generic (RES_TYPE_FONT, data, length); - case RT_ACCELERATOR: - return bin_to_res_accelerators (data, length, big_endian); - case RT_RCDATA: - return bin_to_res_rcdata (data, length, big_endian); - case RT_MESSAGETABLE: - return bin_to_res_generic (RES_TYPE_MESSAGETABLE, data, length); - case RT_GROUP_CURSOR: - return bin_to_res_group_cursor (data, length, big_endian); - case RT_GROUP_ICON: - return bin_to_res_group_icon (data, length, big_endian); - case RT_VERSION: - return bin_to_res_version (data, length, big_endian); - } - } -} - -/* Give an error if the binary data is too small. */ - -static void -toosmall (msg) - const char *msg; -{ - fatal (_("%s: not enough binary data"), msg); -} - -/* Swap in a NULL terminated unicode string. */ - -static unichar * -get_unicode (data, length, big_endian, retlen) - const unsigned char *data; - unsigned long length; - int big_endian; - int *retlen; -{ - int c, i; - unichar *ret; - - c = 0; - while (1) - { - if (length < (unsigned long) c * 2 + 2) - toosmall (_("null terminated unicode string")); - if (get_16 (big_endian, data + c * 2) == 0) - break; - ++c; - } - - ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar)); - - for (i = 0; i < c; i++) - ret[i] = get_16 (big_endian, data + i * 2); - ret[i] = 0; - - if (retlen != NULL) - *retlen = c; - - return ret; -} - -/* Get a resource identifier. This returns the number of bytes used. */ - -static int -get_resid (id, data, length, big_endian) - struct res_id *id; - const unsigned char *data; - unsigned long length; - int big_endian; -{ - int first; - - if (length < 2) - toosmall (_("resource ID")); - - first = get_16 (big_endian, data); - if (first == 0xffff) - { - if (length < 4) - toosmall (_("resource ID")); - id->named = 0; - id->u.id = get_16 (big_endian, data + 2); - return 4; - } - else - { - id->named = 1; - id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length); - return id->u.n.length * 2 + 2; - } -} - -/* Convert a resource which just stores uninterpreted data from - binary. */ - -struct res_resource * -bin_to_res_generic (type, data, length) - enum res_type type; - const unsigned char *data; - unsigned long length; -{ - struct res_resource *r; - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = type; - r->u.data.data = data; - r->u.data.length = length; - - return r; -} - -/* Convert a cursor resource from binary. */ - -struct res_resource * -bin_to_res_cursor (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - struct cursor *c; - struct res_resource *r; - - if (length < 4) - toosmall (_("cursor")); - - c = (struct cursor *) res_alloc (sizeof *c); - c->xhotspot = get_16 (big_endian, data); - c->yhotspot = get_16 (big_endian, data + 2); - c->length = length - 4; - c->data = data + 4; - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_CURSOR; - r->u.cursor = c; - - return r; -} - -/* Convert a menu resource from binary. */ - -struct res_resource * -bin_to_res_menu (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - struct res_resource *r; - struct menu *m; - int version, read; - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_MENU; - - m = (struct menu *) res_alloc (sizeof *m); - r->u.menu = m; - - if (length < 2) - toosmall (_("menu header")); - - version = get_16 (big_endian, data); - - if (version == 0) - { - if (length < 4) - toosmall (_("menu header")); - m->help = 0; - m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian, - &read); - } - else if (version == 1) - { - unsigned int offset; - - if (length < 8) - toosmall (_("menuex header")); - m->help = get_32 (big_endian, data + 4); - offset = get_16 (big_endian, data + 2); - if (offset + 4 >= length) - toosmall (_("menuex offset")); - m->items = bin_to_res_menuexitems (data + 4 + offset, - length - (4 + offset), - big_endian, - &read); - } - else - fatal (_("unsupported menu version %d"), version); - - return r; -} - -/* Convert menu items from binary. */ - -static struct menuitem * -bin_to_res_menuitems (data, length, big_endian, read) - const unsigned char *data; - unsigned long length; - int big_endian; - int *read; -{ - struct menuitem *first, **pp; - - first = NULL; - pp = &first; - - *read = 0; - - while (length > 0) - { - int flags, slen, itemlen; - unsigned int stroff; - struct menuitem *mi; - - if (length < 4) - toosmall (_("menuitem header")); - - mi = (struct menuitem *) res_alloc (sizeof *mi); - mi->state = 0; - mi->help = 0; - - flags = get_16 (big_endian, data); - mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU); - - if ((flags & MENUITEM_POPUP) == 0) - stroff = 4; - else - stroff = 2; - - if (length < stroff + 2) - toosmall (_("menuitem header")); - - if (get_16 (big_endian, data + stroff) == 0) - { - slen = 0; - mi->text = NULL; - } - else - mi->text = get_unicode (data + stroff, length - stroff, big_endian, - &slen); - - itemlen = stroff + slen * 2 + 2; - - if ((flags & MENUITEM_POPUP) == 0) - { - mi->popup = NULL; - mi->id = get_16 (big_endian, data + 2); - } - else - { - int subread; - - mi->id = 0; - mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen, - big_endian, &subread); - itemlen += subread; - } - - mi->next = NULL; - *pp = mi; - pp = &mi->next; - - data += itemlen; - length -= itemlen; - *read += itemlen; - - if ((flags & MENUITEM_ENDMENU) != 0) - return first; - } - - return first; -} - -/* Convert menuex items from binary. */ - -static struct menuitem * -bin_to_res_menuexitems (data, length, big_endian, read) - const unsigned char *data; - unsigned long length; - int big_endian; - int *read; -{ - struct menuitem *first, **pp; - - first = NULL; - pp = &first; - - *read = 0; - - while (length > 0) - { - int flags, slen; - unsigned int itemlen; - struct menuitem *mi; - - if (length < 14) - toosmall (_("menuitem header")); - - mi = (struct menuitem *) res_alloc (sizeof *mi); - mi->type = get_32 (big_endian, data); - mi->state = get_32 (big_endian, data + 4); - mi->id = get_16 (big_endian, data + 8); - - flags = get_16 (big_endian, data + 10); - - if (get_16 (big_endian, data + 12) == 0) - { - slen = 0; - mi->text = NULL; - } - else - mi->text = get_unicode (data + 12, length - 12, big_endian, &slen); - - itemlen = 12 + slen * 2 + 2; - itemlen = (itemlen + 3) &~ 3; - - if ((flags & 1) == 0) - { - mi->popup = NULL; - mi->help = 0; - } - else - { - int subread; - - if (length < itemlen + 4) - toosmall (_("menuitem")); - mi->help = get_32 (big_endian, data + itemlen); - itemlen += 4; - - mi->popup = bin_to_res_menuexitems (data + itemlen, - length - itemlen, - big_endian, &subread); - itemlen += subread; - } - - mi->next = NULL; - *pp = mi; - pp = &mi->next; - - data += itemlen; - length -= itemlen; - *read += itemlen; - - if ((flags & 0x80) != 0) - return first; - } - - return first; -} - -/* Convert a dialog resource from binary. */ - -static struct res_resource * -bin_to_res_dialog (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - int version; - struct dialog *d; - int c, sublen, i; - unsigned int off; - struct dialog_control **pp; - struct res_resource *r; - - if (length < 18) - toosmall (_("dialog header")); - - d = (struct dialog *) res_alloc (sizeof *d); - - version = get_16 (big_endian, data); - if (version != 1) - { - d->ex = NULL; - d->style = get_32 (big_endian, data); - d->exstyle = get_32 (big_endian, data + 4); - off = 8; - } - else - { - int signature; - - signature = get_16 (big_endian, data + 2); - if (signature != 0xffff) - fatal (_("unexpected dialog signature %d"), signature); - - d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex)); - d->ex->help = get_32 (big_endian, data + 4); - d->exstyle = get_32 (big_endian, data + 8); - d->style = get_32 (big_endian, data + 12); - off = 16; - } - - if (length < off + 10) - toosmall (_("dialog header")); - - c = get_16 (big_endian, data + off); - d->x = get_16 (big_endian, data + off + 2); - d->y = get_16 (big_endian, data + off + 4); - d->width = get_16 (big_endian, data + off + 6); - d->height = get_16 (big_endian, data + off + 8); - - off += 10; - - sublen = get_resid (&d->menu, data + off, length - off, big_endian); - off += sublen; - - sublen = get_resid (&d->class, data + off, length - off, big_endian); - off += sublen; - - d->caption = get_unicode (data + off, length - off, big_endian, &sublen); - off += sublen * 2 + 2; - - if ((d->style & DS_SETFONT) == 0) - { - d->pointsize = 0; - d->font = NULL; - if (d->ex != NULL) - { - d->ex->weight = 0; - d->ex->italic = 0; - } - } - else - { - if (length < off + 2) - toosmall (_("dialog font point size")); - - d->pointsize = get_16 (big_endian, data + off); - off += 2; - - if (d->ex != NULL) - { - if (length < off + 4) - toosmall (_("dialogex font information")); - d->ex->weight = get_16 (big_endian, data + off); - d->ex->italic = get_16 (big_endian, data + off + 2); - off += 4; - } - - d->font = get_unicode (data + off, length - off, big_endian, &sublen); - off += sublen * 2 + 2; - } - - d->controls = NULL; - pp = &d->controls; - - for (i = 0; i < c; i++) - { - struct dialog_control *dc; - int datalen; - - off = (off + 3) &~ 3; - - dc = (struct dialog_control *) res_alloc (sizeof *dc); - - if (d->ex == NULL) - { - if (length < off + 8) - toosmall (_("dialog control")); - - dc->style = get_32 (big_endian, data + off); - dc->exstyle = get_32 (big_endian, data + off + 4); - dc->help = 0; - off += 8; - } - else - { - if (length < off + 12) - toosmall (_("dialogex control")); - dc->help = get_32 (big_endian, data + off); - dc->exstyle = get_32 (big_endian, data + off + 4); - dc->style = get_32 (big_endian, data + off + 8); - off += 12; - } - - if (length < off + 10) - toosmall (_("dialog control")); - - dc->x = get_16 (big_endian, data + off); - dc->y = get_16 (big_endian, data + off + 2); - dc->width = get_16 (big_endian, data + off + 4); - dc->height = get_16 (big_endian, data + off + 6); - - if (d->ex != NULL) - dc->id = get_32 (big_endian, data + off + 8); - else - dc->id = get_16 (big_endian, data + off + 8); - - off += 10 + (d->ex != NULL ? 2 : 0); - - sublen = get_resid (&dc->class, data + off, length - off, big_endian); - off += sublen; - - sublen = get_resid (&dc->text, data + off, length - off, big_endian); - off += sublen; - - if (length < off + 2) - toosmall (_("dialog control end")); - - datalen = get_16 (big_endian, data + off); - off += 2; - - if (datalen == 0) - dc->data = NULL; - else - { - off = (off + 3) &~ 3; - - if (length < off + datalen) - toosmall (_("dialog control data")); - - dc->data = ((struct rcdata_item *) - res_alloc (sizeof (struct rcdata_item))); - dc->data->next = NULL; - dc->data->type = RCDATA_BUFFER; - dc->data->u.buffer.length = datalen; - dc->data->u.buffer.data = data + off; - - off += datalen; - } - - dc->next = NULL; - *pp = dc; - pp = &dc->next; - } - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_DIALOG; - r->u.dialog = d; - - return r; -} - -/* Convert a stringtable resource from binary. */ - -static struct res_resource * -bin_to_res_string (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - struct stringtable *st; - int i; - struct res_resource *r; - - st = (struct stringtable *) res_alloc (sizeof *st); - - for (i = 0; i < 16; i++) - { - unsigned int slen; - - if (length < 2) - toosmall (_("stringtable string length")); - slen = get_16 (big_endian, data); - st->strings[i].length = slen; - - if (slen > 0) - { - unichar *s; - unsigned int j; - - if (length < 2 + 2 * slen) - toosmall (_("stringtable string")); - - s = (unichar *) res_alloc (slen * sizeof (unichar)); - st->strings[i].string = s; - - for (j = 0; j < slen; j++) - s[j] = get_16 (big_endian, data + 2 + j * 2); - } - - data += 2 + 2 * slen; - length -= 2 + 2 * slen; - } - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_STRINGTABLE; - r->u.stringtable = st; - - return r; -} - -/* Convert a fontdir resource from binary. */ - -static struct res_resource * -bin_to_res_fontdir (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - int c, i; - struct fontdir *first, **pp; - struct res_resource *r; - - if (length < 2) - toosmall (_("fontdir header")); - - c = get_16 (big_endian, data); - - first = NULL; - pp = &first; - - for (i = 0; i < c; i++) - { - struct fontdir *fd; - unsigned int off; - - if (length < 56) - toosmall (_("fontdir")); - - fd = (struct fontdir *) res_alloc (sizeof *fd); - fd->index = get_16 (big_endian, data); - - /* To work out the length of the fontdir data, we must get the - length of the device name and face name strings, even though - we don't store them in the fontdir structure. The - documentation says that these are NULL terminated char - strings, not Unicode strings. */ - - off = 56; - - while (off < length && data[off] != '\0') - ++off; - if (off >= length) - toosmall (_("fontdir device name")); - ++off; - - while (off < length && data[off] != '\0') - ++off; - if (off >= length) - toosmall (_("fontdir face name")); - ++off; - - fd->length = off; - fd->data = data; - - fd->next = NULL; - *pp = fd; - pp = &fd->next; - - /* The documentation does not indicate that any rounding is - required. */ - - data += off; - length -= off; - } - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_FONTDIR; - r->u.fontdir = first; - - return r; -} - -/* Convert an accelerators resource from binary. */ - -static struct res_resource * -bin_to_res_accelerators (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - struct accelerator *first, **pp; - struct res_resource *r; - - first = NULL; - pp = &first; - - while (1) - { - struct accelerator *a; - - if (length < 8) - toosmall (_("accelerator")); - - a = (struct accelerator *) res_alloc (sizeof *a); - - a->flags = get_16 (big_endian, data); - a->key = get_16 (big_endian, data + 2); - a->id = get_16 (big_endian, data + 4); - - a->next = NULL; - *pp = a; - pp = &a->next; - - if ((a->flags & ACC_LAST) != 0) - break; - - data += 8; - length -= 8; - } - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_ACCELERATOR; - r->u.acc = first; - - return r; -} - -/* Convert an rcdata resource from binary. */ - -static struct res_resource * -bin_to_res_rcdata (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - struct rcdata_item *ri; - struct res_resource *r; - - ri = (struct rcdata_item *) res_alloc (sizeof *ri); - - ri->next = NULL; - ri->type = RCDATA_BUFFER; - ri->u.buffer.length = length; - ri->u.buffer.data = data; - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_RCDATA; - r->u.rcdata = ri; - - return r; -} - -/* Convert a group cursor resource from binary. */ - -static struct res_resource * -bin_to_res_group_cursor (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - int type, c, i; - struct group_cursor *first, **pp; - struct res_resource *r; - - if (length < 6) - toosmall (_("group cursor header")); - - type = get_16 (big_endian, data + 2); - if (type != 2) - fatal (_("unexpected group cursor type %d"), type); - - c = get_16 (big_endian, data + 4); - - data += 6; - length -= 6; - - first = NULL; - pp = &first; - - for (i = 0; i < c; i++) - { - struct group_cursor *gc; - - if (length < 14) - toosmall (_("group cursor")); - - gc = (struct group_cursor *) res_alloc (sizeof *gc); - - gc->width = get_16 (big_endian, data); - gc->height = get_16 (big_endian, data + 2); - gc->planes = get_16 (big_endian, data + 4); - gc->bits = get_16 (big_endian, data + 6); - gc->bytes = get_32 (big_endian, data + 8); - gc->index = get_16 (big_endian, data + 12); - - gc->next = NULL; - *pp = gc; - pp = &gc->next; - - data += 14; - length -= 14; - } - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_GROUP_CURSOR; - r->u.group_cursor = first; - - return r; -} - -/* Convert a group icon resource from binary. */ - -static struct res_resource * -bin_to_res_group_icon (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - int type, c, i; - struct group_icon *first, **pp; - struct res_resource *r; - - if (length < 6) - toosmall (_("group icon header")); - - type = get_16 (big_endian, data + 2); - if (type != 1) - fatal (_("unexpected group icon type %d"), type); - - c = get_16 (big_endian, data + 4); - - data += 6; - length -= 6; - - first = NULL; - pp = &first; - - for (i = 0; i < c; i++) - { - struct group_icon *gi; - - if (length < 14) - toosmall (_("group icon")); - - gi = (struct group_icon *) res_alloc (sizeof *gi); - - gi->width = data[0]; - gi->height = data[1]; - gi->colors = data[2]; - gi->planes = get_16 (big_endian, data + 4); - gi->bits = get_16 (big_endian, data + 6); - gi->bytes = get_32 (big_endian, data + 8); - gi->index = get_16 (big_endian, data + 12); - - gi->next = NULL; - *pp = gi; - pp = &gi->next; - - data += 14; - length -= 14; - } - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_GROUP_ICON; - r->u.group_icon = first; - - return r; -} - -/* Extract data from a version header. If KEY is not NULL, then the - key must be KEY; otherwise, the key is returned in *PKEY. This - sets *LEN to the total length, *VALLEN to the value length, *TYPE - to the type, and *OFF to the offset to the children. */ - -static void -get_version_header (data, length, big_endian, key, pkey, len, vallen, type, - off) - const unsigned char *data; - unsigned long length; - int big_endian; - const char *key; - unichar **pkey; - int *len; - int *vallen; - int *type; - int *off; -{ - if (length < 8) - toosmall (key); - - *len = get_16 (big_endian, data); - *vallen = get_16 (big_endian, data + 2); - *type = get_16 (big_endian, data + 4); - - *off = 6; - - length -= 6; - data += 6; - - if (key == NULL) - { - int sublen; - - *pkey = get_unicode (data, length, big_endian, &sublen); - *off += sublen * 2 + 2; - } - else - { - while (1) - { - if (length < 2) - toosmall (key); - if (get_16 (big_endian, data) != (unsigned char) *key) - fatal (_("unexpected version string")); - - *off += 2; - length -= 2; - data += 2; - - if (*key == '\0') - break; - - ++key; - } - } - - *off = (*off + 3) &~ 3; -} - -/* Convert a version resource from binary. */ - -static struct res_resource * -bin_to_res_version (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - int verlen, vallen, type, off; - struct fixed_versioninfo *fi; - struct ver_info *first, **pp; - struct versioninfo *v; - struct res_resource *r; - - get_version_header (data, length, big_endian, "VS_VERSION_INFO", - (unichar *) NULL, &verlen, &vallen, &type, &off); - - if ((unsigned int) verlen != length) - fatal (_("version length %d does not match resource length %lu"), - verlen, length); - - if (type != 0) - fatal (_("unexpected version type %d"), type); - - data += off; - length -= off; - - if (vallen == 0) - fi = NULL; - else - { - unsigned long signature, fiv; - - if (vallen != 52) - fatal (_("unexpected fixed version information length %d"), vallen); - - if (length < 52) - toosmall (_("fixed version info")); - - signature = get_32 (big_endian, data); - if (signature != 0xfeef04bd) - fatal (_("unexpected fixed version signature %lu"), signature); - - fiv = get_32 (big_endian, data + 4); - if (fiv != 0 && fiv != 0x10000) - fatal (_("unexpected fixed version info version %lu"), fiv); - - fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi); - - fi->file_version_ms = get_32 (big_endian, data + 8); - fi->file_version_ls = get_32 (big_endian, data + 12); - fi->product_version_ms = get_32 (big_endian, data + 16); - fi->product_version_ls = get_32 (big_endian, data + 20); - fi->file_flags_mask = get_32 (big_endian, data + 24); - fi->file_flags = get_32 (big_endian, data + 28); - fi->file_os = get_32 (big_endian, data + 32); - fi->file_type = get_32 (big_endian, data + 36); - fi->file_subtype = get_32 (big_endian, data + 40); - fi->file_date_ms = get_32 (big_endian, data + 44); - fi->file_date_ls = get_32 (big_endian, data + 48); - - data += 52; - length -= 52; - } - - first = NULL; - pp = &first; - - while (length > 0) - { - struct ver_info *vi; - int ch; - - if (length < 8) - toosmall (_("version var info")); - - vi = (struct ver_info *) res_alloc (sizeof *vi); - - ch = get_16 (big_endian, data + 6); - - if (ch == 'S') - { - struct ver_stringinfo **ppvs; - - vi->type = VERINFO_STRING; - - get_version_header (data, length, big_endian, "StringFileInfo", - (unichar *) NULL, &verlen, &vallen, &type, - &off); - - if (vallen != 0) - fatal (_("unexpected stringfileinfo value length %d"), vallen); - - data += off; - length -= off; - - get_version_header (data, length, big_endian, (const char *) NULL, - &vi->u.string.language, &verlen, &vallen, - &type, &off); - - if (vallen != 0) - fatal (_("unexpected version stringtable value length %d"), vallen); - - data += off; - length -= off; - verlen -= off; - - vi->u.string.strings = NULL; - ppvs = &vi->u.string.strings; - - /* It's convenient to round verlen to a 4 byte alignment, - since we round the subvariables in the loop. */ - verlen = (verlen + 3) &~ 3; - - while (verlen > 0) - { - struct ver_stringinfo *vs; - int subverlen, vslen, valoff; - - vs = (struct ver_stringinfo *) res_alloc (sizeof *vs); - - get_version_header (data, length, big_endian, - (const char *) NULL, &vs->key, &subverlen, - &vallen, &type, &off); - - subverlen = (subverlen + 3) &~ 3; - - data += off; - length -= off; - - vs->value = get_unicode (data, length, big_endian, &vslen); - valoff = vslen * 2 + 2; - valoff = (valoff + 3) &~ 3; - - if (off + valoff != subverlen) - fatal (_("unexpected version string length %d != %d + %d"), - subverlen, off, valoff); - - vs->next = NULL; - *ppvs = vs; - ppvs = &vs->next; - - data += valoff; - length -= valoff; - - if (verlen < subverlen) - fatal (_("unexpected version string length %d < %d"), - verlen, subverlen); - - verlen -= subverlen; - } - } - else if (ch == 'V') - { - struct ver_varinfo **ppvv; - - vi->type = VERINFO_VAR; - - get_version_header (data, length, big_endian, "VarFileInfo", - (unichar *) NULL, &verlen, &vallen, &type, - &off); - - if (vallen != 0) - fatal (_("unexpected varfileinfo value length %d"), vallen); - - data += off; - length -= off; - - get_version_header (data, length, big_endian, (const char *) NULL, - &vi->u.var.key, &verlen, &vallen, &type, &off); - - data += off; - length -= off; - - vi->u.var.var = NULL; - ppvv = &vi->u.var.var; - - while (vallen > 0) - { - struct ver_varinfo *vv; - - if (length < 4) - toosmall (_("version varfileinfo")); - - vv = (struct ver_varinfo *) res_alloc (sizeof *vv); - - vv->language = get_16 (big_endian, data); - vv->charset = get_16 (big_endian, data + 2); - - vv->next = NULL; - *ppvv = vv; - ppvv = &vv->next; - - data += 4; - length -= 4; - - if (vallen < 4) - fatal (_("unexpected version value length %d"), vallen); - - vallen -= 4; - } - } - else - fatal (_("unexpected version string")); - - vi->next = NULL; - *pp = vi; - pp = &vi->next; - } - - v = (struct versioninfo *) res_alloc (sizeof *v); - v->fixed = fi; - v->var = first; - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_VERSIONINFO; - r->u.versioninfo = v; - - return r; -} - -/* Convert an arbitrary user defined resource from binary. */ - -static struct res_resource * -bin_to_res_userdata (data, length, big_endian) - const unsigned char *data; - unsigned long length; - int big_endian; -{ - struct rcdata_item *ri; - struct res_resource *r; - - ri = (struct rcdata_item *) res_alloc (sizeof *ri); - - ri->next = NULL; - ri->type = RCDATA_BUFFER; - ri->u.buffer.length = length; - ri->u.buffer.data = data; - - r = (struct res_resource *) res_alloc (sizeof *r); - r->type = RES_TYPE_USERDATA; - r->u.rcdata = ri; - - return r; -} - -/* Macros to swap out values. */ - -#define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s))) -#define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s))) - -/* Local functions used to convert resources to binary format. */ - -static void dword_align_bin PARAMS ((struct bindata ***, unsigned long *)); -static struct bindata *resid_to_bin PARAMS ((struct res_id, int)); -static struct bindata *unicode_to_bin PARAMS ((const unichar *, int)); -static struct bindata *res_to_bin_accelerator - PARAMS ((const struct accelerator *, int)); -static struct bindata *res_to_bin_cursor - PARAMS ((const struct cursor *, int)); -static struct bindata *res_to_bin_group_cursor - PARAMS ((const struct group_cursor *, int)); -static struct bindata *res_to_bin_dialog - PARAMS ((const struct dialog *, int)); -static struct bindata *res_to_bin_fontdir - PARAMS ((const struct fontdir *, int)); -static struct bindata *res_to_bin_group_icon - PARAMS ((const struct group_icon *, int)); -static struct bindata *res_to_bin_menu - PARAMS ((const struct menu *, int)); -static struct bindata *res_to_bin_menuitems - PARAMS ((const struct menuitem *, int)); -static struct bindata *res_to_bin_menuexitems - PARAMS ((const struct menuitem *, int)); -static struct bindata *res_to_bin_rcdata - PARAMS ((const struct rcdata_item *, int)); -static struct bindata *res_to_bin_stringtable - PARAMS ((const struct stringtable *, int)); -static struct bindata *string_to_unicode_bin PARAMS ((const char *, int)); -static struct bindata *res_to_bin_versioninfo - PARAMS ((const struct versioninfo *, int)); -static struct bindata *res_to_bin_generic - PARAMS ((unsigned long, const unsigned char *)); - -/* Convert a resource to binary. */ - -struct bindata * -res_to_bin (res, big_endian) - const struct res_resource *res; - int big_endian; -{ - switch (res->type) - { - default: - abort (); - case RES_TYPE_BITMAP: - case RES_TYPE_FONT: - case RES_TYPE_ICON: - case RES_TYPE_MESSAGETABLE: - return res_to_bin_generic (res->u.data.length, res->u.data.data); - case RES_TYPE_ACCELERATOR: - return res_to_bin_accelerator (res->u.acc, big_endian); - case RES_TYPE_CURSOR: - return res_to_bin_cursor (res->u.cursor, big_endian); - case RES_TYPE_GROUP_CURSOR: - return res_to_bin_group_cursor (res->u.group_cursor, big_endian); - case RES_TYPE_DIALOG: - return res_to_bin_dialog (res->u.dialog, big_endian); - case RES_TYPE_FONTDIR: - return res_to_bin_fontdir (res->u.fontdir, big_endian); - case RES_TYPE_GROUP_ICON: - return res_to_bin_group_icon (res->u.group_icon, big_endian); - case RES_TYPE_MENU: - return res_to_bin_menu (res->u.menu, big_endian); - case RES_TYPE_RCDATA: - return res_to_bin_rcdata (res->u.rcdata, big_endian); - case RES_TYPE_STRINGTABLE: - return res_to_bin_stringtable (res->u.stringtable, big_endian); - case RES_TYPE_USERDATA: - return res_to_bin_rcdata (res->u.rcdata, big_endian); - case RES_TYPE_VERSIONINFO: - return res_to_bin_versioninfo (res->u.versioninfo, big_endian); - } -} - -/* Align to a 32 bit boundary. PPP points to the of a list of bindata - structures. LENGTH points to the length of the structures. If - necessary, this adds a new bindata to bring length up to a 32 bit - boundary. It updates *PPP and *LENGTH. */ - -static void -dword_align_bin (ppp, length) - struct bindata ***ppp; - unsigned long *length; -{ - int add; - struct bindata *d; - - if ((*length & 3) == 0) - return; - - add = 4 - (*length & 3); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = add; - d->data = (unsigned char *) reswr_alloc (add); - memset (d->data, 0, add); - - d->next = NULL; - **ppp = d; - *ppp = &(**ppp)->next; - - *length += add; -} - -/* Convert a resource ID to binary. This always returns exactly one - bindata structure. */ - -static struct bindata * -resid_to_bin (id, big_endian) - struct res_id id; - int big_endian; -{ - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - - if (! id.named) - { - d->length = 4; - d->data = (unsigned char *) reswr_alloc (4); - put_16 (big_endian, 0xffff, d->data); - put_16 (big_endian, id.u.id, d->data + 2); - } - else - { - int i; - - d->length = id.u.n.length * 2 + 2; - d->data = (unsigned char *) reswr_alloc (d->length); - for (i = 0; i < id.u.n.length; i++) - put_16 (big_endian, id.u.n.name[i], d->data + i * 2); - put_16 (big_endian, 0, d->data + i * 2); - } - - d->next = NULL; - - return d; -} - -/* Convert a null terminated unicode string to binary. This always - returns exactly one bindata structure. */ - -static struct bindata * -unicode_to_bin (str, big_endian) - const unichar *str; - int big_endian; -{ - int len; - struct bindata *d; - - len = 0; - if (str != NULL) - { - const unichar *s; - - for (s = str; *s != 0; s++) - ++len; - } - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = len * 2 + 2; - d->data = (unsigned char *) reswr_alloc (d->length); - - if (str == NULL) - put_16 (big_endian, 0, d->data); - else - { - const unichar *s; - int i; - - for (s = str, i = 0; *s != 0; s++, i++) - put_16 (big_endian, *s, d->data + i * 2); - put_16 (big_endian, 0, d->data + i * 2); - } - - d->next = NULL; - - return d; -} - -/* Convert an accelerator resource to binary. */ - -static struct bindata * -res_to_bin_accelerator (accelerators, big_endian) - const struct accelerator *accelerators; - int big_endian; -{ - struct bindata *first, **pp; - const struct accelerator *a; - - first = NULL; - pp = &first; - - for (a = accelerators; a != NULL; a = a->next) - { - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 8; - d->data = (unsigned char *) reswr_alloc (8); - - put_16 (big_endian, - a->flags | (a->next != NULL ? 0 : ACC_LAST), - d->data); - put_16 (big_endian, a->key, d->data + 2); - put_16 (big_endian, a->id, d->data + 4); - put_16 (big_endian, 0, d->data + 8); - - d->next = NULL; - *pp = d; - pp = &d->next; - } - - return first; -} - -/* Convert a cursor resource to binary. */ - -static struct bindata * -res_to_bin_cursor (c, big_endian) - const struct cursor *c; - int big_endian; -{ - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 4; - d->data = (unsigned char *) reswr_alloc (4); - - put_16 (big_endian, c->xhotspot, d->data); - put_16 (big_endian, c->yhotspot, d->data + 2); - - d->next = (struct bindata *) reswr_alloc (sizeof *d); - d->next->length = c->length; - d->next->data = (unsigned char *) c->data; - d->next->next = NULL; - - return d; -} - -/* Convert a group cursor resource to binary. */ - -static struct bindata * -res_to_bin_group_cursor (group_cursors, big_endian) - const struct group_cursor *group_cursors; - int big_endian; -{ - struct bindata *first, **pp; - int c; - const struct group_cursor *gc; - - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = 6; - first->data = (unsigned char *) reswr_alloc (6); - - put_16 (big_endian, 0, first->data); - put_16 (big_endian, 2, first->data + 2); - - first->next = NULL; - pp = &first->next; - - c = 0; - for (gc = group_cursors; gc != NULL; gc = gc->next) - { - struct bindata *d; - - ++c; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 14; - d->data = (unsigned char *) reswr_alloc (14); - - put_16 (big_endian, gc->width, d->data); - put_16 (big_endian, gc->height, d->data + 2); - put_16 (big_endian, gc->planes, d->data + 4); - put_16 (big_endian, gc->bits, d->data + 6); - put_32 (big_endian, gc->bytes, d->data + 8); - put_16 (big_endian, gc->index, d->data + 12); - - d->next = NULL; - *pp = d; - pp = &d->next; - } - - put_16 (big_endian, c, first->data + 4); - - return first; -} - -/* Convert a dialog resource to binary. */ - -static struct bindata * -res_to_bin_dialog (dialog, big_endian) - const struct dialog *dialog; - int big_endian; -{ - int dialogex; - struct bindata *first, **pp; - unsigned long length; - int off, c; - struct dialog_control *dc; - - dialogex = extended_dialog (dialog); - - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = dialogex ? 26 : 18; - first->data = (unsigned char *) reswr_alloc (first->length); - - length = first->length; - - if (! dialogex) - { - put_32 (big_endian, dialog->style, first->data); - put_32 (big_endian, dialog->exstyle, first->data + 4); - off = 8; - } - else - { - put_16 (big_endian, 1, first->data); - put_16 (big_endian, 0xffff, first->data + 2); - - if (dialog->ex == NULL) - put_32 (big_endian, 0, first->data + 4); - else - put_32 (big_endian, dialog->ex->help, first->data + 4); - put_32 (big_endian, dialog->exstyle, first->data + 8); - put_32 (big_endian, dialog->style, first->data + 12); - off = 16; - } - - put_16 (big_endian, dialog->x, first->data + off + 2); - put_16 (big_endian, dialog->y, first->data + off + 4); - put_16 (big_endian, dialog->width, first->data + off + 6); - put_16 (big_endian, dialog->height, first->data + off + 8); - - pp = &first->next; - - *pp = resid_to_bin (dialog->menu, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - *pp = resid_to_bin (dialog->class, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - *pp = unicode_to_bin (dialog->caption, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - if ((dialog->style & DS_SETFONT) != 0) - { - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = dialogex ? 6 : 2; - d->data = (unsigned char *) reswr_alloc (d->length); - - length += d->length; - - put_16 (big_endian, dialog->pointsize, d->data); - - if (dialogex) - { - if (dialog->ex == NULL) - { - put_16 (big_endian, 0, d->data + 2); - put_16 (big_endian, 0, d->data + 4); - } - else - { - put_16 (big_endian, dialog->ex->weight, d->data + 2); - put_16 (big_endian, dialog->ex->italic, d->data + 4); - } - } - - *pp = d; - pp = &d->next; - - *pp = unicode_to_bin (dialog->font, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - } - - c = 0; - for (dc = dialog->controls; dc != NULL; dc = dc->next) - { - struct bindata *d; - int dcoff; - - ++c; - - dword_align_bin (&pp, &length); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = dialogex ? 24 : 18; - d->data = (unsigned char *) reswr_alloc (d->length); - - length += d->length; - - if (! dialogex) - { - put_32 (big_endian, dc->style, d->data); - put_32 (big_endian, dc->exstyle, d->data + 4); - dcoff = 8; - } - else - { - put_32 (big_endian, dc->help, d->data); - put_32 (big_endian, dc->exstyle, d->data + 4); - put_32 (big_endian, dc->style, d->data + 8); - dcoff = 12; - } - - put_16 (big_endian, dc->x, d->data + dcoff); - put_16 (big_endian, dc->y, d->data + dcoff + 2); - put_16 (big_endian, dc->width, d->data + dcoff + 4); - put_16 (big_endian, dc->height, d->data + dcoff + 6); - - if (dialogex) - put_32 (big_endian, dc->id, d->data + dcoff + 8); - else - put_16 (big_endian, dc->id, d->data + dcoff + 8); - - *pp = d; - pp = &d->next; - - *pp = resid_to_bin (dc->class, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - *pp = resid_to_bin (dc->text, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 2; - d->data = (unsigned char *) reswr_alloc (2); - - length += 2; - - d->next = NULL; - *pp = d; - pp = &d->next; - - if (dc->data == NULL) - put_16 (big_endian, 0, d->data); - else - { - unsigned long sublen; - - dword_align_bin (&pp, &length); - - *pp = res_to_bin_rcdata (dc->data, big_endian); - sublen = 0; - while (*pp != NULL) - { - sublen += (*pp)->length; - pp = &(*pp)->next; - } - - put_16 (big_endian, sublen, d->data); - - length += sublen; - } - } - put_16 (big_endian, c, first->data + off); - - return first; -} - -/* Convert a fontdir resource to binary. */ - -static struct bindata * -res_to_bin_fontdir (fontdirs, big_endian) - const struct fontdir *fontdirs; - int big_endian; -{ - struct bindata *first, **pp; - int c; - const struct fontdir *fd; - - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = 2; - first->data = (unsigned char *) reswr_alloc (2); - - first->next = NULL; - pp = &first->next; - - c = 0; - for (fd = fontdirs; fd != NULL; fd = fd->next) - { - struct bindata *d; - - ++c; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 2; - d->data = (unsigned char *) reswr_alloc (2); - - put_16 (big_endian, fd->index, d->data); - - *pp = d; - pp = &d->next; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = fd->length; - d->data = (unsigned char *) fd->data; - - d->next = NULL; - *pp = d; - pp = &d->next; - } - - put_16 (big_endian, c, first->data); - - return first; -} - -/* Convert a group icon resource to binary. */ - -static struct bindata * -res_to_bin_group_icon (group_icons, big_endian) - const struct group_icon *group_icons; - int big_endian; -{ - struct bindata *first, **pp; - int c; - const struct group_icon *gi; - - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = 6; - first->data = (unsigned char *) reswr_alloc (6); - - put_16 (big_endian, 0, first->data); - put_16 (big_endian, 1, first->data + 2); - - first->next = NULL; - pp = &first->next; - - c = 0; - for (gi = group_icons; gi != NULL; gi = gi->next) - { - struct bindata *d; - - ++c; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 14; - d->data = (unsigned char *) reswr_alloc (14); - - d->data[0] = gi->width; - d->data[1] = gi->height; - d->data[2] = gi->colors; - d->data[3] = 0; - put_16 (big_endian, gi->planes, d->data + 4); - put_16 (big_endian, gi->bits, d->data + 6); - put_32 (big_endian, gi->bytes, d->data + 8); - put_16 (big_endian, gi->index, d->data + 12); - - d->next = NULL; - *pp = d; - pp = &d->next; - } - - put_16 (big_endian, c, first->data + 4); - - return first; -} - -/* Convert a menu resource to binary. */ - -static struct bindata * -res_to_bin_menu (menu, big_endian) - const struct menu *menu; - int big_endian; -{ - int menuex; - struct bindata *d; - - menuex = extended_menu (menu); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = menuex ? 8 : 4; - d->data = (unsigned char *) reswr_alloc (d->length); - - if (! menuex) - { - put_16 (big_endian, 0, d->data); - put_16 (big_endian, 0, d->data + 2); - - d->next = res_to_bin_menuitems (menu->items, big_endian); - } - else - { - put_16 (big_endian, 1, d->data); - put_16 (big_endian, 4, d->data + 2); - put_32 (big_endian, menu->help, d->data + 4); - - d->next = res_to_bin_menuexitems (menu->items, big_endian); - } - - return d; -} - -/* Convert menu items to binary. */ - -static struct bindata * -res_to_bin_menuitems (items, big_endian) - const struct menuitem *items; - int big_endian; -{ - struct bindata *first, **pp; - const struct menuitem *mi; - - first = NULL; - pp = &first; - - for (mi = items; mi != NULL; mi = mi->next) - { - struct bindata *d; - int flags; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = mi->popup == NULL ? 4 : 2; - d->data = (unsigned char *) reswr_alloc (d->length); - - flags = mi->type; - if (mi->next == NULL) - flags |= MENUITEM_ENDMENU; - if (mi->popup != NULL) - flags |= MENUITEM_POPUP; - - put_16 (big_endian, flags, d->data); - - if (mi->popup == NULL) - put_16 (big_endian, mi->id, d->data + 2); - - *pp = d; - pp = &d->next; - - *pp = unicode_to_bin (mi->text, big_endian); - pp = &(*pp)->next; - - if (mi->popup != NULL) - { - *pp = res_to_bin_menuitems (mi->popup, big_endian); - while (*pp != NULL) - pp = &(*pp)->next; - } - } - - return first; -} - -/* Convert menuex items to binary. */ - -static struct bindata * -res_to_bin_menuexitems (items, big_endian) - const struct menuitem *items; - int big_endian; -{ - struct bindata *first, **pp; - unsigned long length; - const struct menuitem *mi; - - first = NULL; - pp = &first; - - length = 0; - - for (mi = items; mi != NULL; mi = mi->next) - { - struct bindata *d; - int flags; - - dword_align_bin (&pp, &length); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 12; - d->data = (unsigned char *) reswr_alloc (12); - - length += 12; - - put_32 (big_endian, mi->type, d->data); - put_32 (big_endian, mi->state, d->data + 4); - put_16 (big_endian, mi->id, d->data + 8); - - flags = 0; - if (mi->next == NULL) - flags |= 0x80; - if (mi->popup != NULL) - flags |= 1; - put_16 (big_endian, flags, d->data + 10); - - *pp = d; - pp = &d->next; - - *pp = unicode_to_bin (mi->text, big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - if (mi->popup != NULL) - { - dword_align_bin (&pp, &length); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 4; - d->data = (unsigned char *) reswr_alloc (4); - - put_32 (big_endian, mi->help, d->data); - - *pp = d; - pp = &d->next; - - *pp = res_to_bin_menuexitems (mi->popup, big_endian); - while (*pp != NULL) - { - length += (*pp)->length; - pp = &(*pp)->next; - } - } - } - - return first; -} - -/* Convert an rcdata resource to binary. This is also used to convert - other information which happens to be stored in rcdata_item lists - to binary. */ - -static struct bindata * -res_to_bin_rcdata (items, big_endian) - const struct rcdata_item *items; - int big_endian; -{ - struct bindata *first, **pp; - const struct rcdata_item *ri; - - first = NULL; - pp = &first; - - for (ri = items; ri != NULL; ri = ri->next) - { - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - - switch (ri->type) - { - default: - abort (); - - case RCDATA_WORD: - d->length = 2; - d->data = (unsigned char *) reswr_alloc (2); - put_16 (big_endian, ri->u.word, d->data); - break; - - case RCDATA_DWORD: - d->length = 4; - d->data = (unsigned char *) reswr_alloc (4); - put_32 (big_endian, ri->u.dword, d->data); - break; - - case RCDATA_STRING: - d->length = ri->u.string.length; - d->data = (unsigned char *) ri->u.string.s; - break; - - case RCDATA_WSTRING: - { - unsigned long i; - - d->length = ri->u.wstring.length * 2; - d->data = (unsigned char *) reswr_alloc (d->length); - for (i = 0; i < ri->u.wstring.length; i++) - put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2); - break; - } - - case RCDATA_BUFFER: - d->length = ri->u.buffer.length; - d->data = (unsigned char *) ri->u.buffer.data; - break; - } - - d->next = NULL; - *pp = d; - pp = &d->next; - } - - return first; -} - -/* Convert a stringtable resource to binary. */ - -static struct bindata * -res_to_bin_stringtable (st, big_endian) - const struct stringtable *st; - int big_endian; -{ - struct bindata *first, **pp; - int i; - - first = NULL; - pp = &first; - - for (i = 0; i < 16; i++) - { - int slen, j; - struct bindata *d; - unichar *s; - - slen = st->strings[i].length; - s = st->strings[i].string; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 2 + slen * 2; - d->data = (unsigned char *) reswr_alloc (d->length); - - put_16 (big_endian, slen, d->data); - - for (j = 0; j < slen; j++) - put_16 (big_endian, s[j], d->data + 2 + j * 2); - - d->next = NULL; - *pp = d; - pp = &d->next; - } - - return first; -} - -/* Convert an ASCII string to a unicode binary string. This always - returns exactly one bindata structure. */ - -static struct bindata * -string_to_unicode_bin (s, big_endian) - const char *s; - int big_endian; -{ - size_t len, i; - struct bindata *d; - - len = strlen (s); - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = len * 2 + 2; - d->data = (unsigned char *) reswr_alloc (d->length); - - for (i = 0; i < len; i++) - put_16 (big_endian, s[i], d->data + i * 2); - put_16 (big_endian, 0, d->data + i * 2); - - d->next = NULL; - - return d; -} - -/* Convert a versioninfo resource to binary. */ - -static struct bindata * -res_to_bin_versioninfo (versioninfo, big_endian) - const struct versioninfo *versioninfo; - int big_endian; -{ - struct bindata *first, **pp; - unsigned long length; - struct ver_info *vi; - - first = (struct bindata *) reswr_alloc (sizeof *first); - first->length = 6; - first->data = (unsigned char *) reswr_alloc (6); - - length = 6; - - if (versioninfo->fixed == NULL) - put_16 (big_endian, 0, first->data + 2); - else - put_16 (big_endian, 52, first->data + 2); - - put_16 (big_endian, 0, first->data + 4); - - pp = &first->next; - - *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian); - length += (*pp)->length; - pp = &(*pp)->next; - - dword_align_bin (&pp, &length); - - if (versioninfo->fixed != NULL) - { - const struct fixed_versioninfo *fi; - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = 52; - d->data = (unsigned char *) reswr_alloc (52); - - length += 52; - - fi = versioninfo->fixed; - - put_32 (big_endian, 0xfeef04bd, d->data); - put_32 (big_endian, 0x10000, d->data + 4); - put_32 (big_endian, fi->file_version_ms, d->data + 8); - put_32 (big_endian, fi->file_version_ls, d->data + 12); - put_32 (big_endian, fi->product_version_ms, d->data + 16); - put_32 (big_endian, fi->product_version_ls, d->data + 20); - put_32 (big_endian, fi->file_flags_mask, d->data + 24); - put_32 (big_endian, fi->file_flags, d->data + 28); - put_32 (big_endian, fi->file_os, d->data + 32); - put_32 (big_endian, fi->file_type, d->data + 36); - put_32 (big_endian, fi->file_subtype, d->data + 40); - put_32 (big_endian, fi->file_date_ms, d->data + 44); - put_32 (big_endian, fi->file_date_ls, d->data + 48); - - d->next = NULL; - *pp = d; - pp = &d->next; - } - - for (vi = versioninfo->var; vi != NULL; vi = vi->next) - { - struct bindata *vid; - unsigned long vilen; - - dword_align_bin (&pp, &length); - - vid = (struct bindata *) reswr_alloc (sizeof *vid); - vid->length = 6; - vid->data = (unsigned char *) reswr_alloc (6); - - length += 6; - vilen = 6; - - put_16 (big_endian, 0, vid->data + 2); - put_16 (big_endian, 0, vid->data + 4); - - *pp = vid; - pp = &vid->next; - - switch (vi->type) - { - default: - abort (); - - case VERINFO_STRING: - { - unsigned long hold, vslen; - struct bindata *vsd; - const struct ver_stringinfo *vs; - - *pp = string_to_unicode_bin ("StringFileInfo", big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - pp = &(*pp)->next; - - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; - - vsd = (struct bindata *) reswr_alloc (sizeof *vsd); - vsd->length = 6; - vsd->data = (unsigned char *) reswr_alloc (6); - - length += 6; - vilen += 6; - vslen = 6; - - put_16 (big_endian, 0, vsd->data + 2); - put_16 (big_endian, 0, vsd->data + 4); - - *pp = vsd; - pp = &vsd->next; - - *pp = unicode_to_bin (vi->u.string.language, big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - vslen += (*pp)->length; - pp = &(*pp)->next; - - for (vs = vi->u.string.strings; vs != NULL; vs = vs->next) - { - struct bindata *vssd; - unsigned long vsslen; - - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; - vslen += length - hold; - - vssd = (struct bindata *) reswr_alloc (sizeof *vssd); - vssd->length = 6; - vssd->data = (unsigned char *) reswr_alloc (6); - - length += 6; - vilen += 6; - vslen += 6; - vsslen = 6; - - put_16 (big_endian, 1, vssd->data + 4); - - *pp = vssd; - pp = &vssd->next; - - *pp = unicode_to_bin (vs->key, big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - vslen += (*pp)->length; - vsslen += (*pp)->length; - pp = &(*pp)->next; - - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; - vslen += length - hold; - vsslen += length - hold; - - *pp = unicode_to_bin (vs->value, big_endian); - put_16 (big_endian, (*pp)->length / 2, vssd->data + 2); - length += (*pp)->length; - vilen += (*pp)->length; - vslen += (*pp)->length; - vsslen += (*pp)->length; - pp = &(*pp)->next; - - put_16 (big_endian, vsslen, vssd->data); - } - - put_16 (big_endian, vslen, vsd->data); - - break; - } - - case VERINFO_VAR: - { - unsigned long hold, vvlen, vvvlen; - struct bindata *vvd; - const struct ver_varinfo *vv; - - *pp = string_to_unicode_bin ("VarFileInfo", big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - pp = &(*pp)->next; - - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; - - vvd = (struct bindata *) reswr_alloc (sizeof *vvd); - vvd->length = 6; - vvd->data = (unsigned char *) reswr_alloc (6); - - length += 6; - vilen += 6; - vvlen = 6; - - put_16 (big_endian, 0, vvd->data + 4); - - *pp = vvd; - pp = &vvd->next; - - *pp = unicode_to_bin (vi->u.var.key, big_endian); - length += (*pp)->length; - vilen += (*pp)->length; - vvlen += (*pp)->length; - pp = &(*pp)->next; - - hold = length; - dword_align_bin (&pp, &length); - vilen += length - hold; - vvlen += length - hold; - - vvvlen = 0; - - for (vv = vi->u.var.var; vv != NULL; vv = vv->next) - { - struct bindata *vvsd; - - vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd); - vvsd->length = 4; - vvsd->data = (unsigned char *) reswr_alloc (4); - - length += 4; - vilen += 4; - vvlen += 4; - vvvlen += 4; - - put_16 (big_endian, vv->language, vvsd->data); - put_16 (big_endian, vv->charset, vvsd->data + 2); - - vvsd->next = NULL; - *pp = vvsd; - pp = &vvsd->next; - } - - put_16 (big_endian, vvlen, vvd->data); - put_16 (big_endian, vvvlen, vvd->data + 2); - - break; - } - } - - put_16 (big_endian, vilen, vid->data); - } - - put_16 (big_endian, length, first->data); - - return first; -} - -/* Convert a generic resource to binary. */ - -static struct bindata * -res_to_bin_generic (length, data) - unsigned long length; - const unsigned char *data; -{ - struct bindata *d; - - d = (struct bindata *) reswr_alloc (sizeof *d); - d->length = length; - d->data = (unsigned char *) data; - - d->next = NULL; - - return d; -} |