source: trunk/src/pe2lx/pe.cpp@ 97

Last change on this file since 97 was 97, checked in by phaller, 26 years ago

Add: added cvs variable $Id$ to source files.

File size: 41.3 KB
Line 
1/* $Id: pe.cpp,v 1.3 1999-06-10 17:08:55 phaller Exp $ */
2
3/*
4 * PE2LX PE image interpreter
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Knut St. Osmundsen
8 *
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 *
12 */
13#define INCL_BITMAPFILEFORMAT
14#define INCL_DOSFILEMGR /* File Manager values */
15#define INCL_DOSERRORS /* DOS Error values */
16#define INCL_DOSPROCESS /* DOS Process values */
17#define INCL_DOSMISC /* DOS Miscellanous values */
18#define INCL_WIN
19#define INCL_BASE
20#define INCL_GPIBITMAPS
21#include <os2.h>
22#include <stdio.h>
23#include <string.h>
24#include <stdlib.h>
25#include <iostream.h>
26#include <string.h>
27#include <assert.h>
28#include <versionos2.h>
29#include <pefile.h>
30#include <winimage.h>
31#include "lx.h"
32#include "menu.h"
33#include "dialog.h"
34#include "icon.h"
35#include "icongrp.h"
36#include "rcdata.h"
37#include "misc.h"
38#include "strings.h"
39#include "bitmap.h"
40#include "accelerator.h"
41#include "cursor.h"
42#include "cursorgrp.h"
43
44//#define FORWARDERS
45
46#ifndef max /*PLF Sat 97-06-21 22:25:44*/
47#define max(a,b) ((a>b) ? (a) : (b))
48#endif
49
50/*heximal(decimal) KSO Sun 24.05.1998*/
51char szHexBuffer[30];
52
53char *hex(ULONG num)
54{
55 sprintf(szHexBuffer, "0x%+08x (%lu)",num,num);
56 return szHexBuffer;
57}
58/**/
59
60
61char INFO_BANNER[] =
62"Usage: PE2LX winfile \n\
63 OR\n\
64 PE2LX winfile os2file\n";
65
66char *ResTypes[MAX_RES] =
67 {"niks", "CURSOR", "BITMAP", "ICON", "MENU", "DIALOG", "STRING",
68 "FONTDIR", "FONT", "ACCELERATOR", "RCDATA", "MESSAGETABLE",
69 "GROUP_CURSOR", "niks", "GROUP_ICON", "niks", "VERSION"};
70
71void ProcessResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType, int level, PIMAGE_RESOURCE_DIRECTORY prdRoot, int VirtualAddress, int type, int id);
72void StoreIdResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType, int level, PIMAGE_RESOURCE_DIRECTORY prdRoot, int VirtualAddress, int type, int id);
73BOOL ProcessImports(void *pFile);
74
75int main(int argc, char *argv[])
76{
77HFILE win32handle;
78ULONG ulAction = 0; /* Action taken by DosOpen */
79ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
80APIRET rc = NO_ERROR; /* Return code */
81ULONG filesize, ulRead;
82LPVOID win32file = NULL;
83IMAGE_SECTION_HEADER sh;
84IMAGE_OPTIONAL_HEADER oh;
85IMAGE_FILE_HEADER fh;
86PIMAGE_BASE_RELOCATION prel;
87PIMAGE_RESOURCE_DIRECTORY prdRoot, prdType;
88PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
89PIMAGE_RESOURCE_DATA_ENTRY pData;
90PIMAGE_EXPORT_DIRECTORY ped;
91char *page;
92int i, j, count, id;
93int *ptrNames, *ptrAddress;
94USHORT *ptrOrd;
95PIMAGE_SECTION_HEADER psh;
96int nSections;
97
98 if(argc != 2 && argc != 3) {
99 cout << "pe2lx v0.0." << PE2LX_VERSION << "alpha"<< endl;
100 cout << INFO_BANNER << endl;
101 return(0);
102 }
103
104 rc = DosOpen(argv[1], /* File path name */
105 &win32handle, /* File handle */
106 &ulAction, /* Action taken */
107 0L, /* File primary allocation */
108 0L, /* File attribute */
109 OPEN_ACTION_FAIL_IF_NEW |
110 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
111 OPEN_FLAGS_NOINHERIT |
112 OPEN_SHARE_DENYNONE |
113 OPEN_ACCESS_READONLY, /* Open mode of the file */
114 0L); /* No extended attribute */
115
116 if (rc != NO_ERROR) {
117 cout << "DosOpen returned " << rc << endl;
118 return 1;
119 }
120
121 /* Move the file pointer back to the beginning of the file */
122 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
123 DosSetFilePtr(win32handle, 0L, FILE_END, &filesize);
124 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
125
126 win32file = malloc(filesize);
127 if(win32file == NULL) {
128 cout << "Error allocating " << filesize << " bytes" << endl;
129//SvL: Probably a huge installation file where the installation data is
130// simply appended
131 filesize = 1024*1024;
132
133 win32file = malloc(filesize);
134 if(win32file == NULL) {
135 DosClose(win32handle); /* Close the file */
136 return(1);
137 }
138 }
139 rc = DosRead(win32handle, win32file, filesize, &ulRead);
140 if(rc != NO_ERROR) {
141 cout << "DosRead returned " << rc << endl;
142 DosClose(win32handle); /* Close the file */
143 return(1);
144 }
145 DosClose(win32handle); /* Close the file */ /*PLF Wed 98-03-18 02:32:26 moved */
146
147 if(GetPEFileHeader (win32file, &fh) == FALSE) {
148 cout << "Not a valid PE file (probably a 16 bits windows exe/dll)!" << endl;
149 return(1);
150 }
151
152 if(!(fh.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {//not valid
153 cout << "Not a valid PE file!" << endl;
154 return(1);
155 }
156 if(fh.Machine != IMAGE_FILE_MACHINE_I386) {
157 cout << "You need a REAL CPU to run this code" << endl;
158 return(1);
159 }
160 //IMAGE_FILE_SYSTEM == only drivers (device/file system/video etc)?
161 if(fh.Characteristics & IMAGE_FILE_SYSTEM) {
162 cout << "Can't convert system files" << endl;
163 return(1);
164 }
165 if(argc == 2) {
166 //ok, it's a PE file, so we can safely make a backup copy
167 char *newfile = (char *)malloc(strlen(argv[1])+1);
168 strcpy(newfile, argv[1]);
169 newfile[strlen(newfile)-1]++;
170 //save copy of win32 exe/dll (exe->exf, dll->dlk)
171 rc = DosMove(argv[1], newfile);
172 if(rc) {
173 cout << "Unable to save original win32 file to " << newfile << "(" << rc << ")" << endl;
174 free(newfile);
175 return(1);
176 }
177 free(newfile);
178 }
179 if(fh.Characteristics & IMAGE_FILE_DLL)
180 OS2Exe.SetExeType(FALSE);
181 else OS2Exe.SetExeType(TRUE);
182
183 if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
184 cout << "No fixups, might not run!" << endl;
185 OS2Exe.SetNoFixups();
186 }
187
188 GetPEOptionalHeader (win32file, &oh);
189 cout << "PE Optional header: " << endl;
190#if 0
191 oh.ImageBase = 0x20000000;
192#endif
193 cout << "Preferred address : " << hex(oh.ImageBase) << endl;
194 cout << "Base Of Code : " << hex(oh.BaseOfCode) << endl;
195 cout << "CodeSize : " << hex(oh.SizeOfCode) << endl;
196 cout << "Base Of Data : " << hex(oh.BaseOfData) << endl;
197 cout << "Data Size (uninit): " << hex(oh.SizeOfUninitializedData) << endl;
198 cout << "Data Size (init) : " << hex(oh.SizeOfInitializedData) << endl;
199 cout << "Entry Point : " << hex(oh.AddressOfEntryPoint) << endl;
200 cout << "Section Alignment : " << hex(oh.SectionAlignment) << endl;
201 cout << "Stack Reserve size: " << hex(oh.SizeOfStackReserve) << endl;
202 cout << "Stack Commit size : " << hex(oh.SizeOfStackCommit) << endl;
203 cout << "SizeOfHeapReserve : " << hex(oh.SizeOfHeapReserve) << endl;
204 cout << "SizeOfHeapCommit : " << hex(oh.SizeOfHeapCommit) << endl;
205 cout << "FileAlignment : " << hex(oh.FileAlignment) << endl;
206
207 //SetExeType must have been called before
208 if(oh.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_GUI) {
209 OS2Exe.SetModuleType(SYSTEM_CHARACTER);
210 cout << "Console app" << endl;
211 }
212 else OS2Exe.SetModuleType(SYSTEM_GUI);
213
214 //// OS2Exe.SetStackSize(oh.SizeOfStackCommit);
215 OS2Exe.SetStackSize(max(oh.SizeOfStackCommit, oh.SizeOfStackReserve));
216 if(argc == 2)
217 OS2Exe.SetModuleName(argv[1]);
218 else OS2Exe.SetModuleName(argv[2]);
219
220 nSections = NR_SECTIONS(win32file);
221
222 if ((psh = (PIMAGE_SECTION_HEADER)SECTIONHDROFF (win32file)) != NULL) {
223 cout << endl;
224 for (i=0; i<nSections; i++) {
225 cout << "Section Name: " << psh[i].Name << endl;
226 cout << "Raw data size: " << hex(psh[i].SizeOfRawData) << endl;
227 cout << "Virtual Address: " << hex(psh[i].VirtualAddress) << endl;
228 cout << "Virtual Size: " << hex(psh[i].Misc.VirtualSize) << endl;
229 cout << "Pointer to raw data: " << hex(psh[i].PointerToRawData) << endl;
230 cout << "Section flags: " << hex(psh[i].Characteristics) << endl;
231 if(strcmp(psh[i].Name, ".reloc") == 0) {
232 cout << ".reloc" << endl << endl;
233 continue;
234 }
235 if(strcmp(psh[i].Name, ".edata") == 0) {
236 cout << ".edata" << endl << endl;
237 continue;
238 }
239 if(strcmp(psh[i].Name, ".pdata") == 0) {
240 cout << ".pdata" << endl << endl;
241 continue;
242 }
243 if(strcmp(psh[i].Name, ".rsrc") == 0) {
244 cout << ".rsrc" << endl << endl;
245 continue;
246 }
247 if(strcmp(psh[i].Name, ".debug") == 0) {
248 cout << ".rdebug" << endl << endl;
249 continue;
250 }
251 if(IsImportSection(win32file, &psh[i]))
252 {
253 int type = SECTION_IMPORT;
254 cout << "Import Data Section" << endl << endl;
255 if(psh[i].Characteristics & IMAGE_SCN_CNT_CODE) {
256 cout << "Also Code Section" << endl << endl;
257 OS2Exe.SetEntryAddress(oh.AddressOfEntryPoint-psh[i].VirtualAddress);
258 type |= SECTION_CODE;
259 }
260 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
261 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
262 psh[i].VirtualAddress + oh.ImageBase,
263 type);
264 continue;
265 }
266
267 if ((psh[i].Characteristics & IMAGE_SCN_CNT_CODE)
268 //KSO Sun 1998-08-09: Borland does not alway set the CODE flag for its "CODE" section (TIB fix need to have the first section marked as code)
269 || (psh[i].Characteristics & IMAGE_SCN_MEM_EXECUTE &&
270 !(psh[i].Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA)) //KSO: make sure its not marked as a datasection
271 )
272 ) {
273 cout << "Code Section" << endl << endl;
274 if(oh.AddressOfEntryPoint < psh[i].VirtualAddress)
275 OS2Exe.SetEntryAddress(oh.AddressOfEntryPoint - oh.BaseOfCode);
276 else OS2Exe.SetEntryAddress(oh.AddressOfEntryPoint-psh[i].VirtualAddress);
277 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
278 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
279 psh[i].VirtualAddress + oh.ImageBase,
280 SECTION_CODE);
281 continue;
282 }
283 if(!(psh[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { //read only data section
284 cout << "Read Only Data Section" << endl << endl;
285 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
286 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
287 psh[i].VirtualAddress + oh.ImageBase,
288 SECTION_READONLYDATA);
289 continue;
290 }
291 if(psh[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
292 cout << "Uninitialized Data Section" << endl << endl;
293 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
294 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
295 psh[i].VirtualAddress + oh.ImageBase,
296 SECTION_UNINITDATA);
297 continue;
298 }
299 if(psh[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
300 cout << "Initialized Data Section" << endl << endl;
301 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
302 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
303 psh[i].VirtualAddress + oh.ImageBase,
304 SECTION_INITDATA);
305 continue;
306 }
307 if(psh[i].Characteristics & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ)) {
308 cout << "Other Section, stored as read/write uninit data" << endl << endl;
309 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
310 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
311 psh[i].VirtualAddress + oh.ImageBase,
312 SECTION_UNINITDATA);
313 continue;
314 }
315 }
316 }
317 //SvL: Align and/or concatenate code & data sections
318 OS2Exe.AlignSections();
319
320 prel = (PIMAGE_BASE_RELOCATION) ImageDirectoryOffset (win32file, IMAGE_DIRECTORY_ENTRY_BASERELOC);
321 OS2Exe.SetNrOff32Fixups((prel) ? oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size/2 : 0);
322
323 if(prel) {
324 j = 1;
325 while(prel->VirtualAddress) {
326 page = (char *)((char *)prel + (int)prel->VirtualAddress);
327 count = (prel->SizeOfBlock - 8)/2;
328 cout.setf(ios::hex, ios::basefield);
329 cout << "Page " << j << " Address " << (ULONG)prel->VirtualAddress << " Count " << count << endl;
330 cout.setf(ios::dec, ios::basefield);
331 j++;
332 for(i=0;i<count;i++) {
333 int type = prel->TypeOffset[i] >> 12;
334 int offset = prel->TypeOffset[i] & 0xFFF;
335 switch(type) {
336 case IMAGE_REL_BASED_ABSOLUTE:
337//// cout << "absolute fixup; unused" << endl;
338 break; //skip
339 case IMAGE_REL_BASED_HIGHLOW:
340//// cout << "address " << offset << " type " << type << endl;
341 OS2Exe.AddOff32Fixup(oh.ImageBase +
342 prel->VirtualAddress +
343 offset);
344 break;
345 case IMAGE_REL_BASED_HIGH:
346 case IMAGE_REL_BASED_LOW:
347 case IMAGE_REL_BASED_HIGHADJ:
348 case IMAGE_REL_BASED_MIPS_JMPADDR:
349 default:
350 cout << "Unknown/unsupported fixup type!" << endl;
351 break;
352 }
353 }
354 prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock);
355 }//while
356 }
357 else {
358 cout << "No fixups, might not run!" << endl;
359 OS2Exe.SetNoFixups();
360 }
361
362 /* get section header and pointer to data directory for .edata section */
363 if((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
364 (win32file, IMAGE_DIRECTORY_ENTRY_EXPORT)) != NULL &&
365 (fh.Characteristics & IMAGE_FILE_DLL) &&
366 GetSectionHdrByImageDir(win32file, IMAGE_DIRECTORY_ENTRY_EXPORT, &sh) ) {
367
368 cout << "Exported Functions: " << endl;
369 ptrOrd = (USHORT *)((int)ped->AddressOfNameOrdinals -
370 (int)sh.VirtualAddress +
371 (int)sh.PointerToRawData + (int)win32file);
372 ptrNames = (int *)((int)ped->AddressOfNames -
373 (int)sh.VirtualAddress +
374 (int)sh.PointerToRawData + (int)win32file);
375 ptrAddress = (int *)((int)ped->AddressOfFunctions -
376 (int)sh.VirtualAddress +
377 (int)sh.PointerToRawData + (int)win32file);
378 OS2Exe.SetNrExtFixups(max(ped->NumberOfNames,ped->NumberOfFunctions));
379 int ord, RVAExport;
380 char *name;
381 for(i=0;i<ped->NumberOfNames;i++) {
382 ord = ptrOrd[i] + ped->Base;
383 name = (char *)((int)ptrNames[i] - (int)sh.VirtualAddress +
384 (int)sh.PointerToRawData + (int)win32file);
385 RVAExport = ptrAddress[ptrOrd[i]];
386// RVAExport = ptrAddress[i];
387#ifdef FORWARDERS
388 if(RVAExport < sh.VirtualAddress || RVAExport > sh.VirtualAddress + sh.SizeOfRawData) {
389#endif
390 //points to code (virtual address relative to oh.ImageBase
391 cout << "address 0x";
392 cout.setf(ios::hex, ios::basefield);
393 cout << RVAExport;
394 cout.setf(ios::dec, ios::basefield);
395 cout << " " << name << "@" << ord << endl;
396 OS2Exe.AddNameExport(oh.ImageBase + RVAExport, name, ord);
397#ifdef FORWARDERS
398
399 }
400 else {//forwarder
401 char *forward = (char *)((int)RVAExport -
402 (int)sh.VirtualAddress +
403 (int)sh.PointerToRawData +
404 (int)win32file);
405 cout << RVAExport << " " << name << " @" << ord << " is forwarder to " << (int)forward << endl;
406// OS2Exe.AddForwarder(name, ord, forward);
407 }
408#endif
409 }
410 for(i=0;i<max(ped->NumberOfNames,ped->NumberOfFunctions);i++) {
411 ord = ped->Base + i; //Correct??
412 RVAExport = ptrAddress[i];
413#ifdef FORWARDERS
414 if(RVAExport < sh.VirtualAddress || RVAExport > sh.VirtualAddress + sh.SizeOfRawData) {
415#endif
416 if(RVAExport) {
417 //points to code (virtual address relative to oh.ImageBase
418 cout << "ord " << ord << " at 0x";
419 cout.setf(ios::hex, ios::basefield);
420 cout << RVAExport << endl;
421 cout.setf(ios::dec, ios::basefield);
422 OS2Exe.AddOrdExport(oh.ImageBase + RVAExport, ord);
423 }
424#ifdef FORWARDERS
425 }
426 else {//forwarder or empty
427 char *forward = (char *)((int)RVAExport -
428 (int)sh.VirtualAddress +
429 (int)sh.PointerToRawData +
430 (int)win32file);
431 cout << "ord " << ord << " at 0x";
432 cout.setf(ios::hex, ios::basefield);
433 cout << RVAExport << " is forwarder to 0x" << (int)forward << endl;
434 cout.setf(ios::dec, ios::basefield);
435// OS2Exe.AddForwarder(NULL, ord, forward);
436 }
437#endif
438 }
439 }
440 else {
441 if(fh.Characteristics & IMAGE_FILE_DLL) {
442 OS2Exe.SetNrExtFixups(0); //adds module name to resident table
443 }
444 }
445 //imported stuff
446 if (!ProcessImports(win32file))
447 {
448 cout << "Fatal: failed to process imports" << endl;
449 return -1;
450 }
451
452
453 //resource stuff
454 if(GetSectionHdrByName (win32file, &sh, ".rsrc")) {
455 cout << "Resource section: " << endl;
456 cout << "Raw data size: " << hex(sh.SizeOfRawData) << endl;
457 cout << "Virtual Address: " << hex(sh.VirtualAddress) << endl;
458 cout << "Pointer to raw data: " << hex(sh.PointerToRawData) << endl;
459 cout << "Section flags: " << hex(sh.Characteristics) << endl << endl;
460 /* get root directory of resource tree */
461 if(NULL != (prdRoot = (PIMAGE_RESOURCE_DIRECTORY)ImageDirectoryOffset
462 (win32file, IMAGE_DIRECTORY_ENTRY_RESOURCE))) {
463 cout << "Resources: " << endl;
464 cout << "pdrRoot: " << hex((ULONG)prdRoot - (ULONG)win32file) << endl;
465
466 OS2Exe.SetResourceSize(max(sh.Misc.VirtualSize, sh.SizeOfRawData));
467 OS2Exe.SetNrResources(GetNumberOfResources(win32file));
468
469 /* set pointer to first resource type entry */
470 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
471
472 //SvL: Store all resource ids so we can safely allocate unique ids for name ids
473 for (i=0; i<prdRoot->NumberOfNamedEntries+prdRoot->NumberOfIdEntries; i++) {
474 /* locate directory or each resource type */
475 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (int)prde->u2.OffsetToData);
476
477 if(i<prdRoot->NumberOfNamedEntries) {
478 //SvL: 30-10-'97, high bit is set, so clear to get real offset
479 prde->u1.Name &= ~0x80000000;
480 char *resname = UnicodeToAscii(*(WCHAR *)((int)prdRoot + (int)prde->u1.Name), (WCHAR *)((int)prdRoot + (int)prde->u1.Name + sizeof(WCHAR))); // first word = string length
481
482 for(j=0;j<MAX_RES;j++) {
483 if(strcmp(resname, ResTypes[j]) == 0)
484 break;
485 }
486 if(j == MAX_RES) {
487 id = NTRT_RCDATA;
488 }
489 else id = j;
490 }
491 else {
492 id = prde->u1.Id;
493 }
494
495 if((int)prdType & 0x80000000) {//subdirectory?
496 StoreIdResSubDir(prdType, 1, prdRoot, sh.VirtualAddress, id, 0);
497 }
498 else assert(FALSE);
499
500 /* increment to next entry */
501 prde++;
502 }
503
504 /* set pointer to first resource type entry */
505 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
506
507 /* loop through all resource directory entry types */
508//eerste level -> types
509//tweede level -> names
510//derde level -> language
511 cout << "Name entries: " << endl;
512 cout << "ID entries: " << endl;
513 for (i=0; i<prdRoot->NumberOfNamedEntries+prdRoot->NumberOfIdEntries; i++) {
514 /* locate directory or each resource type */
515 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (int)prde->u2.OffsetToData);
516
517 if(i<prdRoot->NumberOfNamedEntries) {
518 //SvL: 30-10-'97, high bit is set, so clear to get real offset
519 prde->u1.Name &= ~0x80000000;
520 char *resname = UnicodeToAscii(*(WCHAR *)((int)prdRoot + (int)prde->u1.Name), (WCHAR *)((int)prdRoot + (int)prde->u1.Name + sizeof(WCHAR))); // first word = string length
521
522 cout << "Type " << resname << endl;
523 for(j=0;j<MAX_RES;j++) {
524 if(strcmp(resname, ResTypes[j]) == 0)
525 break;
526 }
527 if(j == MAX_RES) {
528 id = NTRT_RCDATA;
529 }
530 else id = j;
531 }
532 else {
533 if(prde->u1.Id < MAX_RES)
534 cout << "Type " << ResTypes[prde->u1.Id] << endl;
535 else cout << "Custom Type " << prde->u1.Id << endl;
536 id = prde->u1.Id;
537 }
538
539 if((int)prdType & 0x80000000) {//subdirectory?
540 ProcessResSubDir(prdType, 1, prdRoot, sh.VirtualAddress, id, 0);
541 }
542 else {
543 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType;
544 cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
545 cout << "Resource Data entry of size " << hex(pData->Size) << endl;
546 cout << "Resource Data RVA " << hex(pData->OffsetToData) << endl;
547 cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
548 assert(FALSE);
549 }
550
551 /* increment to next entry */
552 prde++;
553 }
554 }
555 OS2Icon::DestroyAll();
556 OS2Cursor::DestroyAll();
557 }
558 OS2Exe.SaveConvertedNames();
559 if(argc == 2)
560 OS2Exe.SaveNewExeFile(argv[1]);
561 else OS2Exe.SaveNewExeFile(argv[2]);
562
563 return(0);
564}
565//******************************************************************************
566//No support for multiple languages; just select the first one present and
567//ignore the rest
568//******************************************************************************
569void ProcessResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType, int level,
570 PIMAGE_RESOURCE_DIRECTORY prdRoot, int VirtualAddress,
571 int type, int id)
572{
573 PIMAGE_RESOURCE_DIRECTORY prdType2;
574 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
575 PIMAGE_RESOURCE_DIR_STRING_U pstring;
576 PIMAGE_RESOURCE_DATA_ENTRY pData;
577 int i;
578
579 switch(level) {
580 case 1:
581 cout << "Names.." << endl;
582 break;
583 case 2:
584 cout << "Language.." << endl;
585 break;
586 }
587 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdType & ~0x80000000);
588 cout << "Subdir with " << prdType->NumberOfNamedEntries << " Name entries" << endl;
589 cout << "Subdir with " << prdType->NumberOfIdEntries << " id entries" << endl;
590
591 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
592 for(i=0;i<prdType->NumberOfNamedEntries+prdType->NumberOfIdEntries;i++) {
593 /* locate directory or each resource type */
594 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (int)prde->u2.OffsetToData);
595
596 if(i < prdType->NumberOfNamedEntries) {//name or id entry?
597 if(prde->u1.s.NameIsString) //unicode directory string /*PLF Sat 97-06-21 22:30:35*/
598 prde->u1.Name &= ~0x80000000;
599 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((int)prdRoot + (int)prde->u1.Name);
600 cout << "Name = " << UnicodeToAscii(pstring->Length, pstring->NameString) << endl;
601 if(level == 1) {
602 id = OS2Exe.ConvertNametoId(UnicodeToAscii(pstring->Length, pstring->NameString));
603 }
604 }
605 else {
606 cout << "Id " << prde->u1.Id << endl;
607 if(level == 1) id = prde->u1.Id;
608 }
609
610 if((int)prdType2 & 0x80000000) {//subdirectory?
611 ProcessResSubDir(prdType2, 2, prdRoot, VirtualAddress, type, id);
612 }
613 else {
614 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType2;
615 cout << "Resource Data entry of size " << hex(pData->Size) << endl;
616 cout << "Resource Data RVA " << hex(pData->OffsetToData - VirtualAddress) << endl;
617 cout << "Resource Data RVA " << hex(pData->OffsetToData) << endl;
618 cout << "Resource Data VA " << hex(VirtualAddress) << endl;
619 if(pData->Size) {//winamp17 winzip archive has resource with size 0
620 switch(type) {
621 case NTRT_MENU:
622 ShowMenu(id, (MenuHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
623 break;
624 case NTRT_ICON:
625 new OS2Icon(id, (WINBITMAPINFOHEADER *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
626 break;
627 case NTRT_BITMAP:
628 //KSO [Mon 03.08.1998]: added OS2Exe to the parameterlist
629 ShowBitmap(OS2Exe, id, (WINBITMAPINFOHEADER *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
630 break;
631 case NTRT_GROUP_ICON:
632 ShowGroupIcon(id, (IconHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
633 break;
634 case NTRT_CURSOR:
635 new OS2Cursor(id, (CursorComponent *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
636 break;
637 case NTRT_GROUP_CURSOR:
638 ShowGroupCursor(id, (CursorHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
639 break;
640 case NTRT_DIALOG:
641 ShowDialog(id, (DialogBoxHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
642 break;
643 case NTRT_VERSION:
644//Store version resource as OS/2 RT_RCDATA resource
645//to retrieve the original for win32's version apis
646//TODO: Only supports one version resource (who would want to use more??)
647 OS2Exe.SetVersionResourceId(id);
648 case NTRT_RCDATA:
649 ShowRCData(id, (char *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
650 break;
651 case NTRT_STRING:
652//String format: tables of 16 strings stored as one resource
653//upper 12 bits of resource id passed by user determines block (res id)
654//lower 4 bits are an index into the string table
655//Best solution is to split the strings up and store them as RCDATA
656 ShowStrings(id, (char *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
657 break;
658 case NTRT_ACCELERATORS:
659 ShowAccelerator(id, (WINACCEL *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
660 break;
661 default:
662 cout << "!!Unsupported resource type!! : " << type << endl;
663 //Just save it as rcdata
664 ShowRCData(id, (char *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
665 break;
666 }//switch
667 }//if size > 0
668 }
669 if(level == 2) break; //only support one language!
670
671 prde++;
672 cout << endl;
673 }
674}
675//******************************************************************************
676//******************************************************************************
677void StoreIdResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType, int level,
678 PIMAGE_RESOURCE_DIRECTORY prdRoot, int VirtualAddress,
679 int type, int id)
680{
681 PIMAGE_RESOURCE_DIRECTORY prdType2;
682 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
683 int i, j;
684
685 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdType & ~0x80000000);
686
687 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
688 for(i=0;i<prdType->NumberOfNamedEntries+prdType->NumberOfIdEntries;i++) {
689 /* locate directory or each resource type */
690 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (int)prde->u2.OffsetToData);
691
692 if(i >= prdType->NumberOfNamedEntries) {//name or id entry?
693 if(level == 1) id = prde->u1.Id;
694 }
695 else {
696 prde++;
697 continue; //skip name ids
698 }
699
700 if((int)prdType2 & 0x80000000) {//subdirectory?
701 StoreIdResSubDir(prdType2, 2, prdRoot, VirtualAddress, type, id);
702 }
703 else {
704 if(type == NTRT_STRING) {
705 for(j=0;j<16;j++) {
706 OS2Exe.StoreResourceId((id-1)*16+j);
707 }
708 }
709 else OS2Exe.StoreResourceId(id);
710 }
711 if(level == 2) break; //only support one language!
712
713 prde++;
714 }
715}
716//******************************************************************************
717//******************************************************************************
718
719/** All initial processing of imports is done here
720 * Should now detect most Borland styled files including the GifCon32.exe and
721 * loader32 from SoftIce. (Stupid Borland!!!)
722 *
723 * knut [Jul 22 1998 2:44am]
724 **/
725BOOL ProcessImports(void *pFile)
726{
727 PIMAGE_IMPORT_DESCRIPTOR pID;
728 IMAGE_SECTION_HEADER shID;
729 IMAGE_SECTION_HEADER shExtra = {0};
730 PIMAGE_OPTIONAL_HEADER pOH;
731
732 int i,j;
733 BOOL fBorland = 0;
734 int cModules;
735 char *pszModules;
736 char *pszCurModule;
737 char *pszTmp;
738 ULONG *pulImport;
739 ULONG ulCurFixup;
740 int Size;
741
742 /* "algorithm:"
743 * 1) get module names and store them
744 * a) check dwRVAModuleName is within .idata seg - if not find section
745 * 2) iterate thru functions of each module
746 * a) check OriginalFirstThunk is not 0 and that it points to a RVA.
747 * b) if not a) borland-styled PE-file - ARG!!!
748 * check FirstThunk
749 * c) check OriginalFirstThunk/FirstThunk ok RVAs and find right section
750 * d) store ordinal/name import
751 * 3) finished
752 */
753
754 /* 1) get module names */
755 pID = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryOffset(pFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
756 if (pID == NULL) {
757 OS2Exe.StoreImportModules("KERNEL32.DLL", 1);
758 OS2Exe.SetNoNameImports();
759 return TRUE; //SvL: yes, there are dlls without imports!
760 }
761 if (!GetSectionHdrByImageDir(pFile, IMAGE_DIRECTORY_ENTRY_IMPORT, &shID)) {
762 OS2Exe.StoreImportModules("KERNEL32.DLL", 1);
763 OS2Exe.SetNoNameImports();
764 return TRUE; //SvL: yes, there are dlls without imports!
765 }
766 //calc size of module list
767 i = Size = cModules = 0;
768 while (pID[i].Name != 0)
769 {
770 //test RVA inside ID-Section
771 if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData))
772 pszTmp = (char*)(pID[i].Name- shID.VirtualAddress + shID.PointerToRawData + (ULONG)pFile);
773 else
774 {
775 //is the "Extra"-section already found or do we have to find it?
776 if (pID[i].Name < shExtra.VirtualAddress || pID[i].Name >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
777 if (!GetSectionHdrByRVA(pFile, &shExtra, pID[i].Name))
778 return FALSE;
779 pszTmp = (char*)(pID[i].Name- shExtra.VirtualAddress + shExtra.PointerToRawData + (ULONG)pFile);
780 }
781 Size += strlen(pszTmp) + 1;
782 i++;
783 cModules++;
784 }
785
786 pszModules = (char*)malloc(Size);
787 assert(pszModules != NULL);
788 j = 0;
789 for (i = 0; i < cModules; i++)
790 {
791 //test RVA inside ID-Section
792 if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData))
793 pszTmp = (char*)(pID[i].Name- shID.VirtualAddress + shID.PointerToRawData + (ULONG)pFile);
794 else
795 {
796 fBorland = TRUE;
797 //is the "Extra"-section already found or do we have to find it?
798 if (pID[i].Name < shExtra.VirtualAddress || pID[i].Name >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
799 if (GetSectionHdrByRVA(pFile, &shExtra, pID[i].Name))
800 {
801 free(pszModules);
802 return FALSE;
803 }
804 pszTmp = (char*)(pID[i].Name- shExtra.VirtualAddress + shExtra.PointerToRawData + (ULONG)pFile);
805 }
806 strcpy(pszModules+j, pszTmp);
807 j += strlen(pszTmp) + 1;
808 }
809 cout << endl;
810 if (fBorland)
811 cout << "Borland-styled PE-File." << endl;
812 //Store modules
813 cout << cModules << " imported Modules: " << endl;
814 OS2Exe.StoreImportModules(pszModules, cModules);
815
816
817 /* 2) functions */
818 pszCurModule = pszModules;
819 pOH = (PIMAGE_OPTIONAL_HEADER)OPTHEADEROFF(pFile);
820 for (i = 0; i < cModules; i++)
821 {
822 cout << "Module " << pszCurModule << endl;
823 // a) check that OriginalFirstThunk not is 0 and look for Borland-styled PE
824 if (i == 0)
825 {
826 //heavy borland-style test - assume array of thunks is within that style does not change
827 if ((ULONG)pID[i].u.OriginalFirstThunk == 0
828 ////|| (ULONG)pID[i].u.OriginalFirstThunk < pOH->SizeOfImage
829 || (ULONG)pID[i].u.OriginalFirstThunk < shID.VirtualAddress
830 || (ULONG)pID[i].u.OriginalFirstThunk >= shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData)
831 || (ULONG)pID[i].u.OriginalFirstThunk >= pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
832 && (ULONG)pID[i].u.OriginalFirstThunk < sizeof(*pID)*cModules + pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
833 // && (ULONG)pID[i].u.OriginalFirstThunk < pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size + pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
834 )
835 fBorland = TRUE;
836 }
837
838 //light borland-style test
839 if (pID[i].u.OriginalFirstThunk == 0 || fBorland)
840 pulImport = (ULONG*)pID[i].FirstThunk;
841 else
842 pulImport = (ULONG*)pID[i].u.OriginalFirstThunk;
843
844 // b) check if RVA ok
845 if (!(pulImport > 0 && (ULONG)pulImport < pOH->SizeOfImage))
846 {
847 cout << "Invalid RVA " << hex((ULONG)pulImport) << endl;
848 break;
849 }
850 // check section
851 if ((ULONG)pulImport < shExtra.VirtualAddress || (ULONG)pulImport >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
852 {
853 if (!GetSectionHdrByRVA(pFile, &shExtra, (ULONG)pulImport))
854 {
855 cout << "warning: could not find section for Thunk RVA " << hex((ULONG)pulImport) << endl;
856 break;
857 }
858 }
859
860 pulImport = (PULONG)((ULONG)pulImport - shExtra.VirtualAddress + (ULONG)pFile + shExtra.PointerToRawData);
861 j = 0;
862 ulCurFixup = (ULONG)pID[i].FirstThunk + pOH->ImageBase;
863 while (pulImport[j] != 0)
864 {
865 if (pulImport[j] & IMAGE_ORDINAL_FLAG)
866 { //ordinal
867 cout.setf(ios::hex, ios::basefield);
868 cout << "0x" << ulCurFixup << " Imported function " << pszCurModule << "@" << (pulImport[j] & ~IMAGE_ORDINAL_FLAG) << endl;
869 cout.setf(ios::dec, ios::basefield);
870 OS2Exe.StoreImportByOrd(i, pulImport[j] & ~IMAGE_ORDINAL_FLAG, ulCurFixup);
871 }
872 else
873 { //name
874 //check
875 if (pulImport[j] < shExtra.VirtualAddress || pulImport[j] >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
876 if (!GetSectionHdrByRVA(pFile, &shExtra, pulImport[j]))
877 {
878 cout << "warning: could not find section for Import Name RVA " << hex(pulImport[j]) << endl;
879 break;
880 }
881 //KSO - Aug 6 1998 1:15am:this eases comparing...
882 char *pszFunctionName = (char*)(pulImport[j] + (ULONG)pFile + shExtra.PointerToRawData - shExtra.VirtualAddress + 2);
883 cout.setf(ios::hex, ios::basefield);
884 cout << "0x" << ulCurFixup << " Imported function " << pszFunctionName << endl;
885 cout.setf(ios::dec, ios::basefield);
886 OS2Exe.StoreImportByName(pszCurModule, i, pszFunctionName, ulCurFixup);
887 }
888 ulCurFixup += sizeof(IMAGE_THUNK_DATA);
889 j++;
890 }
891
892 pszCurModule += strlen(pszCurModule) + 1;
893 cout << endl;
894 }//for (i = 0; i < cModules; i++)
895
896 free(pszModules);
897 return TRUE;
898}
899
Note: See TracBrowser for help on using the repository browser.