00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "global.h"
00026 #ifdef HAVE_HDRSTOP
00027 #pragma hdrstop
00028 #endif
00029
00030 #include <ctime>
00031 #include <cstring>
00032 #include <cctype>
00033 #include <stdexcept>
00034
00035 #include "rva.h"
00036 #include "pefile.hpp"
00037 #include "apicache.h"
00038 #include "utils/compilecheck.hpp"
00039
00040 #define Error(s) { throw std::runtime_error(s); }
00041
00042 static const char *const szDirectoryEntries[] =
00043 {
00044 "Export",
00045 "Import",
00046 "Resource",
00047 "Exception",
00048 "Security",
00049 "Relocation",
00050 "Debug",
00051 "Copyright",
00052 "GlobalPtr",
00053 "TLS",
00054 "Load Configuration",
00055 "Bound Import",
00056 "IAT",
00057 "Delayed Imports",
00058 "COM Runtime",
00059 "Reserved"
00060 };
00061
00062 PeFile::PeFile(ICFile& _file):
00063 file(_file),rva(NULL)
00064 {
00065 file.Seek(0);
00066
00067 PE_IMAGE_DOS_HEADER dos_hdr;
00068 RawRead(file,dos_hdr);
00069 if ( dos_hdr.e_magic != IMAGE_DOS_SIGNATURE )
00070 Error("File is not a valid DOS EXE");
00071 file.Seek(dos_hdr.e_lfanew);
00072
00073 RawRead(file,nt_hdr);
00074 if ( nt_hdr.Signature != IMAGE_NT_SIGNATURE )
00075 Error("Invalid NT EXE file");
00076
00077 if ( nt_hdr.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC )
00078 Error("Invalid NT optional header");
00079
00080 long sections_pos =
00081 dos_hdr.e_lfanew + FIELD_OFFSET( PE_IMAGE_NT_HEADERS, OptionalHeader ) +
00082 nt_hdr.FileHeader.SizeOfOptionalHeader;
00083 file.Seek(sections_pos);
00084
00085 numSection = nt_hdr.FileHeader.NumberOfSections;
00086 sections = new PE_IMAGE_SECTION_HEADER[numSection];
00087 for (unsigned i=0; i<numSection; ++i)
00088 {
00089 RawRead(file,sections[i]);
00090 }
00091
00092
00093 rva = new RVAFileTranslator(sections,numSection);
00094 }
00095
00096 PeFile::~PeFile()
00097 {
00098
00099 delete rva;
00100 delete [] sections;
00101 }
00102
00103 void PeFile::WriteFileHdr(const PE_IMAGE_FILE_HEADER& hdr)
00104 {
00105 #define FIELD "%-30s"
00106 const char *machine = "Unknown";
00107 switch (hdr.Machine) {
00108 default:
00109 case IMAGE_FILE_MACHINE_UNKNOWN:
00110 break;
00111 case IMAGE_FILE_MACHINE_I386: machine = "I386"; break;
00112 case IMAGE_FILE_MACHINE_R3000: machine = "R3000"; break;
00113 case IMAGE_FILE_MACHINE_R4000: machine = "R4000"; break;
00114 case IMAGE_FILE_MACHINE_R10000: machine = "R10000"; break;
00115 case IMAGE_FILE_MACHINE_ALPHA: machine = "Alpha"; break;
00116 case IMAGE_FILE_MACHINE_POWERPC: machine = "PowerPC"; break;
00117 }
00118 printf("File header information\n\n");
00119 printf(FIELD "%s\n","Machine",machine);
00120 printf(FIELD "%u\n","Section #",hdr.NumberOfSections);
00121 printf(FIELD "%08X\n","TimeStamp",hdr.TimeDateStamp);
00122 printf(FIELD "%08X\n","SymbolTable pointer",hdr.PointerToSymbolTable);
00123 printf(FIELD "%u\n","Symbol #",hdr.NumberOfSymbols);
00124 printf(FIELD "%u\n","Optional header size",hdr.SizeOfOptionalHeader);
00125 uint_fast16_t car = hdr.Characteristics;
00126 printf("Characteristics %X\n",(int)car);
00127 if ( car&IMAGE_FILE_RELOCS_STRIPPED )
00128 printf(" Relocation info stripped from file\n");
00129 if ( car&IMAGE_FILE_EXECUTABLE_IMAGE )
00130 printf(" File is executable\n");
00131 if ( car&IMAGE_FILE_LINE_NUMS_STRIPPED )
00132 printf(" Line nunbers stripped from file\n");
00133 if ( car&IMAGE_FILE_LOCAL_SYMS_STRIPPED )
00134 printf(" Local symbols stripped from file\n");
00135 if ( car&IMAGE_FILE_BYTES_REVERSED_LO )
00136 printf(" Bytes of machine word are reversed\n");
00137 if ( car&IMAGE_FILE_32BIT_MACHINE )
00138 printf(" 32 bit word machine\n");
00139 if ( car&IMAGE_FILE_DEBUG_STRIPPED )
00140 printf(" Debugging info stripped from file in .DBG file\n");
00141 if ( car&IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP )
00142 printf(" If Image is on removable media, copy and run from the swap file\n");
00143 if ( car&IMAGE_FILE_NET_RUN_FROM_SWAP )
00144 printf(" If Image is on Net, copy and run from the swap file\n");
00145 if ( car&IMAGE_FILE_SYSTEM )
00146 printf(" System File\n");
00147 if ( car&IMAGE_FILE_DLL )
00148 printf(" File is a DLL\n");
00149 if ( car&IMAGE_FILE_BYTES_REVERSED_HI )
00150 printf(" Bytes of machine word are reversed\n");
00151 printf("\n");
00152 #undef FIELD
00153 }
00154
00155 void PeFile::WriteOptionalHdr(const PE_IMAGE_OPTIONAL_HEADER& hdr)
00156 {
00157 #define FIELD "%-30s"
00158 printf("Optional header information\n\n");
00159 printf(FIELD "%04X\n","Magic",hdr.Magic);
00160 printf(FIELD "%d.%d\n","Linker",hdr.MajorLinkerVersion,hdr.MinorLinkerVersion);
00161 printf(FIELD "%08X\n","Code size",hdr.SizeOfCode);
00162 printf(FIELD "%08X\n","Initialized data size",hdr.SizeOfInitializedData);
00163 printf(FIELD "%08X\n","Uninitialized data size",hdr.SizeOfUninitializedData);
00164 printf(FIELD "%08X\n","Entry point RVA",hdr.AddressOfEntryPoint);
00165 printf(FIELD "%08X\n","Code base RVA",hdr.BaseOfCode);
00166 printf(FIELD "%08X\n","Data base RVA",hdr.BaseOfData);
00167
00168 printf(FIELD "%08X\n","Image base",hdr.ImageBase);
00169 printf(FIELD "%08X/%08X\n","Section/File align",hdr.SectionAlignment,hdr.FileAlignment);
00170 printf(FIELD "%d.%d\n","O/S version",hdr.MajorOperatingSystemVersion,hdr.MinorOperatingSystemVersion);
00171 printf(FIELD "%d.%d\n","Image version",hdr.MajorImageVersion,hdr.MinorImageVersion);
00172 printf(FIELD "%d.%d\n","Subsystem version",hdr.MajorSubsystemVersion,hdr.MinorSubsystemVersion);
00173 printf(FIELD "%08X\n","Win32 version",hdr.Win32VersionValue);
00174 printf(FIELD "%08X\n","Image size",hdr.SizeOfImage);
00175 printf(FIELD "%08X\n","Headers size",hdr.SizeOfHeaders);
00176 printf(FIELD "%08X\n","Checksum",hdr.CheckSum);
00177 const char *subsystem= "Unknown";
00178 switch (hdr.Subsystem) {
00179 default:
00180 case IMAGE_SUBSYSTEM_UNKNOWN:
00181 break;
00182 case IMAGE_SUBSYSTEM_NATIVE: subsystem="Native"; break;
00183 case IMAGE_SUBSYSTEM_WINDOWS_GUI: subsystem="Windows GUI"; break;
00184 case IMAGE_SUBSYSTEM_WINDOWS_CUI: subsystem="Windows Consolle"; break;
00185 case IMAGE_SUBSYSTEM_OS2_CUI: subsystem="OS2 Consolle"; break;
00186 case IMAGE_SUBSYSTEM_POSIX_CUI: subsystem="Posix Consolle"; break;
00187 }
00188 printf(FIELD "%d (%s)\n","Subsystem",hdr.Subsystem,subsystem);
00189 printf(FIELD "%08X\n","DLL flags",hdr.DllCharacteristics);
00190 printf(FIELD "%08X/%08X\n","Stack reserve/commit",hdr.SizeOfStackReserve,hdr.SizeOfStackCommit);
00191 printf(FIELD "%08X/%08X\n","Heap reserve/commit",hdr.SizeOfHeapReserve,hdr.SizeOfHeapCommit);
00192 printf(FIELD "%08X\n","Loader flags",hdr.LoaderFlags);
00193 printf(FIELD "%u\n","RVA #",hdr.NumberOfRvaAndSizes);
00194 printf("\n%-20s%-10sSize\n","Name","RVA");
00195 printf("-----------------------------\n");
00196 for(int i=0; i<16; ++i)
00197 printf("%-20s%08X %08X\n",szDirectoryEntries[i],hdr.DataDirectory[i].VirtualAddress,hdr.DataDirectory[i].Size);
00198 printf("\n");
00199 #undef FIELD
00200 }
00201
00202 void PeFile::WriteSectionHdr(const PE_IMAGE_SECTION_HEADER& hdr)
00203 {
00204 #define FIELD "%-30s"
00205 printf(FIELD "%-8.8s\n","Name",hdr.Name);
00206 printf(FIELD "%08X\n","PhysicalAddress",hdr.Misc.PhysicalAddress);
00207 printf(FIELD "%08X\n","VirtualAddress",hdr.VirtualAddress);
00208 printf(FIELD "%08X\n","Size of raw data",hdr.SizeOfRawData);
00209 printf(FIELD "%08X\n","Pointer to raw data",hdr.PointerToRawData);
00210 printf(FIELD "%08X\n","Pointer to relocations",hdr.PointerToRelocations);
00211 printf(FIELD "%08X\n","Pointer to linenumbers",hdr.PointerToLinenumbers);
00212 printf(FIELD "%04X\n","Number of relocations",hdr.NumberOfRelocations);
00213 printf(FIELD "%04X\n","Number of line numbers",hdr.NumberOfLinenumbers);
00214
00215 printf("Characteristics\n");
00216 uint32_t car = hdr.Characteristics;
00217 if ( car&IMAGE_SCN_CNT_CODE ) printf(" Section contains code\n");
00218 if ( car&IMAGE_SCN_CNT_INITIALIZED_DATA ) printf(" Section contains initialized data\n");
00219 if ( car&IMAGE_SCN_CNT_UNINITIALIZED_DATA ) printf(" Section contains uninitialized data\n");
00220 if ( car&IMAGE_SCN_LNK_INFO ) printf(" Section contains comments or some other type of information\n");
00221 if ( car&IMAGE_SCN_LNK_REMOVE ) printf(" Section contents will not become part of image\n");
00222 if ( car&IMAGE_SCN_LNK_COMDAT ) printf(" Section contents comdat\n");
00223
00224 if ( car&IMAGE_SCN_MEM_FARDATA ) printf(" FarData\n");
00225 if ( car&IMAGE_SCN_MEM_PURGEABLE ) printf(" Purgeable\n");
00226 if ( car&IMAGE_SCN_MEM_16BIT ) printf(" 16bit\n");
00227 if ( car&IMAGE_SCN_MEM_LOCKED ) printf(" Locked\n");
00228 if ( car&IMAGE_SCN_MEM_PRELOAD ) printf(" Preload\n");
00229
00230 if ( car&IMAGE_SCN_ALIGN_1BYTES ) printf(" Align 1 byte\n");
00231 if ( car&IMAGE_SCN_ALIGN_2BYTES ) printf(" Align 2 bytes\n");
00232 if ( car&IMAGE_SCN_ALIGN_4BYTES ) printf(" Align 4 bytes\n");
00233 if ( car&IMAGE_SCN_ALIGN_8BYTES ) printf(" Align 8 bytes\n");
00234 if ( car&IMAGE_SCN_ALIGN_16BYTES ) printf(" Align 16 bytes\n");
00235 if ( car&IMAGE_SCN_ALIGN_32BYTES ) printf(" Align 32 bytes\n");
00236 if ( car&IMAGE_SCN_ALIGN_64BYTES ) printf(" Align 64 bytes\n");
00237
00238 if ( car&IMAGE_SCN_LNK_NRELOC_OVFL ) printf(" Section contains extended relocations\n");
00239 if ( car&IMAGE_SCN_MEM_DISCARDABLE ) printf(" Discardable\n");
00240 if ( car&IMAGE_SCN_MEM_NOT_CACHED ) printf(" Not cachable\n");
00241 if ( car&IMAGE_SCN_MEM_NOT_PAGED ) printf(" Not pageable\n");
00242 if ( car&IMAGE_SCN_MEM_SHARED ) printf(" Shareable\n");
00243 if ( car&IMAGE_SCN_MEM_EXECUTE ) printf(" Executable\n");
00244 if ( car&IMAGE_SCN_MEM_READ ) printf(" Readable\n");
00245 if ( car&IMAGE_SCN_MEM_WRITE ) printf(" Writeable\n");
00246 printf("\n");
00247 #undef FIELD
00248 }
00249
00250 #ifdef __BORLANDC__
00251 #pragma argsused
00252 #endif
00253 void PeFile::WriteImport(uint32_t address,uint32_t hint,const char* dll_name,const char* func_name,void* param)
00254 {
00255 if (address == 0)
00256 printf("\nDLL: %s\n",dll_name);
00257 else
00258 {
00259 printf(" Addr:%08lX ",(long int)address);
00260 if (func_name==NULL)
00261 {
00262 std::string name;
00263 if (ApiCache::GetFullApiName(name,dll_name,hint))
00264 printf("Ordinal:%u(%04X) (%s)\n",hint,hint,name.c_str());
00265 else
00266 printf("Ordinal:%u(%04X)\n",hint,hint);
00267 }
00268 else
00269 printf("hint:%u(%04X) Name:%s\n",hint,hint,func_name);
00270 }
00271 }
00272
00273 #ifdef __BORLANDC__
00274 #pragma argsused
00275 #endif
00276 void PeFile::WriteExport(uint32_t address,uint32_t hint,const char* dll_name,const char* func_name,void* param)
00277 {
00278 if (address == 0)
00279 printf("\nDLL: %s\n",dll_name);
00280 else
00281 {
00282 printf(" Addr:%08lX ",(long int)address);
00283 if (func_name==NULL)
00284 printf("Ordinal:%u(%04X)\n",hint,hint);
00285 else
00286 printf("hint:%u(%04X) Name:%s\n",hint,hint,func_name);
00287 }
00288 }
00289
00290 void PeFile::ParseImport(PImportProc proc,void* param)
00291 {
00292 const PE_IMAGE_DATA_DIRECTORY& imports =
00293 GetDataDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT);
00294 if ( imports.VirtualAddress == 0 || imports.Size == 0 )
00295 return;
00296
00297 file.Seek(GetRVA().RVA2FileSafe(imports.VirtualAddress));
00298 for (;;)
00299 {
00300 PE_IMAGE_IMPORT_DESCRIPTOR desc;
00301 RawRead(file,desc);
00302 long pos = file.Tell();
00303
00304
00305 if (desc.Characteristics == 0 && desc.FirstThunk == 0)
00306 break;
00307
00308 uint32_t address = desc.FirstThunk;
00309
00310
00311 file.Seek(GetRVA().RVA2FileSafe(desc.Name));
00312 char *pDllName = file.ReadString();
00313 proc(0,0,pDllName,NULL,param);
00314
00315
00316 int len = strlen(pDllName);
00317 if (len>=4 && stricmp(pDllName+(len-4),".dll") == 0)
00318 pDllName[len-4] = '\0';
00319
00320
00321
00322 if (desc.OriginalFirstThunk == 0)
00323 file.Seek(GetRVA().RVA2FileSafe((uint32_t)desc.FirstThunk));
00324 else
00325 file.Seek(GetRVA().RVA2FileSafe((uint32_t)desc.OriginalFirstThunk));
00326 for (;;)
00327 {
00328 PE_IMAGE_THUNK_DATA thunk;
00329 RawRead(file,thunk);
00330 long pos2 = file.Tell();
00331
00332
00333 if (thunk.u1.Ordinal == 0)
00334 break;
00335
00336 if (IMAGE_SNAP_BY_ORDINAL(thunk.u1.Ordinal))
00337 {
00338
00339 proc(address,IMAGE_ORDINAL(thunk.u1.Ordinal),pDllName,NULL,param);
00340 }
00341 else
00342 {
00343
00344 uint16_t hint;
00345
00346
00347 file.Seek(GetRVA().RVA2FileSafe((uint32_t)thunk.u1.AddressOfData));
00348 RawRead(file,hint);
00349 char *p = file.ReadString();
00350 proc(address,hint,pDllName,p,param);
00351 delete [] p;
00352 }
00353 address += sizeof(PE_IMAGE_THUNK_DATA);
00354
00355 file.Seek(pos2);
00356 }
00357 file.Seek(pos);
00358 delete[] pDllName;
00359 }
00360 }
00361
00362 void PeFile::ParseExport(PExportProc proc,void* param)
00363 {
00364
00365 const PE_IMAGE_DATA_DIRECTORY& export_ =
00366 GetDataDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT);
00367 if ( export_.VirtualAddress == 0 || export_.Size == 0 )
00368 return;
00369
00370 file.Seek(GetRVA().RVA2FileSafe(export_.VirtualAddress));
00371
00372 PE_IMAGE_EXPORT_DIRECTORY desc;
00373 RawRead(file,desc);
00374
00375
00376 file.Seek(GetRVA().RVA2FileSafe(desc.Name));
00377 char *pDllName = file.ReadString();
00378 proc(0,0,pDllName,NULL,param);
00379
00380
00381 int len = strlen(pDllName);
00382 if (len>=4 && stricmp(pDllName+(len-4),".dll") == 0)
00383 pDllName[len-4] = '\0';
00384
00385
00386 int ordBase = desc.Base;
00387 long functionPos = GetRVA().RVA2FileSafe(desc.AddressOfFunctions);
00388 long ordinalPos = GetRVA().RVA2FileSafe(desc.AddressOfNameOrdinals);
00389 long namePos = GetRVA().RVA2FileSafe(desc.AddressOfNames);
00390
00391 char **names= new char*[desc.NumberOfFunctions];
00392
00393
00394 unsigned n;
00395 for( n = 0; n<desc.NumberOfFunctions; ++n)
00396 names[n] = NULL;
00397
00398 for( n = 0; n<desc.NumberOfNames; ++n)
00399 {
00400 uint16_t ordinal;
00401 char *pName;
00402
00403
00404 uint32_t pos;
00405 file.Seek(namePos);
00406 RawRead(file,pos);
00407 namePos = file.Tell();
00408
00409
00410 file.Seek(GetRVA().RVA2FileSafe(pos));
00411 pName = file.ReadString();
00412
00413
00414 file.Seek(ordinalPos);
00415 RawRead(file,ordinal);
00416 ordinalPos = file.Tell();
00417
00418
00419 if (ordinal >= desc.NumberOfFunctions )
00420 throw std::runtime_error("bad ordinal");
00421
00422 names[ordinal] = pName;
00423 }
00424
00425 file.Seek(functionPos);
00426 for( n = 0; n<desc.NumberOfFunctions; ++n)
00427 {
00428
00429 uint32_t funcRVA;
00430 if (file.Tell() != functionPos)
00431 file.Seek(functionPos);
00432 RawRead(file,funcRVA);
00433
00434 if (funcRVA != 0)
00435 proc(funcRVA,ordBase + n,pDllName,names[n],param);
00436 functionPos += 4;
00437
00438 delete[] names[n];
00439 }
00440
00441 delete[] names;
00442 delete[] pDllName;
00443 }
00444
00445 typedef void (*PRelocationProc)(uint32_t address,unsigned type,void* param);
00446 #ifdef __BORLANDC__
00447 #pragma argsused
00448 #endif
00449 void PeFile::WriteRelocation(uint32_t address,unsigned type,void* param)
00450 {
00451 printf("%08lX ",(long int)address);
00452 switch(type)
00453 {
00454 case IMAGE_REL_BASED_ABSOLUTE:
00455 printf("Absolute\n"); break;
00456 case IMAGE_REL_BASED_HIGH:
00457 printf("Relative High\n"); break;
00458 case IMAGE_REL_BASED_LOW:
00459 printf("Relative Low\n"); break;
00460 case IMAGE_REL_BASED_HIGHLOW:
00461 printf("Relative HighLow\n"); break;
00462 case IMAGE_REL_BASED_HIGHADJ:
00463 printf("Relative HighAdj\n"); break;
00464 default:
00465 printf("Unknown\n"); break;
00466 }
00467 }
00468
00469 void PeFile::ParseRelocations(PRelocationProc proc,void* param)
00470 {
00471 const PE_IMAGE_DATA_DIRECTORY& relocation =
00472 GetDataDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC);
00473 if ( relocation.VirtualAddress == 0 || relocation.Size == 0 )
00474 return;
00475
00476 file.Seek(GetRVA().RVA2FileSafe(relocation.VirtualAddress));
00477 if (proc == PeFile::WriteRelocation)
00478 {
00479 printf("\nRelocations\n");
00480 printf("Address Type\n");
00481 }
00482 for (;;)
00483 {
00484 PE_IMAGE_BASE_RELOCATION chunk;
00485 long pos = file.Tell();
00486 RawRead(file,chunk);
00487 if (chunk.VirtualAddress == 0)
00488 break;
00489 for (int i=(chunk.SizeOfBlock - sizeof(chunk))>>1; i>0; --i)
00490 {
00491 uint16_t info;
00492 RawRead(file,info);
00493 if (info == 0)
00494 break;
00495 proc(chunk.VirtualAddress+(info&0xFFFu),info>>12,param);
00496 }
00497 file.Seek(pos+chunk.SizeOfBlock);
00498 }
00499 printf("\n");
00500 }
00501
00502
00503 static void WriteBinary(const ICFile& file,int _len)
00504 {
00505 _PRG_ASSERT(_len>0);
00506 unsigned int len = (unsigned int)_len;
00507 unsigned address = 0;
00508 const unsigned nCarInRow = 16;
00509 char buffer[3*nCarInRow+nCarInRow+10];
00510 for(unsigned n=0;;++n)
00511 {
00512 unsigned part = n%nCarInRow;
00513 if (part==0)
00514 {
00515 if (n>=nCarInRow)
00516 {
00517 buffer[nCarInRow*3+nCarInRow+1] = '\0';
00518 printf("%08X %s\n",address+n-nCarInRow,buffer);
00519 if (n>=len)
00520 return;
00521 }
00522
00523 memset(buffer,' ',sizeof(buffer));
00524 }
00525 if (n<len)
00526 {
00527 uint8_t car;
00528 file.RawRead(&car,1);
00529
00530
00531 sprintf(buffer+part*3,"%02X",car);
00532 buffer[part*3+2] = part==(nCarInRow/2-1)?'-':' ';
00533
00534 buffer[nCarInRow*3+1+part] = isprint(car)?car:'.';
00535 }
00536 }
00537 }
00538
00539
00540 COMPILE_CHECK(error_Only_ASCII_charset_supported,
00541 ('0' == 0x30 && '9' == 0x39 && 'A' == 0x41 && 'Z' == (0x41+25) &&
00542 'a' == 0x61 && 'z' == (0x61+25) && ' ' == 32 && '\t' == 9 && '\n' == 10)
00543 );
00544
00545
00546 static void out_ws(const unicode_t* s)
00547 {
00548 for(;*s;++s)
00549 {
00550 char c;
00551 c = char((*s) & 0xff);
00552
00553 if ( (*s) < 256 && isprint(c) )
00554 printf("%c",c);
00555 else
00556 printf("\\x%04x",*s);
00557 }
00558 }
00559
00560
00561
00562
00563
00564
00565
00566 static void WriteResource(ICFile& file,const PeResourceDirectoryData* data,const PeResourceDirectoryInfo* info,unsigned level,void*)
00567 {
00568
00569 if (level == 0 && data == NULL)
00570 {
00571 printf("Resources\n");
00572 printf("%*s%-16s%08X\n",level*4,"","Characteristics",info->dir.Characteristics);
00573 time_t t = (time_t)info->dir.TimeDateStamp;
00574 printf("%*s%-16s%08X %s",level*4,"","TimeDateStamp",info->dir.TimeDateStamp,ctime(&t));
00575 printf("%*s%-16s%i:%i\n",level*4,"","Version",info->dir.MajorVersion,info->dir.MinorVersion);
00576 }
00577 else
00578 {
00579
00580
00581 const PeResourceId* p = data?(const PeResourceId*)data:(const PeResourceId*)info;
00582 if (p)
00583 {
00584 printf("%*s",(level)*4,"");
00585 switch(level-1)
00586 {
00587 case 0:
00588 printf("Type ");
00589 switch(p->id)
00590 {
00591 case 1: printf("cursor"); break;
00592 case 2: printf("bitmap"); break;
00593 case 3: printf("icon"); break;
00594 case 4: printf("menu"); break;
00595 case 5: printf("dialog"); break;
00596 case 6: printf("string table"); break;
00597 case 7: printf("font directory"); break;
00598 case 8: printf("font"); break;
00599 case 9: printf("accelerators"); break;
00600 case 10: printf("unformatted resource data"); break;
00601 case 11: printf("message table"); break;
00602 case 12: printf("group cursor"); break;
00603 case 14: printf("group icon"); break;
00604 case 16: printf("version information"); break;
00605 case 17: printf("dialog include"); break;
00606 case 19: printf("plug & play"); break;
00607 case 20: printf("vxd"); break;
00608 case 21: printf("animate cursor"); break;
00609 case 22: printf("animate icon"); break;
00610 case 23: printf("html"); break;
00611 default: printf("unknown"); break;
00612 }
00613 if (p->name)
00614 {
00615 printf(" (");
00616 out_ws(p->name);
00617 printf(")\n");
00618 }
00619 else
00620 printf(" (%i)\n",p->id);
00621 break;
00622 case 1:
00623 if (p->name)
00624 {
00625 printf("ID ");
00626 out_ws(p->name);
00627 printf("\n");
00628 }
00629 else
00630 printf("ID %i\n",p->id);
00631 break;
00632 case 2:
00633 if (p->name)
00634 {
00635 printf("LangID ");
00636 out_ws(p->name);
00637 printf("\n");
00638 }
00639 else
00640 printf("LangID %i\n",p->id);
00641 break;
00642 default:
00643 if (p->name)
00644 {
00645 printf("Name ");
00646 out_ws(p->name);
00647 printf("\n");
00648 }
00649 else
00650 printf("Name %08X\n",p->id);
00651 break;
00652 }
00653 }
00654 }
00655
00656
00657 if (data == NULL)
00658 printf("%*s%-16s%i named %i id\n",level*4,"","Entryes",info->dir.NumberOfNamedEntries,info->dir.NumberOfIdEntries);
00659
00660
00661 if (data)
00662 {
00663 printf("%*s%-16s%08X\n",(level)*4,"","OffsetToData",data->data.OffsetToData);
00664 printf("%*s%-16s%08X\n",(level)*4,"","Size",data->data.Size);
00665 printf("%*s%-16s%08X\n",(level)*4,"","CodePage",data->data.CodePage);
00666 printf("%*s%-16s%08X\n",(level)*4,"","Reserved",data->data.Reserved);
00667
00668 WriteBinary(file,data->data.Size);
00669 }
00670 }
00671
00672 static void ParseResourceDirectory(const RVAFileTranslator& rva,uint32_t start,PeResourceDirectoryInfo *info,unsigned level,ICFile& file,PeFile::PResourceProc proc,void* param)
00673 {
00674
00675 RawRead(file,info->dir);
00676
00677 proc(file,NULL,info,level,param);
00678
00679 int i = info->dir.NumberOfNamedEntries + info->dir.NumberOfIdEntries;
00680 for(;i>0;--i)
00681 {
00682 PE_IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
00683 RawRead(file,entry);
00684 long pos = file.Tell();
00685
00686 unicode_t *pName = NULL;
00687 if ( RESOURCE_ENTRY_ISSTRING(entry) )
00688 {
00689
00690 file.Seek(start+RESOURCE_ENTRY_NAME_OFFSET(entry));
00691 pName = (unicode_t*)file.ReadStringFlag(
00692 ICFile::strUcs2|ICFile::strLen16);
00693 }
00694
00695 if ( RESOURCE_ENTRY_ISDIRECTORY(entry) )
00696 {
00697 file.Seek(start+RESOURCE_ENTRY_DATA_OFFSET(entry) );
00698
00699
00700 PeResourceDirectoryInfo _info;
00701 _info.name = pName;
00702 _info.id = RESOURCE_ENTRY_GETID(entry);
00703 _info.highLevel = info;
00704
00705 ParseResourceDirectory(rva,start,&_info,level+1,file,proc,param);
00706 }
00707 else
00708 {
00709 file.Seek(start+entry.u2.OffsetToData);
00710
00711
00712 PeResourceDirectoryData data;
00713 RawRead(file,data.data);
00714 data.id = RESOURCE_ENTRY_GETID(entry);
00715 data.name = pName;
00716
00717 file.Seek(rva.RVA2FileSafe(data.data.OffsetToData));
00718 proc(file,&data,info,level+1,param);
00719 }
00720 delete [] pName;
00721
00722 file.Seek(pos);
00723 }
00724 }
00725
00726 void PeFile::ParseResource(PResourceProc proc,void* param)
00727 {
00728 const PE_IMAGE_DATA_DIRECTORY& resource =
00729 GetDataDirectory(IMAGE_DIRECTORY_ENTRY_RESOURCE);
00730 if ( resource.VirtualAddress == 0 || resource.Size == 0 )
00731 return;
00732
00733 uint32_t start = GetRVA().RVA2FileSafe(resource.VirtualAddress);
00734 file.Seek(start);
00735
00736
00737 PeResourceDirectoryInfo info;
00738 info.name = NULL;
00739 info.id = 0;
00740 info.highLevel = NULL;
00741
00742 ParseResourceDirectory(GetRVA(),start,&info,0,file,proc,param);
00743 }
00744
00745 void PeFile::WriteResource()
00746 {
00747 ParseResource(::WriteResource,NULL);
00748 }
00749