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

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

* empty log message *

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