Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

htperes.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      htperes.cc
00004  *
00005  *      Copyright (C) 1999-2002 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include "formats.h"
00022 #include "htapp.h"
00023 #include "htctrl.h"
00024 #include "htdialog.h"
00025 #include "htendian.h"
00026 #include "hthex.h"
00027 #include "htiobox.h"
00028 #include "htkeyb.h"
00029 #include "htnewexe.h"
00030 #include "htobj.h"
00031 #include "htpe.h"
00032 #include "htperes.h"
00033 #include "htstring.h"
00034 #include "httree.h"
00035 #include "log.h"
00036 #include "pestruct.h"
00037 #include "stream.h"
00038 
00039 #include <string.h>
00040 
00041 static int_hash restypes[] = {
00042         {0x0001, "cursors"},
00043         {0x0002, "bitmaps"},
00044         {0x0003, "icons"},
00045         {0x0004, "menus"},
00046         {0x0005, "dialogs"},
00047         {0x0006, "string tables"},
00048         {0x0007, "font directories"},
00049         {0x0008, "fonts"},
00050         {0x0009, "accelerators"},
00051         {0x000a, "custom resource data"},
00052         {0x000b, "message tables"},
00053         {0x000c, "group cursors"},
00054         {0x000e, "group icons"},
00055         {0x0010, "version information"},
00056         {0x0011, "dialog includes"},
00057         {0x0013, "pnp"},
00058         {0x0014, "vxd"},
00059         {0x0015, "animated cursors"},
00060         { 0 }
00061 };
00062 
00063 static int_hash languages[] = {
00064         {7,  "german"},
00065         {9,  "english"},
00066         {10, "spanish"},
00067         {12, "french"},
00068         {16, "italian"},
00069         { 0 }
00070 };
00071 
00072 class ht_pe_resource_leaf: public Object {
00073 public:
00074         dword offset;
00075         dword size;
00076 };
00077 
00078 static ht_streamfile *peresource_file;
00079 static FILEOFS peresource_dir_ofs;
00080 static ht_static_treeview *peresource_tree;
00081 static char peresource_string[128];
00082 static pe_section_headers *peresource_section_headers;
00083 
00084 static void read_resource_dir(void *node, int ofs, int level)
00085 {
00086         if (level>2) return;            /* no deep recursions please (for
00087                                                            currupted resource directories) */
00088         PE_RESOURCE_DIRECTORY dir;
00089 // get directory
00090         peresource_file->seek(peresource_dir_ofs+ofs);
00091         if (peresource_file->read(&dir, sizeof dir) != (sizeof dir)) return;
00092         create_host_struct(&dir, PE_RESOURCE_DIRECTORY_struct, little_endian);
00093 // get entries
00094         PE_RESOURCE_DIRECTORY_ENTRY entry;
00095         for (int i=0; i<dir.name_count+dir.id_count; i++) {
00096                 peresource_file->seek(peresource_dir_ofs+ofs+sizeof dir+i*8);
00097                 peresource_file->read(&entry, sizeof entry);
00098                 create_host_struct(&entry, PE_RESOURCE_DIRECTORY_ENTRY_struct, little_endian);
00099                 char *rm = peresource_string;
00100                 if (entry.offset_to_directory & 0x80000000) {
00101                         bool hasname = entry.name & 0x80000000;
00102                         PE_RESOURCE_DIRECTORY subdir;
00103                         peresource_file->seek(peresource_dir_ofs+entry.offset_to_directory & 0x7fffffff);
00104                         peresource_file->read(&subdir, sizeof subdir);
00105                         create_host_struct(&subdir, PE_RESOURCE_DIRECTORY_struct, little_endian);
00106                         if (hasname) {
00107                                 peresource_file->seek(peresource_dir_ofs+entry.name & 0x7fffffff);
00108                                 char *name = getstrw(peresource_file);
00109                                 rm += sprintf(rm, "%s [%d]", name, subdir.name_count+subdir.id_count);
00110                                 free(name);
00111                         } else {
00112                                 char *s = (!level) ? s = matchhash(entry.name & 0xffff, restypes) : NULL;
00113                                 if (s) {
00114                                         rm += sprintf(rm, "ID %04x, %s [%d]", entry.name & 0xffff, s, subdir.name_count+subdir.id_count);
00115                                 } else {
00116                                         rm += sprintf(rm, "ID %04x [%d]", entry.name & 0xffff, subdir.name_count+subdir.id_count);
00117                                 }
00118                         }
00119                         void *n = peresource_tree->add_child(node, peresource_string);
00120                         read_resource_dir(n, entry.offset_to_directory & 0x7fffffff, level+1);
00121                 } else {
00122                         char *s = matchhash((char)entry.name, languages);
00123                         if (s) {
00124                                 rm += sprintf(rm, "resource, %s (%04x) ", s, entry.name & 0xffff);
00125                         } else {
00126                                 rm += sprintf(rm, "resource, unknown language (%04x) ", entry.name & 0xffff);
00127                         }
00128 
00129                         PE_RESOURCE_DATA_ENTRY data;
00130                         peresource_file->seek(peresource_dir_ofs+entry.offset_to_directory);
00131                         peresource_file->read(&data, sizeof data);
00132                         create_host_struct(&data, PE_RESOURCE_DATA_ENTRY_struct, little_endian);
00133                         
00134                         ht_pe_resource_leaf *xdata = NULL;
00135                         FILEOFS dofs=0;
00136                         if (pe_rva_to_ofs(peresource_section_headers, data.offset_to_data, &dofs)) {
00137                                 xdata = new ht_pe_resource_leaf();
00138                                 xdata->offset = dofs;
00139                                 xdata->size = data.size;
00140                                 rm += sprintf(rm, "offset %08x", dofs);
00141                         } else {
00142                                 rm += sprintf(rm, "offset ? (rva %08x, currupt)", data.offset_to_data);
00143                         }
00144                         sprintf(rm, " size %08x", data.size);
00145                         peresource_tree->add_child(node, peresource_string, xdata);
00146                 }
00147         }
00148 }
00149 
00150 static ht_view *htperesources_init(bounds *b, ht_streamfile *file, ht_format_group *group)
00151 {
00152         ht_pe_shared_data *pe_shared=(ht_pe_shared_data *)group->get_shared_data();
00153 
00154         if (pe_shared->opt_magic!=COFF_OPTMAGIC_PE32 && pe_shared->opt_magic!=COFF_OPTMAGIC_PE64) return NULL;
00155 
00156         bool pe32 = (pe_shared->opt_magic==COFF_OPTMAGIC_PE32);
00157 
00158         dword sec_rva, sec_size;
00159         if (pe32) {
00160                 sec_rva = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_RESOURCE].address;
00161                 sec_size = pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_RESOURCE].size;
00162         } else {
00163                 sec_rva = pe_shared->pe64.header_nt.directory[PE_DIRECTORY_ENTRY_RESOURCE].address;
00164                 sec_size = pe_shared->pe64.header_nt.directory[PE_DIRECTORY_ENTRY_RESOURCE].size;
00165         }
00166         if (!sec_rva || !sec_size) return NULL;
00167 
00168         ht_static_treeview *t=new ht_pe_resource_viewer();
00169         t->init(b, DESC_PE_RESOURCES);
00170 
00171         void *root;
00172 /* get resource directory offset */
00173         /* 1. get resource directory rva */
00174         FILEOFS iofs;
00175         dword irva;
00176         if (pe32) {
00177                 irva=pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_RESOURCE].address;
00178 //              dword isize=pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_RESOURCE].size;
00179         } else {
00180                 irva=pe_shared->pe64.header_nt.directory[PE_DIRECTORY_ENTRY_RESOURCE].address;
00181         }
00182         /* 2. transform it into an offset */
00183         if (!pe_rva_to_ofs(&pe_shared->sections, irva, &iofs)) goto pe_read_error;
00184 
00185         LOG("%s: PE: reading resource directory at offset %08x, rva %08x", file->get_filename(), iofs, irva);
00186 
00187         peresource_file=file;
00188         peresource_dir_ofs=iofs;
00189         peresource_tree=t;
00190         peresource_section_headers=&pe_shared->sections;
00191 
00192         root=t->add_child(0, "pe resources");
00193 
00194         read_resource_dir(root, 0, 0);
00195 
00196         t->adjust(root, true);
00197         t->update();
00198         pe_shared->v_resources = t;
00199         return t;
00200 pe_read_error:
00201         errorbox("%s: PE resource directory seems to be corrupted.", file->get_filename());
00202         t->done();
00203         delete t;
00204         return NULL;
00205 }
00206 
00207 format_viewer_if htperesources_if = {
00208         htperesources_init,
00209         0
00210 };
00211 
00212 /*
00213  *      CLASS ht_pe_resource_viewer
00214  */
00215 
00216 void ht_pe_resource_viewer::init(bounds *b, char *desc)
00217 {
00218         ht_static_treeview::init(b, desc);
00219         VIEW_DEBUG_NAME("ht_pe_resource_viewer");
00220 }
00221 
00222 void ht_pe_resource_viewer::done()
00223 {
00224         ht_static_treeview::done();
00225 }
00226 
00227 void ht_pe_resource_viewer::handlemsg(htmsg *msg)
00228 {
00229         switch (msg->msg) {
00230                 case msg_vstate_restore:
00231                         vstate_restore((Object*)msg->data1.ptr);
00232                         clearmsg(msg);
00233                         return;
00234         }
00235         ht_static_treeview::handlemsg(msg);
00236 }
00237 
00238 void ht_pe_resource_viewer::select_node(void *node)
00239 {
00240         static_node *s=(static_node*)node;
00241 
00242         if (s->data) {
00243                 ht_group *vr_group=group;
00244                 while (strcmp(vr_group->desc, VIEWERGROUP_NAME)) vr_group=vr_group->group;
00245                 ht_view *c=vr_group->getfirstchild();
00246                 ht_format_viewer *hexv = NULL;
00247                 while (c) {
00248                         if (c->desc && (strcmp(c->desc, DESC_HEX)==0)) {
00249                                 hexv=(ht_format_viewer*)c;
00250                                 break;
00251                         }
00252                         c=c->next;
00253                 }
00254                 if (hexv) {
00255                         vstate_save();
00256                         hexv->goto_offset(((ht_pe_resource_leaf*)s->data)->offset, false);
00257                         hexv->pselect_set(((ht_pe_resource_leaf*)s->data)->offset,
00258                                 ((ht_pe_resource_leaf*)s->data)->offset+((ht_pe_resource_leaf*)s->data)->size);
00259                         app->focus(hexv);
00260                 }
00261         }
00262 }
00263 
00264 class ht_pe_resource_viewer_vstate: public Object {
00265 public:
00266         void *node;
00267 };
00268 
00269 Object *ht_pe_resource_viewer::vstate_create()
00270 {
00271         ht_pe_resource_viewer_vstate *v = new ht_pe_resource_viewer_vstate();
00272         v->node = get_cursor_node();
00273         return v;
00274 }
00275 
00276 bool ht_pe_resource_viewer::vstate_save()
00277 {
00278         Object *vs = vstate_create();
00279         if (vs) {
00280                 htmsg m;
00281                 m.msg = msg_vstate_save;
00282                 m.type = mt_empty;
00283                 m.data1.ptr = vs;
00284                 m.data2.ptr = this;
00285                 app->sendmsg(&m);
00286                 return true;
00287         }
00288         return false;
00289 }
00290 
00291 void ht_pe_resource_viewer::vstate_restore(Object *d)
00292 {
00293         ht_pe_resource_viewer_vstate *v = new ht_pe_resource_viewer_vstate();
00294         goto_node(v->node);
00295 }

Generated on Fri May 7 21:15:36 2004 by doxygen 1.3.5