1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29: #include "sysdep.h"
30: #include "bfd.h"
31: #include "bucomm.h"
32: #include "libiberty.h"
33: #include "windres.h"
34:
35:
36:
37: static void toosmall (const char *);
38:
39: static unichar *get_unicode (windres_bfd *, const bfd_byte *, rc_uint_type, rc_uint_type *);
40: static int get_resid (windres_bfd *, rc_res_id *, const bfd_byte *, rc_uint_type);
41: static rc_res_resource *bin_to_res_generic (windres_bfd *, enum rc_res_type,
42: const bfd_byte *, rc_uint_type);
43: static rc_res_resource *bin_to_res_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
44: static rc_res_resource *bin_to_res_menu (windres_bfd *,const bfd_byte *, rc_uint_type);
45: static rc_menuitem *bin_to_res_menuitems (windres_bfd *, const bfd_byte *, rc_uint_type,
46: rc_uint_type *);
47: static rc_menuitem *bin_to_res_menuexitems (windres_bfd *, const bfd_byte *, rc_uint_type,
48: rc_uint_type *);
49: static rc_res_resource *bin_to_res_dialog (windres_bfd *, const bfd_byte *, rc_uint_type);
50: static rc_res_resource *bin_to_res_string (windres_bfd *,const bfd_byte *, rc_uint_type);
51: static rc_res_resource *bin_to_res_fontdir (windres_bfd *, const bfd_byte *, rc_uint_type);
52: static rc_res_resource *bin_to_res_accelerators (windres_bfd *, const bfd_byte *, rc_uint_type);
53: static rc_res_resource *bin_to_res_rcdata (windres_bfd *, const bfd_byte *, rc_uint_type, int);
54: static rc_res_resource *bin_to_res_group_cursor (windres_bfd *, const bfd_byte *, rc_uint_type);
55: static rc_res_resource *bin_to_res_group_icon (windres_bfd *, const bfd_byte *, rc_uint_type);
56: static rc_res_resource *bin_to_res_version (windres_bfd *, const bfd_byte *, rc_uint_type);
57: static rc_res_resource *bin_to_res_userdata (windres_bfd *, const bfd_byte *, rc_uint_type);
58: static rc_res_resource *bin_to_res_toolbar (windres_bfd *, const bfd_byte *, rc_uint_type);
59: static void get_version_header (windres_bfd *, const bfd_byte *, rc_uint_type, const char *,
60: unichar **, rc_uint_type *, rc_uint_type *, rc_uint_type *,
61: rc_uint_type *);
62:
63:
64:
65:
66:
67:
68: rc_res_resource *
69: bin_to_res (windres_bfd *wrbfd, rc_res_id type, const bfd_byte *data,
70: rc_uint_type length)
71: {
72: if (type.named)
73: return bin_to_res_userdata (wrbfd, data, length);
74: else
75: {
76: switch (type.u.id)
77: {
78: default:
79: return bin_to_res_userdata (wrbfd, data, length);
80: case RT_CURSOR:
81: return bin_to_res_cursor (wrbfd, data, length);
82: case RT_BITMAP:
83: return bin_to_res_generic (wrbfd, RES_TYPE_BITMAP, data, length);
84: case RT_ICON:
85: return bin_to_res_generic (wrbfd, RES_TYPE_ICON, data, length);
86: case RT_MENU:
87: return bin_to_res_menu (wrbfd, data, length);
88: case RT_DIALOG:
89: return bin_to_res_dialog (wrbfd, data, length);
90: case RT_STRING:
91: return bin_to_res_string (wrbfd, data, length);
92: case RT_FONTDIR:
93: return bin_to_res_fontdir (wrbfd, data, length);
94: case RT_FONT:
95: return bin_to_res_generic (wrbfd, RES_TYPE_FONT, data, length);
96: case RT_ACCELERATOR:
97: return bin_to_res_accelerators (wrbfd, data, length);
98: case RT_RCDATA:
99: return bin_to_res_rcdata (wrbfd, data, length, RES_TYPE_RCDATA);
100: case RT_MESSAGETABLE:
101: return bin_to_res_generic (wrbfd, RES_TYPE_MESSAGETABLE, data, length);
102: case RT_GROUP_CURSOR:
103: return bin_to_res_group_cursor (wrbfd, data, length);
104: case RT_GROUP_ICON:
105: return bin_to_res_group_icon (wrbfd, data, length);
106: case RT_VERSION:
107: return bin_to_res_version (wrbfd, data, length);
108: case RT_TOOLBAR:
109: return bin_to_res_toolbar (wrbfd, data, length);
110:
111: }
112: }
113: }
114:
115:
116:
117: static void
118: toosmall (const char *msg)
119: {
120: fatal (_("%s: not enough binary data"), msg);
121: }
122:
123:
124:
125: static unichar *
126: get_unicode (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
127: rc_uint_type *retlen)
128: {
129: rc_uint_type c, i;
130: unichar *ret;
131:
132: c = 0;
133: while (1)
134: {
135: if (length < c * 2 + 2)
136: toosmall (_("null terminated unicode string"));
137: if (windres_get_16 (wrbfd, data + c * 2, 2) == 0)
138: break;
139: ++c;
140: }
141:
142: ret = (unichar *) res_alloc ((c + 1) * sizeof (unichar));
143:
144: for (i = 0; i < c; i++)
145: ret[i] = windres_get_16 (wrbfd, data + i * 2, 2);
146: ret[i] = 0;
147:
148: if (retlen != NULL)
149: *retlen = c;
150:
151: return ret;
152: }
153:
154:
155:
156: static int
157: get_resid (windres_bfd *wrbfd, rc_res_id *id, const bfd_byte *data,
158: rc_uint_type length)
159: {
160: rc_uint_type first;
161:
162: if (length < 2)
163: toosmall (_("resource ID"));
164:
165: first = windres_get_16 (wrbfd, data, 2);
166: if (first == 0xffff)
167: {
168: if (length < 4)
169: toosmall (_("resource ID"));
170: id->named = 0;
171: id->u.id = windres_get_16 (wrbfd, data + 2, 2);
172: return 4;
173: }
174: else
175: {
176: id->named = 1;
177: id->u.n.name = get_unicode (wrbfd, data, length, &id->u.n.length);
178: return id->u.n.length * 2 + 2;
179: }
180: }
181:
182:
183:
184:
185: rc_res_resource *
186: bin_to_res_generic (windres_bfd *wrbfd ATTRIBUTE_UNUSED, enum rc_res_type type,
187: const bfd_byte *data, rc_uint_type length)
188: {
189: rc_res_resource *r;
190:
191: r = (rc_res_resource *) res_alloc (sizeof (rc_res_resource));
192: r->type = type;
193: r->u.data.data = data;
194: r->u.data.length = length;
195:
196: return r;
197: }
198:
199:
200:
201: rc_res_resource *
202: bin_to_res_cursor (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
203: {
204: rc_cursor *c;
205: rc_res_resource *r;
206:
207: if (length < 4)
208: toosmall (_("cursor"));
209:
210: c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
211: c->xhotspot = windres_get_16 (wrbfd, data, 2);
212: c->yhotspot = windres_get_16 (wrbfd, data + 2, 2);
213: c->length = length - 4;
214: c->data = data + 4;
215:
216: r = (rc_res_resource *) res_alloc (sizeof *r);
217: r->type = RES_TYPE_CURSOR;
218: r->u.cursor = c;
219:
220: return r;
221: }
222:
223:
224:
225: rc_res_resource *
226: bin_to_res_menu (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
227: {
228: rc_res_resource *r;
229: rc_menu *m;
230: rc_uint_type version, read;
231:
232: r = (rc_res_resource *) res_alloc (sizeof *r);
233: r->type = RES_TYPE_MENU;
234:
235: m = (rc_menu *) res_alloc (sizeof (rc_menu));
236: r->u.menu = m;
237:
238: if (length < 2)
239: toosmall (_("menu header"));
240:
241: version = windres_get_16 (wrbfd, data, 2);
242:
243: if (version == 0)
244: {
245: if (length < 4)
246: toosmall (_("menu header"));
247: m->help = 0;
248: m->items = bin_to_res_menuitems (wrbfd, data + 4, length - 4, &read);
249: }
250: else if (version == 1)
251: {
252: rc_uint_type offset;
253:
254: if (length < 8)
255: toosmall (_("menuex header"));
256: m->help = windres_get_32 (wrbfd, data + 4, 4);
257: offset = windres_get_16 (wrbfd, data + 2, 2);
258: if (offset + 4 >= length)
259: toosmall (_("menuex offset"));
260: m->items = bin_to_res_menuexitems (wrbfd, data + 4 + offset,
261: length - (4 + offset), &read);
262: }
263: else
264: fatal (_("unsupported menu version %d"), (int) version);
265:
266: return r;
267: }
268:
269:
270:
271: static rc_menuitem *
272: bin_to_res_menuitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
273: rc_uint_type *read)
274: {
275: rc_menuitem *first, **pp;
276:
277: first = NULL;
278: pp = &first;
279:
280: *read = 0;
281:
282: while (length > 0)
283: {
284: rc_uint_type flags, slen, itemlen;
285: rc_uint_type stroff;
286: rc_menuitem *mi;
287:
288: if (length < 4)
289: toosmall (_("menuitem header"));
290:
291: mi = (rc_menuitem *) res_alloc (sizeof *mi);
292: mi->state = 0;
293: mi->help = 0;
294:
295: flags = windres_get_16 (wrbfd, data, 2);
296: mi->type = flags &~ (MENUITEM_POPUP | MENUITEM_ENDMENU);
297:
298: if ((flags & MENUITEM_POPUP) == 0)
299: stroff = 4;
300: else
301: stroff = 2;
302:
303: if (length < stroff + 2)
304: toosmall (_("menuitem header"));
305:
306: if (windres_get_16 (wrbfd, data + stroff, 2) == 0)
307: {
308: slen = 0;
309: mi->text = NULL;
310: }
311: else
312: mi->text = get_unicode (wrbfd, data + stroff, length - stroff, &slen);
313:
314: itemlen = stroff + slen * 2 + 2;
315:
316: if ((flags & MENUITEM_POPUP) == 0)
317: {
318: mi->popup = NULL;
319: mi->id = windres_get_16 (wrbfd, data + 2, 2);
320: }
321: else
322: {
323: rc_uint_type subread;
324:
325: mi->id = 0;
326: mi->popup = bin_to_res_menuitems (wrbfd, data + itemlen, length - itemlen,
327: &subread);
328: itemlen += subread;
329: }
330:
331: mi->next = NULL;
332: *pp = mi;
333: pp = &mi->next;
334:
335: data += itemlen;
336: length -= itemlen;
337: *read += itemlen;
338:
339: if ((flags & MENUITEM_ENDMENU) != 0)
340: return first;
341: }
342:
343: return first;
344: }
345:
346:
347:
348: static rc_menuitem *
349: bin_to_res_menuexitems (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length,
350: rc_uint_type *read)
351: {
352: rc_menuitem *first, **pp;
353:
354: first = NULL;
355: pp = &first;
356:
357: *read = 0;
358:
359: while (length > 0)
360: {
361: rc_uint_type flags, slen;
362: rc_uint_type itemlen;
363: rc_menuitem *mi;
364:
365: if (length < 16)
366: toosmall (_("menuitem header"));
367:
368: mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
369: mi->type = windres_get_32 (wrbfd, data, 4);
370: mi->state = windres_get_32 (wrbfd, data + 4, 4);
371: mi->id = windres_get_32 (wrbfd, data + 8, 4);
372:
373: flags = windres_get_16 (wrbfd, data + 12, 2);
374:
375: if (windres_get_16 (wrbfd, data + 14, 2) == 0)
376: {
377: slen = 0;
378: mi->text = NULL;
379: }
380: else
381: mi->text = get_unicode (wrbfd, data + 14, length - 14, &slen);
382:
383: itemlen = 14 + slen * 2 + 2;
384: itemlen = (itemlen + 3) &~ 3;
385:
386: if ((flags & 1) == 0)
387: {
388: mi->popup = NULL;
389: mi->help = 0;
390: }
391: else
392: {
393: rc_uint_type subread;
394:
395: if (length < itemlen + 4)
396: toosmall (_("menuitem"));
397: mi->help = windres_get_32 (wrbfd, data + itemlen, 4);
398: itemlen += 4;
399:
400: mi->popup = bin_to_res_menuexitems (wrbfd, data + itemlen,
401: length - itemlen, &subread);
402: itemlen += subread;
403: }
404:
405: mi->next = NULL;
406: *pp = mi;
407: pp = &mi->next;
408:
409: data += itemlen;
410: length -= itemlen;
411: *read += itemlen;
412:
413: if ((flags & 0x80) != 0)
414: return first;
415: }
416:
417: return first;
418: }
419:
420:
421:
422: static rc_res_resource *
423: bin_to_res_dialog (windres_bfd *wrbfd, const bfd_byte *data, rc_uint_type length)
424: {
425: rc_uint_type signature;
426: rc_dialog *d;
427: rc_uint_type c, sublen, i;
428: rc_uint_type off;
429: rc_dialog_control **pp;
430: rc_res_resource *r;
431:
432: if (length < 18)
433: toosmall (_("dialog header"));
434:
435: d = (rc_dialog *) res_alloc (sizeof (rc_dialog));
436:
437: signature = windres_get_16 (wrbfd, data + 2, 2);
438: if (signature != 0xffff)
439: {
440: d->ex = NULL;
441: d->style = windres_get_32 (wrbfd, data, 4);
442: d->exstyle = windres_get_32 (wrbfd, data + 4, 4);
443: off = 8;
444: }
445: else
446: {
447: int version;
448:
449: version = windres_get_16 (wrbfd, data, 2);
450: if (version != 1)
451: fatal (_("unexpected DIALOGEX version %d"), version);
452:
453: d->ex = (rc_dialog_ex *) res_alloc (sizeof (rc_dialog_ex));
454: d->ex->help = windres_get_32 (wrbfd, data + 4, 4);
455: d->exstyle = windres_get_32 (wrbfd, data + 8, 4);
456: d->style = windres_get_32 (wrbfd, data + 12, 4);
457: off = 16;
458: }
459:
460: if (length < off + 10)
461: toosmall (_("dialog header"));
462:
463: c = windres_get_16 (wrbfd, data + off, 2);
464: d->x = windres_get_16 (wrbfd, data + off + 2, 2);
465: d->y = windres_get_16 (wrbfd, data + off + 4, 2);
466: d->width = windres_get_16 (wrbfd, data + off + 6, 2);
467: d->height = windres_get_16 (wrbfd, data + off + 8, 2);
468:
469: off += 10;
470:
471: sublen = get_resid (wrbfd, &d->menu, data + off, length - off);
472: off += sublen;
473:
474: sublen = get_resid (wrbfd, &d->class, data + off, length - off);
475: off += sublen;
476:
477: d->caption = get_unicode (wrbfd, data + off, length - off, &sublen);
478: off += sublen * 2 + 2;
479: if (sublen == 0)
480: d->caption = NULL;
481:
482: if ((d->style & DS_SETFONT) == 0)
483: {
484: d->pointsize = 0;
485: d->font = NULL;
486: if (d->ex != NULL)
487: {
488: d->ex->weight = 0;
489: d->ex->italic = 0;
490: d->ex->charset = 1;
491: }
492: }
493: else
494: {
495: if (length < off + 2)
496: toosmall (_("dialog font point size"));
497:
498: d->pointsize = windres_get_16 (wrbfd, data + off, 2);
499: off += 2;
500:
501: if (d->ex != NULL)
502: {
503: if (length < off + 4)
504: toosmall (_("dialogex font information"));
505: d->ex->weight = windres_get_16 (wrbfd, data + off, 2);
506: d->ex->italic = windres_get_8 (wrbfd, data + off + 2, 1);
507: d->ex->charset = windres_get_8 (wrbfd, data + off + 3, 1);
508: off += 4;
509: }
510:
511: d->font = get_unicode (wrbfd, data + off, length - off, &sublen);
512: off += sublen * 2 + 2;
513: }
514:
515: d->controls = NULL;
516: pp = &d->controls;
517:
518: for (i = 0; i < c; i++)
519: {
520: rc_dialog_control *dc;
521: int datalen;
522:
523: off = (off + 3) &~ 3;
524:
525: dc = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
526:
527: if (d->ex == NULL)
528: {
529: if (length < off + 8)
530: toosmall (_("dialog control"));
531:
532: dc->style = windres_get_32 (wrbfd, data + off, 4);
533: dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
534: dc->help = 0;
535: off += 8;
536: }
537: else
538: {
539: if (length < off + 12)
540: toosmall (_("dialogex control"));
541: dc->help = windres_get_32 (wrbfd, data + off, 4);
542: dc->exstyle = windres_get_32 (wrbfd, data + off + 4, 4);
543: dc->style = windres_get_32 (wrbfd, data + off + 8, 4);
544: off += 12;
545: }