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

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

Edgar Buerkle's codepages changes

File size: 41.9 KB
Line 
1/* $Id: pe.cpp,v 1.5 1999-07-06 08:50:11 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 nSections = NR_SECTIONS(win32file);
233
234 if ((psh = (PIMAGE_SECTION_HEADER)SECTIONHDROFF (win32file)) != NULL) {
235 cout << endl;
236 for (i=0; i<nSections; i++) {
237 cout << "Section Name: " << psh[i].Name << endl;
238 cout << "Raw data size: " << hex(psh[i].SizeOfRawData) << endl;
239 cout << "Virtual Address: " << hex(psh[i].VirtualAddress) << endl;
240 cout << "Virtual Size: " << hex(psh[i].Misc.VirtualSize) << endl;
241 cout << "Pointer to raw data: " << hex(psh[i].PointerToRawData) << endl;
242 cout << "Section flags: " << hex(psh[i].Characteristics) << endl;
243 if(strcmp(psh[i].Name, ".reloc") == 0) {
244 cout << ".reloc" << endl << endl;
245 continue;
246 }
247 if(strcmp(psh[i].Name, ".edata") == 0) {
248 cout << ".edata" << endl << endl;
249 continue;
250 }
251 if(strcmp(psh[i].Name, ".pdata") == 0) {
252 cout << ".pdata" << endl << endl;
253 continue;
254 }
255 if(strcmp(psh[i].Name, ".rsrc") == 0) {
256 cout << ".rsrc" << endl << endl;
257 continue;
258 }
259 if(strcmp(psh[i].Name, ".debug") == 0) {
260 cout << ".rdebug" << endl << endl;
261 continue;
262 }
263 if(IsImportSection(win32file, &psh[i]))
264 {
265 int type = SECTION_IMPORT;
266 cout << "Import Data Section" << endl << endl;
267 if(psh[i].Characteristics & IMAGE_SCN_CNT_CODE) {
268 cout << "Also Code Section" << endl << endl;
269 OS2Exe.SetEntryAddress(oh.AddressOfEntryPoint-psh[i].VirtualAddress);
270 type |= SECTION_CODE;
271 }
272 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
273 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
274 psh[i].VirtualAddress + oh.ImageBase,
275 type);
276 continue;
277 }
278
279 if ((psh[i].Characteristics & IMAGE_SCN_CNT_CODE)
280 //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)
281 || (psh[i].Characteristics & IMAGE_SCN_MEM_EXECUTE &&
282 !(psh[i].Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA)) //KSO: make sure its not marked as a datasection
283 )
284 ) {
285 cout << "Code Section" << endl << endl;
286 if(oh.AddressOfEntryPoint < psh[i].VirtualAddress)
287 OS2Exe.SetEntryAddress(oh.AddressOfEntryPoint - oh.BaseOfCode);
288 else OS2Exe.SetEntryAddress(oh.AddressOfEntryPoint-psh[i].VirtualAddress);
289 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
290 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
291 psh[i].VirtualAddress + oh.ImageBase,
292 SECTION_CODE);
293 continue;
294 }
295 if(!(psh[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { //read only data section
296 cout << "Read Only Data Section" << endl << endl;
297 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
298 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
299 psh[i].VirtualAddress + oh.ImageBase,
300 SECTION_READONLYDATA);
301 continue;
302 }
303 if(psh[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
304 cout << "Uninitialized Data Section" << endl << endl;
305 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
306 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
307 psh[i].VirtualAddress + oh.ImageBase,
308 SECTION_UNINITDATA);
309 continue;
310 }
311 if(psh[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
312 cout << "Initialized Data Section" << endl << endl;
313 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
314 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
315 psh[i].VirtualAddress + oh.ImageBase,
316 SECTION_INITDATA);
317 continue;
318 }
319 if(psh[i].Characteristics & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ)) {
320 cout << "Other Section, stored as read/write uninit data" << endl << endl;
321 OS2Exe.StoreSection((char *)win32file+psh[i].PointerToRawData,
322 psh[i].SizeOfRawData, psh[i].Misc.VirtualSize,
323 psh[i].VirtualAddress + oh.ImageBase,
324 SECTION_UNINITDATA);
325 continue;
326 }
327 }
328 }
329 //SvL: Align and/or concatenate code & data sections
330 OS2Exe.AlignSections();
331
332 prel = (PIMAGE_BASE_RELOCATION) ImageDirectoryOffset (win32file, IMAGE_DIRECTORY_ENTRY_BASERELOC);
333 OS2Exe.SetNrOff32Fixups((prel) ? oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size/2 : 0);
334
335 if(prel) {
336 j = 1;
337 while(prel->VirtualAddress) {
338 page = (char *)((char *)prel + (int)prel->VirtualAddress);
339 count = (prel->SizeOfBlock - 8)/2;
340 cout.setf(ios::hex, ios::basefield);
341 cout << "Page " << j << " Address " << (ULONG)prel->VirtualAddress << " Count " << count << endl;
342 cout.setf(ios::dec, ios::basefield);
343 j++;
344 for(i=0;i<count;i++) {
345 int type = prel->TypeOffset[i] >> 12;
346 int offset = prel->TypeOffset[i] & 0xFFF;
347 switch(type) {
348 case IMAGE_REL_BASED_ABSOLUTE:
349//// cout << "absolute fixup; unused" << endl;
350 break; //skip
351 case IMAGE_REL_BASED_HIGHLOW:
352//// cout << "address " << offset << " type " << type << endl;
353 OS2Exe.AddOff32Fixup(oh.ImageBase +
354 prel->VirtualAddress +
355 offset);
356 break;
357 case IMAGE_REL_BASED_HIGH:
358 case IMAGE_REL_BASED_LOW:
359 case IMAGE_REL_BASED_HIGHADJ:
360 case IMAGE_REL_BASED_MIPS_JMPADDR:
361 default:
362 cout << "Unknown/unsupported fixup type!" << endl;
363 break;
364 }
365 }
366 prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock);
367 }//while
368 }
369 else {
370 cout << "No fixups, might not run!" << endl;
371 OS2Exe.SetNoFixups();
372 }
373
374 /* get section header and pointer to data directory for .edata section */
375 if((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
376 (win32file, IMAGE_DIRECTORY_ENTRY_EXPORT)) != NULL &&
377 (fh.Characteristics & IMAGE_FILE_DLL) &&
378 GetSectionHdrByImageDir(win32file, IMAGE_DIRECTORY_ENTRY_EXPORT, &sh) ) {
379
380 cout << "Exported Functions: " << endl;
381 ptrOrd = (USHORT *)((int)ped->AddressOfNameOrdinals -
382 (int)sh.VirtualAddress +
383 (int)sh.PointerToRawData + (int)win32file);
384 ptrNames = (int *)((int)ped->AddressOfNames -
385 (int)sh.VirtualAddress +
386 (int)sh.PointerToRawData + (int)win32file);
387 ptrAddress = (int *)((int)ped->AddressOfFunctions -
388 (int)sh.VirtualAddress +
389 (int)sh.PointerToRawData + (int)win32file);
390 OS2Exe.SetNrExtFixups(max(ped->NumberOfNames,ped->NumberOfFunctions));
391 int ord, RVAExport;
392 char *name;
393 for(i=0;i<ped->NumberOfNames;i++) {
394 ord = ptrOrd[i] + ped->Base;
395 name = (char *)((int)ptrNames[i] - (int)sh.VirtualAddress +
396 (int)sh.PointerToRawData + (int)win32file);
397 RVAExport = ptrAddress[ptrOrd[i]];
398// RVAExport = ptrAddress[i];
399#ifdef FORWARDERS
400 if(RVAExport < sh.VirtualAddress || RVAExport > sh.VirtualAddress + sh.SizeOfRawData) {
401#endif
402 //points to code (virtual address relative to oh.ImageBase
403 cout << "address 0x";
404 cout.setf(ios::hex, ios::basefield);
405 cout << RVAExport;
406 cout.setf(ios::dec, ios::basefield);
407 cout << " " << name << "@" << ord << endl;
408 OS2Exe.AddNameExport(oh.ImageBase + RVAExport, name, ord);
409#ifdef FORWARDERS
410
411 }
412 else {//forwarder
413 char *forward = (char *)((int)RVAExport -
414 (int)sh.VirtualAddress +
415 (int)sh.PointerToRawData +
416 (int)win32file);
417 cout << RVAExport << " " << name << " @" << ord << " is forwarder to " << (int)forward << endl;
418// OS2Exe.AddForwarder(name, ord, forward);
419 }
420#endif
421 }
422 for(i=0;i<max(ped->NumberOfNames,ped->NumberOfFunctions);i++) {
423 ord = ped->Base + i; //Correct??
424 RVAExport = ptrAddress[i];
425#ifdef FORWARDERS
426 if(RVAExport < sh.VirtualAddress || RVAExport > sh.VirtualAddress + sh.SizeOfRawData) {
427#endif
428 if(RVAExport) {
429 //points to code (virtual address relative to oh.ImageBase
430 cout << "ord " << ord << " at 0x";
431 cout.setf(ios::hex, ios::basefield);
432 cout << RVAExport << endl;
433 cout.setf(ios::dec, ios::basefield);
434 OS2Exe.AddOrdExport(oh.ImageBase + RVAExport, ord);
435 }
436#ifdef FORWARDERS
437 }
438 else {//forwarder or empty
439 char *forward = (char *)((int)RVAExport -
440 (int)sh.VirtualAddress +
441 (int)sh.PointerToRawData +
442 (int)win32file);
443 cout << "ord " << ord << " at 0x";
444 cout.setf(ios::hex, ios::basefield);
445 cout << RVAExport << " is forwarder to 0x" << (int)forward << endl;
446 cout.setf(ios::dec, ios::basefield);
447// OS2Exe.AddForwarder(NULL, ord, forward);
448 }
449#endif
450 }
451 }
452 else {
453 if(fh.Characteristics & IMAGE_FILE_DLL) {
454 OS2Exe.SetNrExtFixups(0); //adds module name to resident table
455 }
456 }
457 //imported stuff
458 if (!ProcessImports(win32file))
459 {
460 cout << "Fatal: failed to process imports" << endl;
461 return -1;
462 }
463
464
465 //resource stuff
466 if(GetSectionHdrByName (win32file, &sh, ".rsrc")) {
467 cout << "Resource section: " << endl;
468 cout << "Raw data size: " << hex(sh.SizeOfRawData) << endl;
469 cout << "Virtual Address: " << hex(sh.VirtualAddress) << endl;
470 cout << "Pointer to raw data: " << hex(sh.PointerToRawData) << endl;
471 cout << "Section flags: " << hex(sh.Characteristics) << endl << endl;
472 /* get root directory of resource tree */
473 if(NULL != (prdRoot = (PIMAGE_RESOURCE_DIRECTORY)ImageDirectoryOffset
474 (win32file, IMAGE_DIRECTORY_ENTRY_RESOURCE))) {
475 cout << "Resources: " << endl;
476 cout << "pdrRoot: " << hex((ULONG)prdRoot - (ULONG)win32file) << endl;
477
478 OS2Exe.SetResourceSize(max(sh.Misc.VirtualSize, sh.SizeOfRawData));
479 OS2Exe.SetNrResources(GetNumberOfResources(win32file));
480
481 /* set pointer to first resource type entry */
482 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
483
484 //SvL: Store all resource ids so we can safely allocate unique ids for name ids
485 for (i=0; i<prdRoot->NumberOfNamedEntries+prdRoot->NumberOfIdEntries; i++) {
486 /* locate directory or each resource type */
487 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (int)prde->u2.OffsetToData);
488
489 if(i<prdRoot->NumberOfNamedEntries) {
490 //SvL: 30-10-'97, high bit is set, so clear to get real offset
491 prde->u1.Name &= ~0x80000000;
492 char *resname = UnicodeToAscii(*(WCHAR *)((int)prdRoot + (int)prde->u1.Name), (WCHAR *)((int)prdRoot + (int)prde->u1.Name + sizeof(WCHAR))); // first word = string length
493
494 for(j=0;j<MAX_RES;j++) {
495 if(strcmp(resname, ResTypes[j]) == 0)
496 break;
497 }
498 if(j == MAX_RES) {
499 id = NTRT_RCDATA;
500 }
501 else id = j;
502 }
503 else {
504 id = prde->u1.Id;
505 }
506
507 if((int)prdType & 0x80000000) {//subdirectory?
508 StoreIdResSubDir(prdType, 1, prdRoot, sh.VirtualAddress, id, 0);
509 }
510 else assert(FALSE);
511
512 /* increment to next entry */
513 prde++;
514 }
515
516 /* set pointer to first resource type entry */
517 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
518
519 /* loop through all resource directory entry types */
520//eerste level -> types
521//tweede level -> names
522//derde level -> language
523 cout << "Name entries: " << endl;
524 cout << "ID entries: " << endl;
525 for (i=0; i<prdRoot->NumberOfNamedEntries+prdRoot->NumberOfIdEntries; i++) {
526 /* locate directory or each resource type */
527 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (int)prde->u2.OffsetToData);
528
529 if(i<prdRoot->NumberOfNamedEntries) {
530 //SvL: 30-10-'97, high bit is set, so clear to get real offset
531 prde->u1.Name &= ~0x80000000;
532 char *resname = UnicodeToAscii(*(WCHAR *)((int)prdRoot + (int)prde->u1.Name), (WCHAR *)((int)prdRoot + (int)prde->u1.Name + sizeof(WCHAR))); // first word = string length
533
534 cout << "Type " << resname << endl;
535 for(j=0;j<MAX_RES;j++) {
536 if(strcmp(resname, ResTypes[j]) == 0)
537 break;
538 }
539 if(j == MAX_RES) {
540 id = NTRT_RCDATA;
541 }
542 else id = j;
543 }
544 else {
545 if(prde->u1.Id < MAX_RES)
546 cout << "Type " << ResTypes[prde->u1.Id] << endl;
547 else cout << "Custom Type " << prde->u1.Id << endl;
548 id = prde->u1.Id;
549 }
550
551 if((int)prdType & 0x80000000) {//subdirectory?
552 ProcessResSubDir(prdType, 1, prdRoot, sh.VirtualAddress, id, 0);
553 }
554 else {
555 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType;
556 cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
557 cout << "Resource Data entry of size " << hex(pData->Size) << endl;
558 cout << "Resource Data RVA " << hex(pData->OffsetToData) << endl;
559 cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
560 assert(FALSE);
561 }
562
563 /* increment to next entry */
564 prde++;
565 }
566 }
567 OS2Icon::DestroyAll();
568 OS2Cursor::DestroyAll();
569 }
570 OS2Exe.SaveConvertedNames();
571 if(os2file == NULL)
572 OS2Exe.SaveNewExeFile(winfile);
573 else OS2Exe.SaveNewExeFile(os2file);
574
575 return(0);
576}
577//******************************************************************************
578//No support for multiple languages; just select the first one present and
579//ignore the rest
580//******************************************************************************
581void ProcessResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType, int level,
582 PIMAGE_RESOURCE_DIRECTORY prdRoot, int VirtualAddress,
583 int type, int id)
584{
585 PIMAGE_RESOURCE_DIRECTORY prdType2;
586 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
587 PIMAGE_RESOURCE_DIR_STRING_U pstring;
588 PIMAGE_RESOURCE_DATA_ENTRY pData;
589 int i;
590
591 switch(level) {
592 case 1:
593 cout << "Names.." << endl;
594 break;
595 case 2:
596 cout << "Language.." << endl;
597 break;
598 }
599 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdType & ~0x80000000);
600 cout << "Subdir with " << prdType->NumberOfNamedEntries << " Name entries" << endl;
601 cout << "Subdir with " << prdType->NumberOfIdEntries << " id entries" << endl;
602
603 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
604 for(i=0;i<prdType->NumberOfNamedEntries+prdType->NumberOfIdEntries;i++) {
605 /* locate directory or each resource type */
606 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (int)prde->u2.OffsetToData);
607
608 if(i < prdType->NumberOfNamedEntries) {//name or id entry?
609 if(prde->u1.s.NameIsString) //unicode directory string /*PLF Sat 97-06-21 22:30:35*/
610 prde->u1.Name &= ~0x80000000;
611 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((int)prdRoot + (int)prde->u1.Name);
612 cout << "Name = " << UnicodeToAscii(pstring->Length, pstring->NameString) << endl;
613 if(level == 1) {
614 id = OS2Exe.ConvertNametoId(UnicodeToAscii(pstring->Length, pstring->NameString));
615 }
616 }
617 else {
618 cout << "Id " << prde->u1.Id << endl;
619 if(level == 1) id = prde->u1.Id;
620 }
621
622 if((int)prdType2 & 0x80000000) {//subdirectory?
623 ProcessResSubDir(prdType2, 2, prdRoot, VirtualAddress, type, id);
624 }
625 else {
626 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType2;
627 cout << "Resource Data entry of size " << hex(pData->Size) << endl;
628 cout << "Resource Data RVA " << hex(pData->OffsetToData - VirtualAddress) << endl;
629 cout << "Resource Data RVA " << hex(pData->OffsetToData) << endl;
630 cout << "Resource Data VA " << hex(VirtualAddress) << endl;
631 if(fUseCodePage == TRUE)
632 WinCodePage = pData->CodePage;
633 else WinCodePage = 0;
634
635 if(pData->Size) {//winamp17 winzip archive has resource with size 0
636 switch(type) {
637 case NTRT_MENU:
638 ShowMenu(id, (MenuHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size, WinCodePage);
639 break;
640 case NTRT_ICON:
641 new OS2Icon(id, (WINBITMAPINFOHEADER *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
642 break;
643 case NTRT_BITMAP:
644 //KSO [Mon 03.08.1998]: added OS2Exe to the parameterlist
645 ShowBitmap(OS2Exe, id, (WINBITMAPINFOHEADER *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
646 break;
647 case NTRT_GROUP_ICON:
648 ShowGroupIcon(id, (IconHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
649 break;
650 case NTRT_CURSOR:
651 new OS2Cursor(id, (CursorComponent *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
652 break;
653 case NTRT_GROUP_CURSOR:
654 ShowGroupCursor(id, (CursorHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
655 break;
656 case NTRT_DIALOG:
657 ShowDialog(id, (DialogBoxHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size, WinCodePage);
658 break;
659 case NTRT_VERSION:
660//Store version resource as OS/2 RT_RCDATA resource
661//to retrieve the original for win32's version apis
662//TODO: Only supports one version resource (who would want to use more??)
663 OS2Exe.SetVersionResourceId(id);
664 case NTRT_RCDATA:
665 ShowRCData(id, (char *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
666 break;
667 case NTRT_STRING:
668//String format: tables of 16 strings stored as one resource
669//upper 12 bits of resource id passed by user determines block (res id)
670//lower 4 bits are an index into the string table
671//Best solution is to split the strings up and store them as RCDATA
672 ShowStrings(id, (char *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size, WinCodePage);
673 break;
674 case NTRT_ACCELERATORS:
675 ShowAccelerator(id, (WINACCEL *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
676 break;
677 default:
678 cout << "!!Unsupported resource type!! : " << type << endl;
679 //Just save it as rcdata
680 ShowRCData(id, (char *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
681 break;
682 }//switch
683 }//if size > 0
684 }
685 if(level == 2) break; //only support one language!
686
687 prde++;
688 cout << endl;
689 }
690}
691//******************************************************************************
692//******************************************************************************
693void StoreIdResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType, int level,
694 PIMAGE_RESOURCE_DIRECTORY prdRoot, int VirtualAddress,
695 int type, int id)
696{
697 PIMAGE_RESOURCE_DIRECTORY prdType2;
698 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
699 int i, j;
700
701 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdType & ~0x80000000);
702
703 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
704 for(i=0;i<prdType->NumberOfNamedEntries+prdType->NumberOfIdEntries;i++) {
705 /* locate directory or each resource type */
706 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (int)prde->u2.OffsetToData);
707
708 if(i >= prdType->NumberOfNamedEntries) {//name or id entry?
709 if(level == 1) id = prde->u1.Id;
710 }
711 else {
712 prde++;
713 continue; //skip name ids
714 }
715
716 if((int)prdType2 & 0x80000000) {//subdirectory?
717 StoreIdResSubDir(prdType2, 2, prdRoot, VirtualAddress, type, id);
718 }
719 else {
720 if(type == NTRT_STRING) {
721 for(j=0;j<16;j++) {
722 OS2Exe.StoreResourceId((id-1)*16+j);
723 }
724 }
725 else OS2Exe.StoreResourceId(id);
726 }
727 if(level == 2) break; //only support one language!
728
729 prde++;
730 }
731}
732//******************************************************************************
733//******************************************************************************
734
735/** All initial processing of imports is done here
736 * Should now detect most Borland styled files including the GifCon32.exe and
737 * loader32 from SoftIce. (Stupid Borland!!!)
738 *
739 * knut [Jul 22 1998 2:44am]
740 **/
741BOOL ProcessImports(void *pFile)
742{
743 PIMAGE_IMPORT_DESCRIPTOR pID;
744 IMAGE_SECTION_HEADER shID;
745 IMAGE_SECTION_HEADER shExtra = {0};
746 PIMAGE_OPTIONAL_HEADER pOH;
747
748 int i,j;
749 BOOL fBorland = 0;
750 int cModules;
751 char *pszModules;
752 char *pszCurModule;
753 char *pszTmp;
754 ULONG *pulImport;
755 ULONG ulCurFixup;
756 int Size;
757
758 /* "algorithm:"
759 * 1) get module names and store them
760 * a) check dwRVAModuleName is within .idata seg - if not find section
761 * 2) iterate thru functions of each module
762 * a) check OriginalFirstThunk is not 0 and that it points to a RVA.
763 * b) if not a) borland-styled PE-file - ARG!!!
764 * check FirstThunk
765 * c) check OriginalFirstThunk/FirstThunk ok RVAs and find right section
766 * d) store ordinal/name import
767 * 3) finished
768 */
769
770 /* 1) get module names */
771 pID = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryOffset(pFile, IMAGE_DIRECTORY_ENTRY_IMPORT);
772 if (pID == NULL) {
773 OS2Exe.StoreImportModules("KERNEL32.DLL", 1);
774 OS2Exe.SetNoNameImports();
775 return TRUE; //SvL: yes, there are dlls without imports!
776 }
777 if (!GetSectionHdrByImageDir(pFile, IMAGE_DIRECTORY_ENTRY_IMPORT, &shID)) {
778 OS2Exe.StoreImportModules("KERNEL32.DLL", 1);
779 OS2Exe.SetNoNameImports();
780 return TRUE; //SvL: yes, there are dlls without imports!
781 }
782 //calc size of module list
783 i = Size = cModules = 0;
784 while (pID[i].Name != 0)
785 {
786 //test RVA inside ID-Section
787 if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData))
788 pszTmp = (char*)(pID[i].Name- shID.VirtualAddress + shID.PointerToRawData + (ULONG)pFile);
789 else
790 {
791 //is the "Extra"-section already found or do we have to find it?
792 if (pID[i].Name < shExtra.VirtualAddress || pID[i].Name >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
793 if (!GetSectionHdrByRVA(pFile, &shExtra, pID[i].Name))
794 return FALSE;
795 pszTmp = (char*)(pID[i].Name- shExtra.VirtualAddress + shExtra.PointerToRawData + (ULONG)pFile);
796 }
797 Size += strlen(pszTmp) + 1;
798 i++;
799 cModules++;
800 }
801
802 pszModules = (char*)malloc(Size);
803 assert(pszModules != NULL);
804 j = 0;
805 for (i = 0; i < cModules; i++)
806 {
807 //test RVA inside ID-Section
808 if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData))
809 pszTmp = (char*)(pID[i].Name- shID.VirtualAddress + shID.PointerToRawData + (ULONG)pFile);
810 else
811 {
812 fBorland = TRUE;
813 //is the "Extra"-section already found or do we have to find it?
814 if (pID[i].Name < shExtra.VirtualAddress || pID[i].Name >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
815 if (GetSectionHdrByRVA(pFile, &shExtra, pID[i].Name))
816 {
817 free(pszModules);
818 return FALSE;
819 }
820 pszTmp = (char*)(pID[i].Name- shExtra.VirtualAddress + shExtra.PointerToRawData + (ULONG)pFile);
821 }
822 strcpy(pszModules+j, pszTmp);
823 j += strlen(pszTmp) + 1;
824 }
825 cout << endl;
826 if (fBorland)
827 cout << "Borland-styled PE-File." << endl;
828 //Store modules
829 cout << cModules << " imported Modules: " << endl;
830 OS2Exe.StoreImportModules(pszModules, cModules);
831
832
833 /* 2) functions */
834 pszCurModule = pszModules;
835 pOH = (PIMAGE_OPTIONAL_HEADER)OPTHEADEROFF(pFile);
836 for (i = 0; i < cModules; i++)
837 {
838 cout << "Module " << pszCurModule << endl;
839 // a) check that OriginalFirstThunk not is 0 and look for Borland-styled PE
840 if (i == 0)
841 {
842 //heavy borland-style test - assume array of thunks is within that style does not change
843 if ((ULONG)pID[i].u.OriginalFirstThunk == 0
844 ////|| (ULONG)pID[i].u.OriginalFirstThunk < pOH->SizeOfImage
845 || (ULONG)pID[i].u.OriginalFirstThunk < shID.VirtualAddress
846 || (ULONG)pID[i].u.OriginalFirstThunk >= shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData)
847 || (ULONG)pID[i].u.OriginalFirstThunk >= pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
848 && (ULONG)pID[i].u.OriginalFirstThunk < sizeof(*pID)*cModules + pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
849 // && (ULONG)pID[i].u.OriginalFirstThunk < pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size + pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
850 )
851 fBorland = TRUE;
852 }
853
854 //light borland-style test
855 if (pID[i].u.OriginalFirstThunk == 0 || fBorland)
856 pulImport = (ULONG*)pID[i].FirstThunk;
857 else
858 pulImport = (ULONG*)pID[i].u.OriginalFirstThunk;
859
860 // b) check if RVA ok
861 if (!(pulImport > 0 && (ULONG)pulImport < pOH->SizeOfImage))
862 {
863 cout << "Invalid RVA " << hex((ULONG)pulImport) << endl;
864 break;
865 }
866 // check section
867 if ((ULONG)pulImport < shExtra.VirtualAddress || (ULONG)pulImport >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
868 {
869 if (!GetSectionHdrByRVA(pFile, &shExtra, (ULONG)pulImport))
870 {
871 cout << "warning: could not find section for Thunk RVA " << hex((ULONG)pulImport) << endl;
872 break;
873 }
874 }
875
876 pulImport = (PULONG)((ULONG)pulImport - shExtra.VirtualAddress + (ULONG)pFile + shExtra.PointerToRawData);
877 j = 0;
878 ulCurFixup = (ULONG)pID[i].FirstThunk + pOH->ImageBase;
879 while (pulImport[j] != 0)
880 {
881 if (pulImport[j] & IMAGE_ORDINAL_FLAG)
882 { //ordinal
883 cout.setf(ios::hex, ios::basefield);
884 cout << "0x" << ulCurFixup << " Imported function " << pszCurModule << "@" << (pulImport[j] & ~IMAGE_ORDINAL_FLAG) << endl;
885 cout.setf(ios::dec, ios::basefield);
886 OS2Exe.StoreImportByOrd(i, pulImport[j] & ~IMAGE_ORDINAL_FLAG, ulCurFixup);
887 }
888 else
889 { //name
890 //check
891 if (pulImport[j] < shExtra.VirtualAddress || pulImport[j] >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
892 if (!GetSectionHdrByRVA(pFile, &shExtra, pulImport[j]))
893 {
894 cout << "warning: could not find section for Import Name RVA " << hex(pulImport[j]) << endl;
895 break;
896 }
897 //KSO - Aug 6 1998 1:15am:this eases comparing...
898 char *pszFunctionName = (char*)(pulImport[j] + (ULONG)pFile + shExtra.PointerToRawData - shExtra.VirtualAddress + 2);
899 cout.setf(ios::hex, ios::basefield);
900 cout << "0x" << ulCurFixup << " Imported function " << pszFunctionName << endl;
901 cout.setf(ios::dec, ios::basefield);
902 OS2Exe.StoreImportByName(pszCurModule, i, pszFunctionName, ulCurFixup);
903 }
904 ulCurFixup += sizeof(IMAGE_THUNK_DATA);
905 j++;
906 }
907
908 pszCurModule += strlen(pszCurModule) + 1;
909 cout << endl;
910 }//for (i = 0; i < cModules; i++)
911
912 free(pszModules);
913 return TRUE;
914}
915
Note: See TracBrowser for help on using the repository browser.