source: trunk/src/win32k/pe2lx/pe.cpp@ 847

Last change on this file since 847 was 847, checked in by bird, 26 years ago

Initial checkin of Win32k. (not tested & pe2lx not up-to-date!)

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