resbin.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,388 行 · 第 1/4 页
C
2,388 行
/* resbin.c -- manipulate the Windows binary resource format. Copyright 1997, 1998, 1999 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 voidtoosmall (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 intget_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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?