00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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;
00087
00088 PE_RESOURCE_DIRECTORY dir;
00089
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
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
00173
00174 FILEOFS iofs;
00175 dword irva;
00176 if (pe32) {
00177 irva=pe_shared->pe32.header_nt.directory[PE_DIRECTORY_ENTRY_RESOURCE].address;
00178
00179 } else {
00180 irva=pe_shared->pe64.header_nt.directory[PE_DIRECTORY_ENTRY_RESOURCE].address;
00181 }
00182
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
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 }