source: trunk/src/pe2lx/pe.cpp

Last change on this file was 363, checked in by sandervl, 26 years ago

* empty log message *

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