Back to index

cell-binutils  2.17cvs20070401
resbin.c
Go to the documentation of this file.
00001 /* resbin.c -- manipulate the Windows binary resource format.
00002    Copyright 1997, 1998, 1999, 2002, 2003
00003    Free Software Foundation, Inc.
00004    Written by Ian Lance Taylor, Cygnus Support.
00005 
00006    This file is part of GNU Binutils.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00021    02110-1301, USA.  */
00022 
00023 /* This file contains functions to convert between the binary resource
00024    format and the internal structures that we want to use.  The same
00025    binary resource format is used in both res and COFF files.  */
00026 
00027 #include "bfd.h"
00028 #include "bucomm.h"
00029 #include "libiberty.h"
00030 #include "windres.h"
00031 
00032 /* Macros to swap in values.  */
00033 
00034 #define get_8(s)      (*((unsigned char *)(s)))
00035 #define get_16(be, s) ((be) ? bfd_getb16 (s) : bfd_getl16 (s))
00036 #define get_32(be, s) ((be) ? bfd_getb32 (s) : bfd_getl32 (s))
00037 
00038 /* Local functions.  */
00039 
00040 static void toosmall (const char *);
00041 
00042 static unichar *get_unicode
00043   (const unsigned char *, unsigned long, int, int *);
00044 static int get_resid
00045   (struct res_id *, const unsigned char *, unsigned long, int);
00046 static struct res_resource *bin_to_res_generic
00047   (enum res_type, const unsigned char *, unsigned long);
00048 static struct res_resource *bin_to_res_cursor
00049   (const unsigned char *, unsigned long, int);
00050 static struct res_resource *bin_to_res_menu
00051   (const unsigned char *, unsigned long, int);
00052 static struct menuitem *bin_to_res_menuitems
00053   (const unsigned char *, unsigned long, int, int *);
00054 static struct menuitem *bin_to_res_menuexitems
00055   (const unsigned char *, unsigned long, int, int *);
00056 static struct res_resource *bin_to_res_dialog
00057   (const unsigned char *, unsigned long, int);
00058 static struct res_resource *bin_to_res_string
00059   (const unsigned char *, unsigned long, int);
00060 static struct res_resource *bin_to_res_fontdir
00061   (const unsigned char *, unsigned long, int);
00062 static struct res_resource *bin_to_res_accelerators
00063   (const unsigned char *, unsigned long, int);
00064 static struct res_resource *bin_to_res_rcdata
00065   (const unsigned char *, unsigned long, int);
00066 static struct res_resource *bin_to_res_group_cursor
00067   (const unsigned char *, unsigned long, int);
00068 static struct res_resource *bin_to_res_group_icon
00069   (const unsigned char *, unsigned long, int);
00070 static struct res_resource *bin_to_res_version
00071   (const unsigned char *, unsigned long, int);
00072 static struct res_resource *bin_to_res_userdata
00073   (const unsigned char *, unsigned long, int);
00074 static void get_version_header
00075   (const unsigned char *, unsigned long, int, const char *,
00076    unichar **, int *, int *, int *, int *);
00077 
00078 /* Given a resource type ID, a pointer to data, a length, return a
00079    res_resource structure which represents that resource.  The caller
00080    is responsible for initializing the res_info and coff_info fields
00081    of the returned structure.  */
00082 
00083 struct res_resource *
00084 bin_to_res (struct res_id type, const unsigned char *data,
00085            unsigned long length, int big_endian)
00086 {
00087   if (type.named)
00088     return bin_to_res_userdata (data, length, big_endian);
00089   else
00090     {
00091       switch (type.u.id)
00092        {
00093        default:
00094          return bin_to_res_userdata (data, length, big_endian);
00095        case RT_CURSOR:
00096          return bin_to_res_cursor (data, length, big_endian);
00097        case RT_BITMAP:
00098          return bin_to_res_generic (RES_TYPE_BITMAP, data, length);
00099        case RT_ICON:
00100          return bin_to_res_generic (RES_TYPE_ICON, data, length);
00101        case RT_MENU:
00102          return bin_to_res_menu (data, length, big_endian);
00103        case RT_DIALOG:
00104          return bin_to_res_dialog (data, length, big_endian);
00105        case RT_STRING:
00106          return bin_to_res_string (data, length, big_endian);
00107        case RT_FONTDIR:
00108          return bin_to_res_fontdir (data, length, big_endian);
00109        case RT_FONT:
00110          return bin_to_res_generic (RES_TYPE_FONT, data, length);
00111        case RT_ACCELERATOR:
00112          return bin_to_res_accelerators (data, length, big_endian);
00113        case RT_RCDATA:
00114          return bin_to_res_rcdata (data, length, big_endian);
00115        case RT_MESSAGETABLE:
00116          return bin_to_res_generic (RES_TYPE_MESSAGETABLE, data, length);
00117        case RT_GROUP_CURSOR:
00118          return bin_to_res_group_cursor (data, length, big_endian);
00119        case RT_GROUP_ICON:
00120          return bin_to_res_group_icon (data, length, big_endian);
00121        case RT_VERSION:
00122          return bin_to_res_version (data, length, big_endian);
00123        }
00124     }
00125 }
00126 
00127 /* Give an error if the binary data is too small.  */
00128 
00129 static void
00130 toosmall (const char *msg)
00131 {
00132   fatal (_("%s: not enough binary data"), msg);
00133 }
00134 
00135 /* Swap in a NULL terminated unicode string.  */
00136 
00137 static unichar *
00138 get_unicode (const unsigned char *data, unsigned long length,
00139             int big_endian, int *retlen)
00140 {
00141   int c, i;
00142   unichar *ret;
00143 
00144   c = 0;
00145   while (1)
00146     {
00147       if (length < (unsigned long) c * 2 + 2)
00148        toosmall (_("null terminated unicode string"));
00149       if (get_16 (big_endian, data + c * 2) == 0)
00150        break;
00151       ++c;
00152     }
00153 
00154   ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
00155 
00156   for (i = 0; i < c; i++)
00157     ret[i] = get_16 (big_endian, data + i * 2);
00158   ret[i] = 0;
00159 
00160   if (retlen != NULL)
00161     *retlen = c;
00162 
00163   return ret;
00164 }
00165 
00166 /* Get a resource identifier.  This returns the number of bytes used.  */
00167 
00168 static int
00169 get_resid (struct res_id *id, const unsigned char *data,
00170           unsigned long length, int big_endian)
00171 {
00172   int first;
00173 
00174   if (length < 2)
00175     toosmall (_("resource ID"));
00176 
00177   first = get_16 (big_endian, data);
00178   if (first == 0xffff)
00179     {
00180       if (length < 4)
00181        toosmall (_("resource ID"));
00182       id->named = 0;
00183       id->u.id = get_16 (big_endian, data + 2);
00184       return 4;
00185     }
00186   else
00187     {
00188       id->named = 1;
00189       id->u.n.name = get_unicode (data, length, big_endian, &id->u.n.length);
00190       return id->u.n.length * 2 + 2;
00191     }
00192 }
00193 
00194 /* Convert a resource which just stores uninterpreted data from
00195    binary.  */
00196 
00197 struct res_resource *
00198 bin_to_res_generic (enum res_type type, const unsigned char *data,
00199                   unsigned long length)
00200 {
00201   struct res_resource *r;
00202 
00203   r = (struct res_resource *) res_alloc (sizeof *r);
00204   r->type = type;
00205   r->u.data.data = data;
00206   r->u.data.length = length;
00207 
00208   return r;
00209 }
00210 
00211 /* Convert a cursor resource from binary.  */
00212 
00213 struct res_resource *
00214 bin_to_res_cursor (const unsigned char *data, unsigned long length,
00215                  int big_endian)
00216 {
00217   struct cursor *c;
00218   struct res_resource *r;
00219 
00220   if (length < 4)
00221     toosmall (_("cursor"));
00222 
00223   c = (struct cursor *) res_alloc (sizeof *c);
00224   c->xhotspot = get_16 (big_endian, data);
00225   c->yhotspot = get_16 (big_endian, data + 2);
00226   c->length = length - 4;
00227   c->data = data + 4;
00228 
00229   r = (struct res_resource *) res_alloc (sizeof *r);
00230   r->type = RES_TYPE_CURSOR;
00231   r->u.cursor = c;
00232 
00233   return r;
00234 }
00235 
00236 /* Convert a menu resource from binary.  */
00237 
00238 struct res_resource *
00239 bin_to_res_menu (const unsigned char *data, unsigned long length,
00240                int big_endian)
00241 {
00242   struct res_resource *r;
00243   struct menu *m;
00244   int version, read;
00245 
00246   r = (struct res_resource *) res_alloc (sizeof *r);
00247   r->type = RES_TYPE_MENU;
00248 
00249   m = (struct menu *) res_alloc (sizeof *m);
00250   r->u.menu = m;
00251 
00252   if (length < 2)
00253     toosmall (_("menu header"));
00254 
00255   version = get_16 (big_endian, data);
00256 
00257   if (version == 0)
00258     {
00259       if (length < 4)
00260        toosmall (_("menu header"));
00261       m->help = 0;
00262       m->items = bin_to_res_menuitems (data + 4, length - 4, big_endian,
00263                                    &read);
00264     }
00265   else if (version == 1)
00266     {
00267       unsigned int offset;
00268 
00269       if (length < 8)
00270        toosmall (_("menuex header"));
00271       m->help = get_32 (big_endian, data + 4);
00272       offset = get_16 (big_endian, data + 2);
00273       if (offset + 4 >= length)
00274        toosmall (_("menuex offset"));
00275       m->items = bin_to_res_menuexitems (data + 4 + offset,
00276                                     length - (4 + offset),
00277                                     big_endian,
00278                                     &read);
00279     }
00280   else
00281     fatal (_("unsupported menu version %d"), version);
00282 
00283   return r;
00284 }
00285 
00286 /* Convert menu items from binary.  */
00287 
00288 static struct menuitem *
00289 bin_to_res_menuitems (const unsigned char *data, unsigned long length,
00290                     int big_endian, int *read)
00291 {
00292   struct menuitem *first, **pp;
00293 
00294   first = NULL;
00295   pp = &first;
00296 
00297   *read = 0;
00298 
00299   while (length > 0)
00300     {
00301       int flags, slen, itemlen;
00302       unsigned int stroff;
00303       struct menuitem *mi;
00304 
00305       if (length < 4)
00306        toosmall (_("menuitem header"));
00307 
00308       mi = (struct menuitem *) res_alloc (sizeof *mi);
00309       mi->state = 0;
00310       mi->help = 0;
00311 
00312       flags = get_16 (big_endian, data);
00313       mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
00314 
00315       if ((flags & MENUITEM_POPUP) == 0)
00316        stroff = 4;
00317       else
00318        stroff = 2;
00319 
00320       if (length < stroff + 2)
00321        toosmall (_("menuitem header"));
00322 
00323       if (get_16 (big_endian, data + stroff) == 0)
00324        {
00325          slen = 0;
00326          mi->text = NULL;
00327        }
00328       else
00329        mi->text = get_unicode (data + stroff, length - stroff, big_endian,
00330                             &slen);
00331 
00332       itemlen = stroff + slen * 2 + 2;
00333 
00334       if ((flags & MENUITEM_POPUP) == 0)
00335        {
00336          mi->popup = NULL;
00337          mi->id = get_16 (big_endian, data + 2);
00338        }
00339       else
00340        {
00341          int subread;
00342 
00343          mi->id = 0;
00344          mi->popup = bin_to_res_menuitems (data + itemlen, length - itemlen,
00345                                        big_endian, &subread);
00346          itemlen += subread;
00347        }
00348 
00349       mi->next = NULL;
00350       *pp = mi;
00351       pp = &mi->next;
00352 
00353       data += itemlen;
00354       length -= itemlen;
00355       *read += itemlen;
00356 
00357       if ((flags & MENUITEM_ENDMENU) != 0)
00358        return first;
00359     }
00360 
00361   return first;
00362 }
00363 
00364 /* Convert menuex items from binary.  */
00365 
00366 static struct menuitem *
00367 bin_to_res_menuexitems (const unsigned char *data, unsigned long length,
00368                      int big_endian, int *read)
00369 {
00370   struct menuitem *first, **pp;
00371 
00372   first = NULL;
00373   pp = &first;
00374 
00375   *read = 0;
00376 
00377   while (length > 0)
00378     {
00379       int flags, slen;
00380       unsigned int itemlen;
00381       struct menuitem *mi;
00382 
00383       if (length < 14)
00384        toosmall (_("menuitem header"));
00385 
00386       mi = (struct menuitem *) res_alloc (sizeof *mi);
00387       mi->type = get_32 (big_endian, data);
00388       mi->state = get_32 (big_endian, data + 4);
00389       mi->id = get_16 (big_endian, data + 8);
00390 
00391       flags = get_16 (big_endian, data + 10);
00392 
00393       if (get_16 (big_endian, data + 12) == 0)
00394        {
00395          slen = 0;
00396          mi->text = NULL;
00397        }
00398       else
00399        mi->text = get_unicode (data + 12, length - 12, big_endian, &slen);
00400 
00401       itemlen = 12 + slen * 2 + 2;
00402       itemlen = (itemlen + 3) &~ 3;
00403 
00404       if ((flags & 1) == 0)
00405        {
00406          mi->popup = NULL;
00407          mi->help = 0;
00408        }
00409       else
00410        {
00411          int subread;
00412 
00413          if (length < itemlen + 4)
00414            toosmall (_("menuitem"));
00415          mi->help = get_32 (big_endian, data + itemlen);
00416          itemlen += 4;
00417 
00418          mi->popup = bin_to_res_menuexitems (data + itemlen,
00419                                          length - itemlen,
00420                                          big_endian, &subread);
00421          itemlen += subread;
00422        }
00423 
00424       mi->next = NULL;
00425       *pp = mi;
00426       pp = &mi->next;
00427 
00428       data += itemlen;
00429       length -= itemlen;
00430       *read += itemlen;
00431 
00432       if ((flags & 0x80) != 0)
00433        return first;
00434     }
00435 
00436   return first;
00437 }
00438 
00439 /* Convert a dialog resource from binary.  */
00440 
00441 static struct res_resource *
00442 bin_to_res_dialog (const unsigned char *data, unsigned long length,
00443                  int big_endian)
00444 {
00445   int signature;
00446   struct dialog *d;
00447   int c, sublen, i;
00448   unsigned int off;
00449   struct dialog_control **pp;
00450   struct res_resource *r;
00451 
00452   if (length < 18)
00453     toosmall (_("dialog header"));
00454 
00455   d = (struct dialog *) res_alloc (sizeof *d);
00456 
00457   signature = get_16 (big_endian, data + 2);
00458   if (signature != 0xffff)
00459     {
00460       d->ex = NULL;
00461       d->style = get_32 (big_endian, data);
00462       d->exstyle = get_32 (big_endian, data + 4);
00463       off = 8;
00464     }
00465   else
00466     {
00467       int version;
00468 
00469       version = get_16 (big_endian, data);
00470       if (version != 1)
00471        fatal (_("unexpected DIALOGEX version %d"), version);
00472 
00473       d->ex = (struct dialog_ex *) res_alloc (sizeof (struct dialog_ex));
00474       d->ex->help = get_32 (big_endian, data + 4);
00475       d->exstyle = get_32 (big_endian, data + 8);
00476       d->style = get_32 (big_endian, data + 12);
00477       off = 16;
00478     }
00479 
00480   if (length < off + 10)
00481     toosmall (_("dialog header"));
00482 
00483   c = get_16 (big_endian, data + off);
00484   d->x = get_16  (big_endian, data + off + 2);
00485   d->y = get_16 (big_endian, data + off + 4);
00486   d->width = get_16 (big_endian, data + off + 6);
00487   d->height = get_16 (big_endian, data + off + 8);
00488 
00489   off += 10;
00490 
00491   sublen = get_resid (&d->menu, data + off, length - off, big_endian);
00492   off += sublen;
00493 
00494   sublen = get_resid (&d->class, data + off, length - off, big_endian);
00495   off += sublen;
00496 
00497   d->caption = get_unicode (data + off, length - off, big_endian, &sublen);
00498   off += sublen * 2 + 2;
00499   if (sublen == 0)
00500     d->caption = NULL;
00501 
00502   if ((d->style & DS_SETFONT) == 0)
00503     {
00504       d->pointsize = 0;
00505       d->font = NULL;
00506       if (d->ex != NULL)
00507        {
00508          d->ex->weight = 0;
00509          d->ex->italic = 0;
00510          d->ex->charset = 1; /* Default charset.  */
00511        }
00512     }
00513   else
00514     {
00515       if (length < off + 2)
00516        toosmall (_("dialog font point size"));
00517 
00518       d->pointsize = get_16 (big_endian, data + off);
00519       off += 2;
00520 
00521       if (d->ex != NULL)
00522        {
00523          if (length < off + 4)
00524            toosmall (_("dialogex font information"));
00525          d->ex->weight = get_16 (big_endian, data + off);
00526          d->ex->italic = get_8 (data + off + 2);
00527          d->ex->charset = get_8 (data + off + 3);
00528          off += 4;
00529        }
00530 
00531       d->font = get_unicode (data + off, length - off, big_endian, &sublen);
00532       off += sublen * 2 + 2;
00533     }
00534 
00535   d->controls = NULL;
00536   pp = &d->controls;
00537 
00538   for (i = 0; i < c; i++)
00539     {
00540       struct dialog_control *dc;
00541       int datalen;
00542 
00543       off = (off + 3) &~ 3;
00544 
00545       dc = (struct dialog_control *) res_alloc (sizeof *dc);
00546 
00547       if (d->ex == NULL)
00548        {
00549          if (length < off + 8)
00550            toosmall (_("dialog control"));
00551 
00552          dc->style = get_32 (big_endian, data + off);
00553          dc->exstyle = get_32 (big_endian, data + off + 4);
00554          dc->help = 0;
00555          off += 8;
00556        }
00557       else
00558        {
00559          if (length < off + 12)
00560            toosmall (_("dialogex control"));
00561          dc->help = get_32 (big_endian, data + off);
00562          dc->exstyle = get_32 (big_endian, data + off + 4);
00563          dc->style = get_32 (big_endian, data + off + 8);
00564          off += 12;
00565        }
00566 
00567       if (length < off + 10)
00568        toosmall (_("dialog control"));
00569 
00570       dc->x = get_16 (big_endian, data + off);
00571       dc->y = get_16 (big_endian, data + off + 2);
00572       dc->width = get_16 (big_endian, data + off + 4);
00573       dc->height = get_16 (big_endian, data + off + 6);
00574 
00575       if (d->ex != NULL)
00576        dc->id = get_32 (big_endian, data + off + 8);
00577       else
00578        dc->id = get_16 (big_endian, data + off + 8);
00579 
00580       off += 10 + (d->ex != NULL ? 2 : 0);
00581 
00582       sublen = get_resid (&dc->class, data + off, length - off, big_endian);
00583       off += sublen;
00584 
00585       sublen = get_resid (&dc->text, data + off, length - off, big_endian);
00586       off += sublen;
00587 
00588       if (length < off + 2)
00589        toosmall (_("dialog control end"));
00590 
00591       datalen = get_16 (big_endian, data + off);
00592       off += 2;
00593 
00594       if (datalen == 0)
00595        dc->data = NULL;
00596       else
00597        {
00598          off = (off + 3) &~ 3;
00599 
00600          if (length < off + datalen)
00601            toosmall (_("dialog control data"));
00602 
00603          dc->data = ((struct rcdata_item *)
00604                     res_alloc (sizeof (struct rcdata_item)));
00605          dc->data->next = NULL;
00606          dc->data->type = RCDATA_BUFFER;
00607          dc->data->u.buffer.length = datalen;
00608          dc->data->u.buffer.data = data + off;
00609 
00610          off += datalen;
00611        }
00612 
00613       dc->next = NULL;
00614       *pp = dc;
00615       pp = &dc->next;
00616     }
00617 
00618   r = (struct res_resource *) res_alloc (sizeof *r);
00619   r->type = RES_TYPE_DIALOG;
00620   r->u.dialog = d;
00621 
00622   return r;
00623 }
00624 
00625 /* Convert a stringtable resource from binary.  */
00626 
00627 static struct res_resource *
00628 bin_to_res_string (const unsigned char *data, unsigned long length,
00629                  int big_endian)
00630 {
00631   struct stringtable *st;
00632   int i;
00633   struct res_resource *r;
00634 
00635   st = (struct stringtable *) res_alloc (sizeof *st);
00636 
00637   for (i = 0; i < 16; i++)
00638     {
00639       unsigned int slen;
00640 
00641       if (length < 2)
00642        toosmall (_("stringtable string length"));
00643       slen = get_16 (big_endian, data);
00644       st->strings[i].length = slen;
00645 
00646       if (slen > 0)
00647        {
00648          unichar *s;
00649          unsigned int j;
00650 
00651          if (length < 2 + 2 * slen)
00652            toosmall (_("stringtable string"));
00653 
00654          s = (unichar *) res_alloc (slen * sizeof (unichar));
00655          st->strings[i].string = s;
00656 
00657          for (j = 0; j < slen; j++)
00658            s[j] = get_16 (big_endian, data + 2 + j * 2);
00659        }
00660 
00661       data += 2 + 2 * slen;
00662       length -= 2 + 2 * slen;
00663     }
00664 
00665   r = (struct res_resource *) res_alloc (sizeof *r);
00666   r->type = RES_TYPE_STRINGTABLE;
00667   r->u.stringtable = st;
00668 
00669   return r;
00670 }
00671 
00672 /* Convert a fontdir resource from binary.  */
00673 
00674 static struct res_resource *
00675 bin_to_res_fontdir (const unsigned char *data, unsigned long length,
00676                   int big_endian)
00677 {
00678   int c, i;
00679   struct fontdir *first, **pp;
00680   struct res_resource *r;
00681 
00682   if (length < 2)
00683     toosmall (_("fontdir header"));
00684 
00685   c = get_16 (big_endian, data);
00686 
00687   first = NULL;
00688   pp = &first;
00689 
00690   for (i = 0; i < c; i++)
00691     {
00692       struct fontdir *fd;
00693       unsigned int off;
00694 
00695       if (length < 56)
00696        toosmall (_("fontdir"));
00697 
00698       fd = (struct fontdir *) res_alloc (sizeof *fd);
00699       fd->index = get_16 (big_endian, data);
00700 
00701       /* To work out the length of the fontdir data, we must get the
00702          length of the device name and face name strings, even though
00703          we don't store them in the fontdir structure.  The
00704          documentation says that these are NULL terminated char
00705          strings, not Unicode strings.  */
00706 
00707       off = 56;
00708 
00709       while (off < length && data[off] != '\0')
00710        ++off;
00711       if (off >= length)
00712        toosmall (_("fontdir device name"));
00713       ++off;
00714 
00715       while (off < length && data[off] != '\0')
00716        ++off;
00717       if (off >= length)
00718        toosmall (_("fontdir face name"));
00719       ++off;
00720 
00721       fd->length = off;
00722       fd->data = data;
00723 
00724       fd->next = NULL;
00725       *pp = fd;
00726       pp = &fd->next;
00727 
00728       /* The documentation does not indicate that any rounding is
00729          required.  */
00730 
00731       data += off;
00732       length -= off;
00733     }
00734 
00735   r = (struct res_resource *) res_alloc (sizeof *r);
00736   r->type = RES_TYPE_FONTDIR;
00737   r->u.fontdir = first;
00738 
00739   return r;
00740 }
00741 
00742 /* Convert an accelerators resource from binary.  */
00743 
00744 static struct res_resource *
00745 bin_to_res_accelerators (const unsigned char *data, unsigned long length,
00746                       int big_endian)
00747 {
00748   struct accelerator *first, **pp;
00749   struct res_resource *r;
00750 
00751   first = NULL;
00752   pp = &first;
00753 
00754   while (1)
00755     {
00756       struct accelerator *a;
00757 
00758       if (length < 8)
00759        toosmall (_("accelerator"));
00760 
00761       a = (struct accelerator *) res_alloc (sizeof *a);
00762 
00763       a->flags = get_16 (big_endian, data);
00764       a->key = get_16 (big_endian, data + 2);
00765       a->id = get_16 (big_endian, data + 4);
00766 
00767       a->next = NULL;
00768       *pp = a;
00769       pp = &a->next;
00770 
00771       if ((a->flags & ACC_LAST) != 0)
00772        break;
00773 
00774       data += 8;
00775       length -= 8;
00776     }
00777 
00778   r = (struct res_resource *) res_alloc (sizeof *r);
00779   r->type = RES_TYPE_ACCELERATOR;
00780   r->u.acc = first;
00781 
00782   return r;
00783 }
00784 
00785 /* Convert an rcdata resource from binary.  */
00786 
00787 static struct res_resource *
00788 bin_to_res_rcdata (const unsigned char *data, unsigned long length,
00789                  int big_endian ATTRIBUTE_UNUSED)
00790 {
00791   struct rcdata_item *ri;
00792   struct res_resource *r;
00793 
00794   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
00795 
00796   ri->next = NULL;
00797   ri->type = RCDATA_BUFFER;
00798   ri->u.buffer.length = length;
00799   ri->u.buffer.data = data;
00800 
00801   r = (struct res_resource *) res_alloc (sizeof *r);
00802   r->type = RES_TYPE_RCDATA;
00803   r->u.rcdata = ri;
00804 
00805   return r;
00806 }
00807 
00808 /* Convert a group cursor resource from binary.  */
00809 
00810 static struct res_resource *
00811 bin_to_res_group_cursor (const unsigned char *data, unsigned long length,
00812                       int big_endian)
00813 {
00814   int type, c, i;
00815   struct group_cursor *first, **pp;
00816   struct res_resource *r;
00817 
00818   if (length < 6)
00819     toosmall (_("group cursor header"));
00820 
00821   type = get_16 (big_endian, data + 2);
00822   if (type != 2)
00823     fatal (_("unexpected group cursor type %d"), type);
00824 
00825   c = get_16 (big_endian, data + 4);
00826 
00827   data += 6;
00828   length -= 6;
00829 
00830   first = NULL;
00831   pp = &first;
00832 
00833   for (i = 0; i < c; i++)
00834     {
00835       struct group_cursor *gc;
00836 
00837       if (length < 14)
00838        toosmall (_("group cursor"));
00839 
00840       gc = (struct group_cursor *) res_alloc (sizeof *gc);
00841 
00842       gc->width = get_16 (big_endian, data);
00843       gc->height = get_16 (big_endian, data + 2);
00844       gc->planes = get_16 (big_endian, data + 4);
00845       gc->bits = get_16 (big_endian, data + 6);
00846       gc->bytes = get_32 (big_endian, data + 8);
00847       gc->index = get_16 (big_endian, data + 12);
00848 
00849       gc->next = NULL;
00850       *pp = gc;
00851       pp = &gc->next;
00852 
00853       data += 14;
00854       length -= 14;
00855     }
00856 
00857   r = (struct res_resource *) res_alloc (sizeof *r);
00858   r->type = RES_TYPE_GROUP_CURSOR;
00859   r->u.group_cursor = first;
00860 
00861   return r;
00862 }
00863 
00864 /* Convert a group icon resource from binary.  */
00865 
00866 static struct res_resource *
00867 bin_to_res_group_icon (const unsigned char *data, unsigned long length,
00868                      int big_endian)
00869 {
00870   int type, c, i;
00871   struct group_icon *first, **pp;
00872   struct res_resource *r;
00873 
00874   if (length < 6)
00875     toosmall (_("group icon header"));
00876 
00877   type = get_16 (big_endian, data + 2);
00878   if (type != 1)
00879     fatal (_("unexpected group icon type %d"), type);
00880 
00881   c = get_16 (big_endian, data + 4);
00882 
00883   data += 6;
00884   length -= 6;
00885 
00886   first = NULL;
00887   pp = &first;
00888 
00889   for (i = 0; i < c; i++)
00890     {
00891       struct group_icon *gi;
00892 
00893       if (length < 14)
00894        toosmall (_("group icon"));
00895 
00896       gi = (struct group_icon *) res_alloc (sizeof *gi);
00897 
00898       gi->width = data[0];
00899       gi->height = data[1];
00900       gi->colors = data[2];
00901       gi->planes = get_16 (big_endian, data + 4);
00902       gi->bits = get_16 (big_endian, data + 6);
00903       gi->bytes = get_32 (big_endian, data + 8);
00904       gi->index = get_16 (big_endian, data + 12);
00905 
00906       gi->next = NULL;
00907       *pp = gi;
00908       pp = &gi->next;
00909 
00910       data += 14;
00911       length -= 14;
00912     }
00913 
00914   r = (struct res_resource *) res_alloc (sizeof *r);
00915   r->type = RES_TYPE_GROUP_ICON;
00916   r->u.group_icon = first;
00917 
00918   return r;
00919 }
00920 
00921 /* Extract data from a version header.  If KEY is not NULL, then the
00922    key must be KEY; otherwise, the key is returned in *PKEY.  This
00923    sets *LEN to the total length, *VALLEN to the value length, *TYPE
00924    to the type, and *OFF to the offset to the children.  */
00925 
00926 static void
00927 get_version_header (const unsigned char *data, unsigned long length,
00928                   int big_endian, const char *key, unichar **pkey,
00929                   int *len, int *vallen, int *type, int *off)
00930 {
00931   if (length < 8)
00932     toosmall (key);
00933 
00934   *len = get_16 (big_endian, data);
00935   *vallen = get_16 (big_endian, data + 2);
00936   *type = get_16 (big_endian, data + 4);
00937 
00938   *off = 6;
00939 
00940   length -= 6;
00941   data += 6;
00942 
00943   if (key == NULL)
00944     {
00945       int sublen;
00946 
00947       *pkey = get_unicode (data, length, big_endian, &sublen);
00948       *off += sublen * 2 + 2;
00949     }
00950   else
00951     {
00952       while (1)
00953        {
00954          if (length < 2)
00955            toosmall (key);
00956          if (get_16 (big_endian, data) != (unsigned char) *key)
00957            fatal (_("unexpected version string"));
00958 
00959          *off += 2;
00960          length -= 2;
00961          data += 2;
00962 
00963          if (*key == '\0')
00964            break;
00965 
00966          ++key;
00967        }
00968     }
00969 
00970   *off = (*off + 3) &~ 3;
00971 }
00972 
00973 /* Convert a version resource from binary.  */
00974 
00975 static struct res_resource *
00976 bin_to_res_version (const unsigned char *data, unsigned long length,
00977                   int big_endian)
00978 {
00979   int verlen, vallen, type, off;
00980   struct fixed_versioninfo *fi;
00981   struct ver_info *first, **pp;
00982   struct versioninfo *v;
00983   struct res_resource *r;
00984 
00985   get_version_header (data, length, big_endian, "VS_VERSION_INFO",
00986                     (unichar **) NULL, &verlen, &vallen, &type, &off);
00987 
00988   if ((unsigned int) verlen != length)
00989     fatal (_("version length %d does not match resource length %lu"),
00990           verlen, length);
00991 
00992   if (type != 0)
00993     fatal (_("unexpected version type %d"), type);
00994 
00995   data += off;
00996   length -= off;
00997 
00998   if (vallen == 0)
00999     fi = NULL;
01000   else
01001     {
01002       unsigned long signature, fiv;
01003 
01004       if (vallen != 52)
01005        fatal (_("unexpected fixed version information length %d"), vallen);
01006 
01007       if (length < 52)
01008        toosmall (_("fixed version info"));
01009 
01010       signature = get_32 (big_endian, data);
01011       if (signature != 0xfeef04bd)
01012        fatal (_("unexpected fixed version signature %lu"), signature);
01013 
01014       fiv = get_32 (big_endian, data + 4);
01015       if (fiv != 0 && fiv != 0x10000)
01016        fatal (_("unexpected fixed version info version %lu"), fiv);
01017 
01018       fi = (struct fixed_versioninfo *) res_alloc (sizeof *fi);
01019 
01020       fi->file_version_ms = get_32 (big_endian, data + 8);
01021       fi->file_version_ls = get_32 (big_endian, data + 12);
01022       fi->product_version_ms = get_32 (big_endian, data + 16);
01023       fi->product_version_ls = get_32 (big_endian, data + 20);
01024       fi->file_flags_mask = get_32 (big_endian, data + 24);
01025       fi->file_flags = get_32 (big_endian, data + 28);
01026       fi->file_os = get_32 (big_endian, data + 32);
01027       fi->file_type = get_32 (big_endian, data + 36);
01028       fi->file_subtype = get_32 (big_endian, data + 40);
01029       fi->file_date_ms = get_32 (big_endian, data + 44);
01030       fi->file_date_ls = get_32 (big_endian, data + 48);
01031 
01032       data += 52;
01033       length -= 52;
01034     }
01035 
01036   first = NULL;
01037   pp = &first;
01038 
01039   while (length > 0)
01040     {
01041       struct ver_info *vi;
01042       int ch;
01043 
01044       if (length < 8)
01045        toosmall (_("version var info"));
01046 
01047       vi = (struct ver_info *) res_alloc (sizeof *vi);
01048 
01049       ch = get_16 (big_endian, data + 6);
01050 
01051       if (ch == 'S')
01052        {
01053          struct ver_stringinfo **ppvs;
01054 
01055          vi->type = VERINFO_STRING;
01056 
01057          get_version_header (data, length, big_endian, "StringFileInfo",
01058                            (unichar **) NULL, &verlen, &vallen, &type,
01059                            &off);
01060 
01061          if (vallen != 0)
01062            fatal (_("unexpected stringfileinfo value length %d"), vallen);
01063 
01064          data += off;
01065          length -= off;
01066 
01067          get_version_header (data, length, big_endian, (const char *) NULL,
01068                            &vi->u.string.language, &verlen, &vallen,
01069                            &type, &off);
01070 
01071          if (vallen != 0)
01072            fatal (_("unexpected version stringtable value length %d"), vallen);
01073 
01074          data += off;
01075          length -= off;
01076          verlen -= off;
01077 
01078          vi->u.string.strings = NULL;
01079          ppvs = &vi->u.string.strings;
01080 
01081          /* It's convenient to round verlen to a 4 byte alignment,
01082              since we round the subvariables in the loop.  */
01083          verlen = (verlen + 3) &~ 3;
01084 
01085          while (verlen > 0)
01086            {
01087              struct ver_stringinfo *vs;
01088              int subverlen, vslen, valoff;
01089 
01090              vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
01091 
01092              get_version_header (data, length, big_endian,
01093                               (const char *) NULL, &vs->key, &subverlen,
01094                               &vallen, &type, &off);
01095 
01096              subverlen = (subverlen + 3) &~ 3;
01097 
01098              data += off;
01099              length -= off;
01100 
01101              vs->value = get_unicode (data, length, big_endian, &vslen);
01102              valoff = vslen * 2 + 2;
01103              valoff = (valoff + 3) &~ 3;
01104 
01105              if (off + valoff != subverlen)
01106               fatal (_("unexpected version string length %d != %d + %d"),
01107                      subverlen, off, valoff);
01108 
01109              vs->next = NULL;
01110              *ppvs = vs;
01111              ppvs = &vs->next;
01112 
01113              data += valoff;
01114              length -= valoff;
01115 
01116              if (verlen < subverlen)
01117               fatal (_("unexpected version string length %d < %d"),
01118                      verlen, subverlen);
01119 
01120              verlen -= subverlen;
01121            }
01122        }
01123       else if (ch == 'V')
01124        {
01125          struct ver_varinfo **ppvv;
01126 
01127          vi->type = VERINFO_VAR;
01128 
01129          get_version_header (data, length, big_endian, "VarFileInfo",
01130                            (unichar **) NULL, &verlen, &vallen, &type,
01131                            &off);
01132 
01133          if (vallen != 0)
01134            fatal (_("unexpected varfileinfo value length %d"), vallen);
01135 
01136          data += off;
01137          length -= off;
01138 
01139          get_version_header (data, length, big_endian, (const char *) NULL,
01140                            &vi->u.var.key, &verlen, &vallen, &type, &off);
01141 
01142          data += off;
01143          length -= off;
01144 
01145          vi->u.var.var = NULL;
01146          ppvv = &vi->u.var.var;
01147 
01148          while (vallen > 0)
01149            {
01150              struct ver_varinfo *vv;
01151 
01152              if (length < 4)
01153               toosmall (_("version varfileinfo"));
01154 
01155              vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
01156 
01157              vv->language = get_16 (big_endian, data);
01158              vv->charset = get_16 (big_endian, data + 2);
01159 
01160              vv->next = NULL;
01161              *ppvv = vv;
01162              ppvv = &vv->next;
01163 
01164              data += 4;
01165              length -= 4;
01166 
01167              if (vallen < 4)
01168               fatal (_("unexpected version value length %d"), vallen);
01169 
01170              vallen -= 4;
01171            }
01172        }
01173       else
01174        fatal (_("unexpected version string"));
01175 
01176       vi->next = NULL;
01177       *pp = vi;
01178       pp = &vi->next;
01179     }
01180 
01181   v = (struct versioninfo *) res_alloc (sizeof *v);
01182   v->fixed = fi;
01183   v->var = first;
01184 
01185   r = (struct res_resource *) res_alloc (sizeof *r);
01186   r->type = RES_TYPE_VERSIONINFO;
01187   r->u.versioninfo = v;
01188 
01189   return r;
01190 }
01191 
01192 /* Convert an arbitrary user defined resource from binary.  */
01193 
01194 static struct res_resource *
01195 bin_to_res_userdata (const unsigned char *data, unsigned long length,
01196                    int big_endian ATTRIBUTE_UNUSED)
01197 {
01198   struct rcdata_item *ri;
01199   struct res_resource *r;
01200 
01201   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
01202 
01203   ri->next = NULL;
01204   ri->type = RCDATA_BUFFER;
01205   ri->u.buffer.length = length;
01206   ri->u.buffer.data = data;
01207 
01208   r = (struct res_resource *) res_alloc (sizeof *r);
01209   r->type = RES_TYPE_USERDATA;
01210   r->u.rcdata = ri;
01211 
01212   return r;
01213 }
01214 
01215 /* Macros to swap out values.  */
01216 
01217 #define put_8(v, s)      (*((unsigned char *) (s)) = (unsigned char) (v))
01218 #define put_16(be, v, s) ((be) ? bfd_putb16 ((v), (s)) : bfd_putl16 ((v), (s)))
01219 #define put_32(be, v, s) ((be) ? bfd_putb32 ((v), (s)) : bfd_putl32 ((v), (s)))
01220 
01221 /* Local functions used to convert resources to binary format.  */
01222 
01223 static void dword_align_bin (struct bindata ***, unsigned long *);
01224 static struct bindata *resid_to_bin (struct res_id, int);
01225 static struct bindata *unicode_to_bin (const unichar *, int);
01226 static struct bindata *res_to_bin_accelerator
01227   (const struct accelerator *, int);
01228 static struct bindata *res_to_bin_cursor
01229   (const struct cursor *, int);
01230 static struct bindata *res_to_bin_group_cursor
01231   (const struct group_cursor *, int);
01232 static struct bindata *res_to_bin_dialog
01233   (const struct dialog *, int);
01234 static struct bindata *res_to_bin_fontdir
01235   (const struct fontdir *, int);
01236 static struct bindata *res_to_bin_group_icon
01237   (const struct group_icon *, int);
01238 static struct bindata *res_to_bin_menu
01239   (const struct menu *, int);
01240 static struct bindata *res_to_bin_menuitems
01241   (const struct menuitem *, int);
01242 static struct bindata *res_to_bin_menuexitems
01243   (const struct menuitem *, int);
01244 static struct bindata *res_to_bin_rcdata
01245   (const struct rcdata_item *, int);
01246 static struct bindata *res_to_bin_stringtable
01247   (const struct stringtable *, int);
01248 static struct bindata *string_to_unicode_bin (const char *, int);
01249 static struct bindata *res_to_bin_versioninfo
01250   (const struct versioninfo *, int);
01251 static struct bindata *res_to_bin_generic
01252   (unsigned long, const unsigned char *);
01253 
01254 /* Convert a resource to binary.  */
01255 
01256 struct bindata *
01257 res_to_bin (const struct res_resource *res, int big_endian)
01258 {
01259   switch (res->type)
01260     {
01261     default:
01262       abort ();
01263     case RES_TYPE_BITMAP:
01264     case RES_TYPE_FONT:
01265     case RES_TYPE_ICON:
01266     case RES_TYPE_MESSAGETABLE:
01267       return res_to_bin_generic (res->u.data.length, res->u.data.data);
01268     case RES_TYPE_ACCELERATOR:
01269       return res_to_bin_accelerator (res->u.acc, big_endian);
01270     case RES_TYPE_CURSOR:
01271       return res_to_bin_cursor (res->u.cursor, big_endian);
01272     case RES_TYPE_GROUP_CURSOR:
01273       return res_to_bin_group_cursor (res->u.group_cursor, big_endian);
01274     case RES_TYPE_DIALOG:
01275       return res_to_bin_dialog (res->u.dialog, big_endian);
01276     case RES_TYPE_FONTDIR:
01277       return res_to_bin_fontdir (res->u.fontdir, big_endian);
01278     case RES_TYPE_GROUP_ICON:
01279       return res_to_bin_group_icon (res->u.group_icon, big_endian);
01280     case RES_TYPE_MENU:
01281       return res_to_bin_menu (res->u.menu, big_endian);
01282     case RES_TYPE_RCDATA:
01283       return res_to_bin_rcdata (res->u.rcdata, big_endian);
01284     case RES_TYPE_STRINGTABLE:
01285       return res_to_bin_stringtable (res->u.stringtable, big_endian);
01286     case RES_TYPE_USERDATA:
01287       return res_to_bin_rcdata (res->u.rcdata, big_endian);
01288     case RES_TYPE_VERSIONINFO:
01289       return res_to_bin_versioninfo (res->u.versioninfo, big_endian);
01290     }
01291 }
01292 
01293 /* Align to a 32 bit boundary.  PPP points to the of a list of bindata
01294    structures.  LENGTH points to the length of the structures.  If
01295    necessary, this adds a new bindata to bring length up to a 32 bit
01296    boundary.  It updates *PPP and *LENGTH.  */
01297 
01298 static void
01299 dword_align_bin (struct bindata ***ppp, unsigned long *length)
01300 {
01301   int add;
01302   struct bindata *d;
01303 
01304   if ((*length & 3) == 0)
01305     return;
01306 
01307   add = 4 - (*length & 3);
01308 
01309   d = (struct bindata *) reswr_alloc (sizeof *d);
01310   d->length = add;
01311   d->data = (unsigned char *) reswr_alloc (add);
01312   memset (d->data, 0, add);
01313 
01314   d->next = NULL;
01315   **ppp = d;
01316   *ppp = &(**ppp)->next;
01317 
01318   *length += add;
01319 }
01320 
01321 /* Convert a resource ID to binary.  This always returns exactly one
01322    bindata structure.  */
01323 
01324 static struct bindata *
01325 resid_to_bin (struct res_id id, int big_endian)
01326 {
01327   struct bindata *d;
01328 
01329   d = (struct bindata *) reswr_alloc (sizeof *d);
01330 
01331   if (! id.named)
01332     {
01333       d->length = 4;
01334       d->data = (unsigned char *) reswr_alloc (d->length);
01335       put_16 (big_endian, 0xffff, d->data);
01336       put_16 (big_endian, id.u.id, d->data + 2);
01337     }
01338   else
01339     {
01340       int i;
01341 
01342       d->length = id.u.n.length * 2 + 2;
01343       d->data = (unsigned char *) reswr_alloc (d->length);
01344       for (i = 0; i < id.u.n.length; i++)
01345        put_16 (big_endian, id.u.n.name[i], d->data + i * 2);
01346       put_16 (big_endian, 0, d->data + i * 2);
01347     }
01348 
01349   d->next = NULL;
01350 
01351   return d;
01352 }
01353 
01354 /* Convert a null terminated unicode string to binary.  This always
01355    returns exactly one bindata structure.  */
01356 
01357 static struct bindata *
01358 unicode_to_bin (const unichar *str, int big_endian)
01359 {
01360   int len;
01361   struct bindata *d;
01362 
01363   len = 0;
01364   if (str != NULL)
01365     {
01366       const unichar *s;
01367 
01368       for (s = str; *s != 0; s++)
01369        ++len;
01370     }
01371 
01372   d = (struct bindata *) reswr_alloc (sizeof *d);
01373   d->length = len * 2 + 2;
01374   d->data = (unsigned char *) reswr_alloc (d->length);
01375 
01376   if (str == NULL)
01377     put_16 (big_endian, 0, d->data);
01378   else
01379     {
01380       const unichar *s;
01381       int i;
01382 
01383       for (s = str, i = 0; *s != 0; s++, i++)
01384        put_16 (big_endian, *s, d->data + i * 2);
01385       put_16 (big_endian, 0, d->data + i * 2);
01386     }
01387 
01388   d->next = NULL;
01389 
01390   return d;
01391 }
01392 
01393 /* Convert an accelerator resource to binary.  */
01394 
01395 static struct bindata *
01396 res_to_bin_accelerator (const struct accelerator *accelerators,
01397                      int big_endian)
01398 {
01399   struct bindata *first, **pp;
01400   const struct accelerator *a;
01401 
01402   first = NULL;
01403   pp = &first;
01404 
01405   for (a = accelerators; a != NULL; a = a->next)
01406     {
01407       struct bindata *d;
01408 
01409       d = (struct bindata *) reswr_alloc (sizeof *d);
01410       d->length = 8;
01411       d->data = (unsigned char *) reswr_alloc (d->length);
01412 
01413       put_16 (big_endian,
01414              a->flags | (a->next != NULL ? 0 : ACC_LAST),
01415              d->data);
01416       put_16 (big_endian, a->key, d->data + 2);
01417       put_16 (big_endian, a->id, d->data + 4);
01418       put_16 (big_endian, 0, d->data + 6);
01419 
01420       d->next = NULL;
01421       *pp = d;
01422       pp = &d->next;
01423     }
01424 
01425   return first;
01426 }
01427 
01428 /* Convert a cursor resource to binary.  */
01429 
01430 static struct bindata *
01431 res_to_bin_cursor (const struct cursor *c, int big_endian)
01432 {
01433   struct bindata *d;
01434 
01435   d = (struct bindata *) reswr_alloc (sizeof *d);
01436   d->length = 4;
01437   d->data = (unsigned char *) reswr_alloc (d->length);
01438 
01439   put_16 (big_endian, c->xhotspot, d->data);
01440   put_16 (big_endian, c->yhotspot, d->data + 2);
01441 
01442   d->next = (struct bindata *) reswr_alloc (sizeof *d);
01443   d->next->length = c->length;
01444   d->next->data = (unsigned char *) c->data;
01445   d->next->next = NULL;
01446 
01447   return d;
01448 }
01449 
01450 /* Convert a group cursor resource to binary.  */
01451 
01452 static struct bindata *
01453 res_to_bin_group_cursor (const struct group_cursor *group_cursors,
01454                       int big_endian)
01455 {
01456   struct bindata *first, **pp;
01457   int c;
01458   const struct group_cursor *gc;
01459 
01460   first = (struct bindata *) reswr_alloc (sizeof *first);
01461   first->length = 6;
01462   first->data = (unsigned char *) reswr_alloc (first->length);
01463 
01464   put_16 (big_endian, 0, first->data);
01465   put_16 (big_endian, 2, first->data + 2);
01466 
01467   first->next = NULL;
01468   pp = &first->next;
01469 
01470   c = 0;
01471   for (gc = group_cursors; gc != NULL; gc = gc->next)
01472     {
01473       struct bindata *d;
01474 
01475       ++c;
01476 
01477       d = (struct bindata *) reswr_alloc (sizeof *d);
01478       d->length = 14;
01479       d->data = (unsigned char *) reswr_alloc (d->length);
01480 
01481       put_16 (big_endian, gc->width, d->data);
01482       put_16 (big_endian, gc->height, d->data + 2);
01483       put_16 (big_endian, gc->planes, d->data + 4);
01484       put_16 (big_endian, gc->bits, d->data + 6);
01485       put_32 (big_endian, gc->bytes, d->data + 8);
01486       put_16 (big_endian, gc->index, d->data + 12);
01487 
01488       d->next = NULL;
01489       *pp = d;
01490       pp = &d->next;
01491     }
01492 
01493   put_16 (big_endian, c, first->data + 4);
01494 
01495   return first;
01496 }
01497 
01498 /* Convert a dialog resource to binary.  */
01499 
01500 static struct bindata *
01501 res_to_bin_dialog (const struct dialog *dialog, int big_endian)
01502 {
01503   int dialogex;
01504   struct bindata *first, **pp;
01505   unsigned long length;
01506   int off, c;
01507   struct dialog_control *dc;
01508 
01509   dialogex = extended_dialog (dialog);
01510 
01511   first = (struct bindata *) reswr_alloc (sizeof *first);
01512   first->length = dialogex ? 26 : 18;
01513   first->data = (unsigned char *) reswr_alloc (first->length);
01514 
01515   length = first->length;
01516 
01517   if (! dialogex)
01518     {
01519       put_32 (big_endian, dialog->style, first->data);
01520       put_32 (big_endian, dialog->exstyle, first->data + 4);
01521       off = 8;
01522     }
01523   else
01524     {
01525       put_16 (big_endian, 1, first->data);
01526       put_16 (big_endian, 0xffff, first->data + 2);
01527 
01528       if (dialog->ex == NULL)
01529        put_32 (big_endian, 0, first->data + 4);
01530       else
01531        put_32 (big_endian, dialog->ex->help, first->data + 4);
01532       put_32 (big_endian, dialog->exstyle, first->data + 8);
01533       put_32 (big_endian, dialog->style, first->data + 12);
01534       off = 16;
01535     }
01536 
01537   put_16 (big_endian, dialog->x, first->data + off + 2);
01538   put_16 (big_endian, dialog->y, first->data + off + 4);
01539   put_16 (big_endian, dialog->width, first->data + off + 6);
01540   put_16 (big_endian, dialog->height, first->data + off + 8);
01541 
01542   pp = &first->next;
01543 
01544   *pp = resid_to_bin (dialog->menu, big_endian);
01545   length += (*pp)->length;
01546   pp = &(*pp)->next;
01547 
01548   *pp = resid_to_bin (dialog->class, big_endian);
01549   length += (*pp)->length;
01550   pp = &(*pp)->next;
01551 
01552   *pp = unicode_to_bin (dialog->caption, big_endian);
01553   length += (*pp)->length;
01554   pp = &(*pp)->next;
01555 
01556   if ((dialog->style & DS_SETFONT) != 0)
01557     {
01558       struct bindata *d;
01559 
01560       d = (struct bindata *) reswr_alloc (sizeof *d);
01561       d->length = dialogex ? 6 : 2;
01562       d->data = (unsigned char *) reswr_alloc (d->length);
01563 
01564       length += d->length;
01565 
01566       put_16 (big_endian, dialog->pointsize, d->data);
01567 
01568       if (dialogex)
01569        {
01570          if (dialog->ex == NULL)
01571            {
01572              put_16 (big_endian, 0, d->data + 2);
01573              put_8 (0, d->data + 4);
01574              put_8 (1, d->data + 5);
01575            }
01576          else
01577            {
01578              put_16 (big_endian, dialog->ex->weight, d->data + 2);
01579              put_8 (dialog->ex->italic, d->data + 4);
01580              put_8 (dialog->ex->charset, d->data + 5);
01581            }
01582        }
01583 
01584       *pp = d;
01585       pp = &d->next;
01586 
01587       *pp = unicode_to_bin (dialog->font, big_endian);
01588       length += (*pp)->length;
01589       pp = &(*pp)->next;
01590     }
01591 
01592   c = 0;
01593   for (dc = dialog->controls; dc != NULL; dc = dc->next)
01594     {
01595       struct bindata *d;
01596       int dcoff;
01597 
01598       ++c;
01599 
01600       dword_align_bin (&pp, &length);
01601 
01602       d = (struct bindata *) reswr_alloc (sizeof *d);
01603       d->length = dialogex ? 24 : 18;
01604       d->data = (unsigned char *) reswr_alloc (d->length);
01605 
01606       length += d->length;
01607 
01608       if (! dialogex)
01609        {
01610          put_32 (big_endian, dc->style, d->data);
01611          put_32 (big_endian, dc->exstyle, d->data + 4);
01612          dcoff = 8;
01613        }
01614       else
01615        {
01616          put_32 (big_endian, dc->help, d->data);
01617          put_32 (big_endian, dc->exstyle, d->data + 4);
01618          put_32 (big_endian, dc->style, d->data + 8);
01619          dcoff = 12;
01620        }
01621 
01622       put_16 (big_endian, dc->x, d->data + dcoff);
01623       put_16 (big_endian, dc->y, d->data + dcoff + 2);
01624       put_16 (big_endian, dc->width, d->data + dcoff + 4);
01625       put_16 (big_endian, dc->height, d->data + dcoff + 6);
01626 
01627       if (dialogex)
01628        put_32 (big_endian, dc->id, d->data + dcoff + 8);
01629       else
01630        put_16 (big_endian, dc->id, d->data + dcoff + 8);
01631 
01632       *pp = d;
01633       pp = &d->next;
01634 
01635       *pp = resid_to_bin (dc->class, big_endian);
01636       length += (*pp)->length;
01637       pp = &(*pp)->next;
01638 
01639       *pp = resid_to_bin (dc->text, big_endian);
01640       length += (*pp)->length;
01641       pp = &(*pp)->next;
01642 
01643       d = (struct bindata *) reswr_alloc (sizeof *d);
01644       d->length = 2;
01645       d->data = (unsigned char *) reswr_alloc (d->length);
01646 
01647       length += 2;
01648 
01649       d->next = NULL;
01650       *pp = d;
01651       pp = &d->next;
01652 
01653       if (dc->data == NULL)
01654        put_16 (big_endian, 0, d->data);
01655       else
01656        {
01657          unsigned long sublen;
01658 
01659          dword_align_bin (&pp, &length);
01660 
01661          *pp = res_to_bin_rcdata (dc->data, big_endian);
01662          sublen = 0;
01663          while (*pp != NULL)
01664            {
01665              sublen += (*pp)->length;
01666              pp = &(*pp)->next;
01667            }
01668 
01669          put_16 (big_endian, sublen, d->data);
01670 
01671          length += sublen;
01672        }
01673     }
01674   put_16 (big_endian, c, first->data + off);
01675 
01676   return first;
01677 }
01678 
01679 /* Convert a fontdir resource to binary.  */
01680 
01681 static struct bindata *
01682 res_to_bin_fontdir (const struct fontdir *fontdirs, int big_endian)
01683 {
01684   struct bindata *first, **pp;
01685   int c;
01686   const struct fontdir *fd;
01687 
01688   first = (struct bindata *) reswr_alloc (sizeof *first);
01689   first->length = 2;
01690   first->data = (unsigned char *) reswr_alloc (first->length);
01691 
01692   first->next = NULL;
01693   pp = &first->next;
01694 
01695   c = 0;
01696   for (fd = fontdirs; fd != NULL; fd = fd->next)
01697     {
01698       struct bindata *d;
01699 
01700       ++c;
01701 
01702       d = (struct bindata *) reswr_alloc (sizeof *d);
01703       d->length = 2;
01704       d->data = (unsigned char *) reswr_alloc (d->length);
01705 
01706       put_16 (big_endian, fd->index, d->data);
01707 
01708       *pp = d;
01709       pp = &d->next;
01710 
01711       d = (struct bindata *) reswr_alloc (sizeof *d);
01712       d->length = fd->length;
01713       d->data = (unsigned char *) fd->data;
01714 
01715       d->next = NULL;
01716       *pp = d;
01717       pp = &d->next;
01718     }
01719 
01720   put_16 (big_endian, c, first->data);
01721 
01722   return first;
01723 }
01724 
01725 /* Convert a group icon resource to binary.  */
01726 
01727 static struct bindata *
01728 res_to_bin_group_icon (const struct group_icon *group_icons, int big_endian)
01729 {
01730   struct bindata *first, **pp;
01731   int c;
01732   const struct group_icon *gi;
01733 
01734   first = (struct bindata *) reswr_alloc (sizeof *first);
01735   first->length = 6;
01736   first->data = (unsigned char *) reswr_alloc (first->length);
01737 
01738   put_16 (big_endian, 0, first->data);
01739   put_16 (big_endian, 1, first->data + 2);
01740 
01741   first->next = NULL;
01742   pp = &first->next;
01743 
01744   c = 0;
01745   for (gi = group_icons; gi != NULL; gi = gi->next)
01746     {
01747       struct bindata *d;
01748 
01749       ++c;
01750 
01751       d = (struct bindata *) reswr_alloc (sizeof *d);
01752       d->length = 14;
01753       d->data = (unsigned char *) reswr_alloc (d->length);
01754 
01755       d->data[0] = gi->width;
01756       d->data[1] = gi->height;
01757       d->data[2] = gi->colors;
01758       d->data[3] = 0;
01759       put_16 (big_endian, gi->planes, d->data + 4);
01760       put_16 (big_endian, gi->bits, d->data + 6);
01761       put_32 (big_endian, gi->bytes, d->data + 8);
01762       put_16 (big_endian, gi->index, d->data + 12);
01763 
01764       d->next = NULL;
01765       *pp = d;
01766       pp = &d->next;
01767     }
01768 
01769   put_16 (big_endian, c, first->data + 4);
01770 
01771   return first;
01772 }
01773 
01774 /* Convert a menu resource to binary.  */
01775 
01776 static struct bindata *
01777 res_to_bin_menu (const struct menu *menu, int big_endian)
01778 {
01779   int menuex;
01780   struct bindata *d;
01781 
01782   menuex = extended_menu (menu);
01783 
01784   d = (struct bindata *) reswr_alloc (sizeof *d);
01785   d->length = menuex ? 8 : 4;
01786   d->data = (unsigned char *) reswr_alloc (d->length);
01787 
01788   if (! menuex)
01789     {
01790       put_16 (big_endian, 0, d->data);
01791       put_16 (big_endian, 0, d->data + 2);
01792 
01793       d->next = res_to_bin_menuitems (menu->items, big_endian);
01794     }
01795   else
01796     {
01797       put_16 (big_endian, 1, d->data);
01798       put_16 (big_endian, 4, d->data + 2);
01799       put_32 (big_endian, menu->help, d->data + 4);
01800 
01801       d->next = res_to_bin_menuexitems (menu->items, big_endian);
01802     }
01803 
01804   return d;
01805 }
01806 
01807 /* Convert menu items to binary.  */
01808 
01809 static struct bindata *
01810 res_to_bin_menuitems (const struct menuitem *items, int big_endian)
01811 {
01812   struct bindata *first, **pp;
01813   const struct menuitem *mi;
01814 
01815   first = NULL;
01816   pp = &first;
01817 
01818   for (mi = items; mi != NULL; mi = mi->next)
01819     {
01820       struct bindata *d;
01821       int flags;
01822 
01823       d = (struct bindata *) reswr_alloc (sizeof *d);
01824       d->length = mi->popup == NULL ? 4 : 2;
01825       d->data = (unsigned char *) reswr_alloc (d->length);
01826 
01827       flags = mi->type;
01828       if (mi->next == NULL)
01829        flags |= MENUITEM_ENDMENU;
01830       if (mi->popup != NULL)
01831        flags |= MENUITEM_POPUP;
01832 
01833       put_16 (big_endian, flags, d->data);
01834 
01835       if (mi->popup == NULL)
01836        put_16 (big_endian, mi->id, d->data + 2);
01837 
01838       *pp = d;
01839       pp = &d->next;
01840 
01841       *pp = unicode_to_bin (mi->text, big_endian);
01842       pp = &(*pp)->next;
01843 
01844       if (mi->popup != NULL)
01845        {
01846          *pp = res_to_bin_menuitems (mi->popup, big_endian);
01847          while (*pp != NULL)
01848            pp = &(*pp)->next;
01849        }
01850     }
01851 
01852   return first;
01853 }
01854 
01855 /* Convert menuex items to binary.  */
01856 
01857 static struct bindata *
01858 res_to_bin_menuexitems (const struct menuitem *items, int big_endian)
01859 {
01860   struct bindata *first, **pp;
01861   unsigned long length;
01862   const struct menuitem *mi;
01863 
01864   first = NULL;
01865   pp = &first;
01866 
01867   length = 0;
01868 
01869   for (mi = items; mi != NULL; mi = mi->next)
01870     {
01871       struct bindata *d;
01872       int flags;
01873 
01874       dword_align_bin (&pp, &length);
01875 
01876       d = (struct bindata *) reswr_alloc (sizeof *d);
01877       d->length = 12;
01878       d->data = (unsigned char *) reswr_alloc (d->length);
01879 
01880       length += 12;
01881 
01882       put_32 (big_endian, mi->type, d->data);
01883       put_32 (big_endian, mi->state, d->data + 4);
01884       put_16 (big_endian, mi->id, d->data + 8);
01885 
01886       flags = 0;
01887       if (mi->next == NULL)
01888        flags |= 0x80;
01889       if (mi->popup != NULL)
01890        flags |= 1;
01891       put_16 (big_endian, flags, d->data + 10);
01892 
01893       *pp = d;
01894       pp = &d->next;
01895 
01896       *pp = unicode_to_bin (mi->text, big_endian);
01897       length += (*pp)->length;
01898       pp = &(*pp)->next;
01899 
01900       if (mi->popup != NULL)
01901        {
01902          dword_align_bin (&pp, &length);
01903 
01904          d = (struct bindata *) reswr_alloc (sizeof *d);
01905          d->length = 4;
01906          d->data = (unsigned char *) reswr_alloc (d->length);
01907 
01908          put_32 (big_endian, mi->help, d->data);
01909 
01910          *pp = d;
01911          pp = &d->next;
01912 
01913          *pp = res_to_bin_menuexitems (mi->popup, big_endian);
01914          while (*pp != NULL)
01915            {
01916              length += (*pp)->length;
01917              pp = &(*pp)->next;
01918            }
01919        }
01920     }
01921 
01922   return first;
01923 }
01924 
01925 /* Convert an rcdata resource to binary.  This is also used to convert
01926    other information which happens to be stored in rcdata_item lists
01927    to binary.  */
01928 
01929 static struct bindata *
01930 res_to_bin_rcdata (const struct rcdata_item *items, int big_endian)
01931 {
01932   struct bindata *first, **pp;
01933   const struct rcdata_item *ri;
01934 
01935   first = NULL;
01936   pp = &first;
01937 
01938   for (ri = items; ri != NULL; ri = ri->next)
01939     {
01940       struct bindata *d;
01941 
01942       d = (struct bindata *) reswr_alloc (sizeof *d);
01943 
01944       switch (ri->type)
01945        {
01946        default:
01947          abort ();
01948 
01949        case RCDATA_WORD:
01950          d->length = 2;
01951          d->data = (unsigned char *) reswr_alloc (d->length);
01952          put_16 (big_endian, ri->u.word, d->data);
01953          break;
01954 
01955        case RCDATA_DWORD:
01956          d->length = 4;
01957          d->data = (unsigned char *) reswr_alloc (d->length);
01958          put_32 (big_endian, ri->u.dword, d->data);
01959          break;
01960 
01961        case RCDATA_STRING:
01962          d->length = ri->u.string.length;
01963          d->data = (unsigned char *) ri->u.string.s;
01964          break;
01965 
01966        case RCDATA_WSTRING:
01967          {
01968            unsigned long i;
01969 
01970            d->length = ri->u.wstring.length * 2;
01971            d->data = (unsigned char *) reswr_alloc (d->length);
01972            for (i = 0; i < ri->u.wstring.length; i++)
01973              put_16 (big_endian, ri->u.wstring.w[i], d->data + i * 2);
01974            break;
01975          }
01976 
01977        case RCDATA_BUFFER:
01978          d->length = ri->u.buffer.length;
01979          d->data = (unsigned char *) ri->u.buffer.data;
01980          break;
01981        }
01982 
01983       d->next = NULL;
01984       *pp = d;
01985       pp = &d->next;
01986     }
01987 
01988   return first;
01989 }
01990 
01991 /* Convert a stringtable resource to binary.  */
01992 
01993 static struct bindata *
01994 res_to_bin_stringtable (const struct stringtable *st, int big_endian)
01995 {
01996   struct bindata *first, **pp;
01997   int i;
01998 
01999   first = NULL;
02000   pp = &first;
02001 
02002   for (i = 0; i < 16; i++)
02003     {
02004       int slen, j;
02005       struct bindata *d;
02006       unichar *s;
02007 
02008       slen = st->strings[i].length;
02009       s = st->strings[i].string;
02010 
02011       d = (struct bindata *) reswr_alloc (sizeof *d);
02012       d->length = 2 + slen * 2;
02013       d->data = (unsigned char *) reswr_alloc (d->length);
02014 
02015       put_16 (big_endian, slen, d->data);
02016 
02017       for (j = 0; j < slen; j++)
02018        put_16 (big_endian, s[j], d->data + 2 + j * 2);
02019 
02020       d->next = NULL;
02021       *pp = d;
02022       pp = &d->next;
02023     }
02024 
02025   return first;
02026 }
02027 
02028 /* Convert an ASCII string to a unicode binary string.  This always
02029    returns exactly one bindata structure.  */
02030 
02031 static struct bindata *
02032 string_to_unicode_bin (const char *s, int big_endian)
02033 {
02034   size_t len, i;
02035   struct bindata *d;
02036 
02037   len = strlen (s);
02038 
02039   d = (struct bindata *) reswr_alloc (sizeof *d);
02040   d->length = len * 2 + 2;
02041   d->data = (unsigned char *) reswr_alloc (d->length);
02042 
02043   for (i = 0; i < len; i++)
02044     put_16 (big_endian, s[i], d->data + i * 2);
02045   put_16 (big_endian, 0, d->data + i * 2);
02046 
02047   d->next = NULL;
02048 
02049   return d;
02050 }
02051 
02052 /* Convert a versioninfo resource to binary.  */
02053 
02054 static struct bindata *
02055 res_to_bin_versioninfo (const struct versioninfo *versioninfo, int big_endian)
02056 {
02057   struct bindata *first, **pp;
02058   unsigned long length;
02059   struct ver_info *vi;
02060 
02061   first = (struct bindata *) reswr_alloc (sizeof *first);
02062   first->length = 6;
02063   first->data = (unsigned char *) reswr_alloc (first->length);
02064 
02065   length = 6;
02066 
02067   if (versioninfo->fixed == NULL)
02068     put_16 (big_endian, 0, first->data + 2);
02069   else
02070     put_16 (big_endian, 52, first->data + 2);
02071 
02072   put_16 (big_endian, 0, first->data + 4);
02073 
02074   pp = &first->next;
02075 
02076   *pp = string_to_unicode_bin ("VS_VERSION_INFO", big_endian);
02077   length += (*pp)->length;
02078   pp = &(*pp)->next;
02079 
02080   dword_align_bin (&pp, &length);
02081 
02082   if (versioninfo->fixed != NULL)
02083     {
02084       const struct fixed_versioninfo *fi;
02085       struct bindata *d;
02086 
02087       d = (struct bindata *) reswr_alloc (sizeof *d);
02088       d->length = 52;
02089       d->data = (unsigned char *) reswr_alloc (d->length);
02090 
02091       length += 52;
02092 
02093       fi = versioninfo->fixed;
02094 
02095       put_32 (big_endian, 0xfeef04bd, d->data);
02096       put_32 (big_endian, 0x10000, d->data + 4);
02097       put_32 (big_endian, fi->file_version_ms, d->data + 8);
02098       put_32 (big_endian, fi->file_version_ls, d->data + 12);
02099       put_32 (big_endian, fi->product_version_ms, d->data + 16);
02100       put_32 (big_endian, fi->product_version_ls, d->data + 20);
02101       put_32 (big_endian, fi->file_flags_mask, d->data + 24);
02102       put_32 (big_endian, fi->file_flags, d->data + 28);
02103       put_32 (big_endian, fi->file_os, d->data + 32);
02104       put_32 (big_endian, fi->file_type, d->data + 36);
02105       put_32 (big_endian, fi->file_subtype, d->data + 40);
02106       put_32 (big_endian, fi->file_date_ms, d->data + 44);
02107       put_32 (big_endian, fi->file_date_ls, d->data + 48);
02108 
02109       d->next = NULL;
02110       *pp = d;
02111       pp = &d->next;
02112     }
02113 
02114   for (vi = versioninfo->var; vi != NULL; vi = vi->next)
02115     {
02116       struct bindata *vid;
02117       unsigned long vilen;
02118 
02119       dword_align_bin (&pp, &length);
02120 
02121       vid = (struct bindata *) reswr_alloc (sizeof *vid);
02122       vid->length = 6;
02123       vid->data = (unsigned char *) reswr_alloc (vid->length);
02124 
02125       length += 6;
02126       vilen = 6;
02127 
02128       put_16 (big_endian, 0, vid->data + 2);
02129       put_16 (big_endian, 0, vid->data + 4);
02130 
02131       *pp = vid;
02132       pp = &vid->next;
02133 
02134       switch (vi->type)
02135        {
02136        default:
02137          abort ();
02138 
02139        case VERINFO_STRING:
02140          {
02141            unsigned long hold, vslen;
02142            struct bindata *vsd;
02143            const struct ver_stringinfo *vs;
02144 
02145            *pp = string_to_unicode_bin ("StringFileInfo", big_endian);
02146            length += (*pp)->length;
02147            vilen += (*pp)->length;
02148            pp = &(*pp)->next;
02149 
02150            hold = length;
02151            dword_align_bin (&pp, &length);
02152            vilen += length - hold;
02153 
02154            vsd = (struct bindata *) reswr_alloc (sizeof *vsd);
02155            vsd->length = 6;
02156            vsd->data = (unsigned char *) reswr_alloc (vsd->length);
02157 
02158            length += 6;
02159            vilen += 6;
02160            vslen = 6;
02161 
02162            put_16 (big_endian, 0, vsd->data + 2);
02163            put_16 (big_endian, 0, vsd->data + 4);
02164 
02165            *pp = vsd;
02166            pp = &vsd->next;
02167 
02168            *pp = unicode_to_bin (vi->u.string.language, big_endian);
02169            length += (*pp)->length;
02170            vilen += (*pp)->length;
02171            vslen += (*pp)->length;
02172            pp = &(*pp)->next;
02173 
02174            for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
02175              {
02176               struct bindata *vssd;
02177               unsigned long vsslen;
02178 
02179               hold = length;
02180               dword_align_bin (&pp, &length);
02181               vilen += length - hold;
02182               vslen += length - hold;
02183 
02184               vssd = (struct bindata *) reswr_alloc (sizeof *vssd);
02185               vssd->length = 6;
02186               vssd->data = (unsigned char *) reswr_alloc (vssd->length);
02187 
02188               length += 6;
02189               vilen += 6;
02190               vslen += 6;
02191               vsslen = 6;
02192 
02193               put_16 (big_endian, 1, vssd->data + 4);
02194 
02195               *pp = vssd;
02196               pp = &vssd->next;
02197 
02198               *pp = unicode_to_bin (vs->key, big_endian);
02199               length += (*pp)->length;
02200               vilen += (*pp)->length;
02201               vslen += (*pp)->length;
02202               vsslen += (*pp)->length;
02203               pp = &(*pp)->next;
02204 
02205               hold = length;
02206               dword_align_bin (&pp, &length);
02207               vilen += length - hold;
02208               vslen += length - hold;
02209               vsslen += length - hold;
02210 
02211               *pp = unicode_to_bin (vs->value, big_endian);
02212               put_16 (big_endian, (*pp)->length / 2, vssd->data + 2);
02213               length += (*pp)->length;
02214               vilen += (*pp)->length;
02215               vslen += (*pp)->length;
02216               vsslen += (*pp)->length;
02217               pp = &(*pp)->next;
02218 
02219               put_16 (big_endian, vsslen, vssd->data);
02220              }
02221 
02222            put_16 (big_endian, vslen, vsd->data);
02223 
02224            break;
02225          }
02226 
02227        case VERINFO_VAR:
02228          {
02229            unsigned long hold, vvlen, vvvlen;
02230            struct bindata *vvd;
02231            const struct ver_varinfo *vv;
02232 
02233            *pp = string_to_unicode_bin ("VarFileInfo", big_endian);
02234            length += (*pp)->length;
02235            vilen += (*pp)->length;
02236            pp = &(*pp)->next;
02237 
02238            hold = length;
02239            dword_align_bin (&pp, &length);
02240            vilen += length - hold;
02241 
02242            vvd = (struct bindata *) reswr_alloc (sizeof *vvd);
02243            vvd->length = 6;
02244            vvd->data = (unsigned char *) reswr_alloc (vvd->length);
02245 
02246            length += 6;
02247            vilen += 6;
02248            vvlen = 6;
02249 
02250            put_16 (big_endian, 0, vvd->data + 4);
02251 
02252            *pp = vvd;
02253            pp = &vvd->next;
02254 
02255            *pp = unicode_to_bin (vi->u.var.key, big_endian);
02256            length += (*pp)->length;
02257            vilen += (*pp)->length;
02258            vvlen += (*pp)->length;
02259            pp = &(*pp)->next;
02260 
02261            hold = length;
02262            dword_align_bin (&pp, &length);
02263            vilen += length - hold;
02264            vvlen += length - hold;
02265 
02266            vvvlen = 0;
02267 
02268            for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
02269              {
02270               struct bindata *vvsd;
02271 
02272               vvsd = (struct bindata *) reswr_alloc (sizeof *vvsd);
02273               vvsd->length = 4;
02274               vvsd->data = (unsigned char *) reswr_alloc (vvsd->length);
02275 
02276               length += 4;
02277               vilen += 4;
02278               vvlen += 4;
02279               vvvlen += 4;
02280 
02281               put_16 (big_endian, vv->language, vvsd->data);
02282               put_16 (big_endian, vv->charset, vvsd->data + 2);
02283 
02284               vvsd->next = NULL;
02285               *pp = vvsd;
02286               pp = &vvsd->next;
02287              }
02288 
02289            put_16 (big_endian, vvlen, vvd->data);
02290            put_16 (big_endian, vvvlen, vvd->data + 2);
02291 
02292            break;
02293          }
02294        }
02295 
02296       put_16 (big_endian, vilen, vid->data);
02297     }
02298 
02299   put_16 (big_endian, length, first->data);
02300 
02301   return first;
02302 }
02303 
02304 /* Convert a generic resource to binary.  */
02305 
02306 static struct bindata *
02307 res_to_bin_generic (unsigned long length, const unsigned char *data)
02308 {
02309   struct bindata *d;
02310 
02311   d = (struct bindata *) reswr_alloc (sizeof *d);
02312   d->length = length;
02313   d->data = (unsigned char *) data;
02314 
02315   d->next = NULL;
02316 
02317   return d;
02318 }