source: trunk/src/kernel32/winimage.cpp@ 651

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

Dll load order bugfix

File size: 48.6 KB
Line 
1/* $Id: winimage.cpp,v 1.15 1999-08-23 17:02:35 sandervl Exp $ */
2
3/*
4 * Win32 PE Image class
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998 Knut St. Osmundsen
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13#define INCL_DOSFILEMGR /* File Manager values */
14#define INCL_DOSMODULEMGR
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#include <os2wrap.h> //Odin32 OS/2 api wrappers
21
22#include <stdio.h>
23#include <string.h>
24#include <stdlib.h>
25
26#include <assert.h>
27#include "misc.h"
28#include "nameid.h"
29#include "win32type.h"
30#include "winimage.h"
31#include "windll.h"
32#include "winexe.h"
33#include "pefile.h"
34#include "unicode.h"
35#include "winres.h"
36#include "os2util.h"
37#include "initterm.h"
38
39char szErrorTitle[] = "Win32 for OS/2";
40char szMemErrorMsg[] = "Memory allocation failure";
41char szFileErrorMsg[] = "File IO error";
42char szPEErrorMsg[] = "Not a valid win32 exe. (perhaps 16 bits windows)";
43char szCPUErrorMsg[] = "Executable doesn't run on x86 machines";
44char szExeErrorMsg[] = "File isn't an executable";
45char szInteralErrorMsg[]= "Internal Error";
46
47#ifndef max
48#define max(a, b) ((a>b) ? a : b)
49#endif
50
51BOOL foutInit = FALSE;
52ofstream fout;
53
54ULONG MissingApi();
55char *hex(ULONG num);
56
57extern ULONG flAllocMem; /*Tue 03.03.1998: knut */
58
59//******************************************************************************
60//******************************************************************************
61Win32Image::Win32Image(char *szFileName) :
62 errorState(NO_ERROR), entryPoint(0), nrsections(0), imageSize(0),
63 imageVirtBase(-1), realBaseAddress(0), imageVirtEnd(0),
64 nrNameExports(0), nrOrdExports(0), nameexports(NULL), ordexports(NULL),
65 NameTable(NULL), Win32Table(NULL), fullpath(NULL),
66 tlsAddress(0), tlsIndexAddr(0), tlsInitSize(0), tlsTotalSize(0), tlsCallBackAddr(0), tlsIndex(-1),
67 pResSection(NULL), pResDir(NULL), winres(NULL), VersionId(-1)
68{
69 //native win32 exe/dll, converted dll or native OS/2 dll
70 //if it's either of the latter two, this flag will be reset when
71 //RegisterDll is called
72 fNativePEImage = TRUE;
73
74 strcpy(this->szFileName, szFileName);
75
76 strcpy(szModule, StripPath(szFileName));
77 strupr(szModule);
78 char *dot = strstr(szModule, ".");
79 while(dot) {
80 char *newdot = strstr(dot+1, ".");
81 if(newdot == NULL) break;
82 dot = newdot;
83 }
84 if(dot)
85 *dot = 0;
86
87 if(foutInit == FALSE) {
88 char logname[32];
89 sprintf(logname, "pe_%d.log", loadNr);
90 fout.open(logname, ios::out | ios::trunc);
91 dprintf(("PE LOGFILE for %s: %s", szModule, logname));
92 foutInit = TRUE;
93 }
94
95#ifdef DEBUG
96 magic = MAGIC_WINIMAGE;
97#endif
98}
99//******************************************************************************
100//******************************************************************************
101Win32Image::Win32Image(HINSTANCE hinstance, int NameTableId, int Win32TableId) :
102 errorState(NO_ERROR), entryPoint(0), nrsections(0), imageSize(0),
103 imageVirtBase(-1), realBaseAddress(0), imageVirtEnd(0),
104 nrNameExports(0), nrOrdExports(0), nameexports(NULL), ordexports(NULL),
105 NameTable(NULL), Win32Table(NULL), fullpath(NULL),
106 tlsAddress(0), tlsIndexAddr(0), tlsInitSize(0), tlsTotalSize(0), tlsCallBackAddr(0), tlsIndex(-1),
107 pResSection(NULL), pResDir(NULL), winres(NULL)
108{
109#ifdef DEBUG
110 magic = MAGIC_WINIMAGE;
111#endif
112 OS2ImageInit(hinstance, NameTableId, Win32TableId);
113
114 szFileName[0] = 0;
115
116 char *name = OS2GetDllName(hinstance);
117 strcpy(szModule, name);
118 strupr(szModule);
119 char *dot = strstr(szModule, ".");
120 while(dot) {
121 char *newdot = strstr(dot+1, ".");
122 if(newdot == NULL) break;
123 dot = newdot;
124 }
125 if(dot)
126 *dot = 0;
127}
128//******************************************************************************
129//******************************************************************************
130void Win32Image::OS2ImageInit(HINSTANCE hinstance, int NameTableId, int Win32TableId)
131{
132 APIRET rc;
133
134 this->hinstance = hinstance;
135 this->NameTableId = NameTableId;
136 this->Win32TableId = Win32TableId;
137
138 //converted win32 exe/dll or OS/2 system dll
139 fNativePEImage = FALSE;
140
141 if(NameTableId != NO_NAMETABLE) {
142 //Load name table resource
143 rc = DosGetResource(hinstance, RT_RCDATA, NameTableId, (PPVOID)&NameTable);
144 if(rc) {
145 eprintf(("Can't find converted name resource (rc %d)!!\n", rc));
146 return;
147 }
148 }
149 else this->NameTableId = 0;
150
151 //Load win32 id table resource
152 if((Win32TableId & 0xFFFFFF) != NO_LOOKUPTABLE) {
153 rc = DosGetResource(hinstance, RT_RCDATA, Win32TableId, (PPVOID)&Win32Table);
154 if(rc) {
155 eprintf(("Can't find win32 id resource (rc %d)!!\n", rc));
156 return;
157 }
158 }
159 else this->Win32TableId = 0;
160}
161//******************************************************************************
162//******************************************************************************
163Win32Image::~Win32Image()
164{
165 Win32Resource *res;
166
167 if(NameTable)
168 DosFreeResource((PVOID)NameTable);
169
170 if(Win32Table)
171 DosFreeResource((PVOID)Win32Table);
172
173 while(winres)
174 {
175 res = winres->next;
176 delete(winres);
177 winres = res;
178 }
179 if(realBaseAddress)
180 DosFreeMem((PVOID)realBaseAddress);
181
182 if(nameexports)
183 free(nameexports);
184
185 if(ordexports)
186 free(ordexports);
187 if(fullpath)
188 free(fullpath);
189}
190//******************************************************************************
191//******************************************************************************
192BOOL Win32Image::init(ULONG reservedMem)
193{
194 HFILE win32handle;
195 ULONG ulAction = 0; /* Action taken by DosOpen */
196 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
197 APIRET rc = NO_ERROR; /* Return code */
198 char szErrorMsg[64];
199 LPVOID win32file = NULL;
200 ULONG filesize, ulRead;
201 PIMAGE_SECTION_HEADER psh;
202 IMAGE_TLS_DIRECTORY *tlsDir = NULL;
203 int nSections, i;
204
205 rc = DosOpen(szFileName, /* File path name */
206 &win32handle, /* File handle */
207 &ulAction, /* Action taken */
208 0L, /* File primary allocation */
209 0L, /* File attribute */
210 OPEN_ACTION_FAIL_IF_NEW |
211 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
212 OPEN_FLAGS_NOINHERIT |
213 OPEN_SHARE_DENYNONE |
214 OPEN_ACCESS_READONLY, /* Open mode of the file */
215 0L); /* No extended attribute */
216
217 if (rc != NO_ERROR) {
218 sprintf(szErrorMsg, "Unable to open %32s\n", szFileName);
219 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
220 errorState = ERROR_INTERNAL;
221 return(FALSE);
222 }
223
224 /* Move the file pointer back to the beginning of the file */
225 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
226 DosSetFilePtr(win32handle, 0L, FILE_END, &filesize);
227 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
228
229 win32file = malloc(filesize);
230 if(win32file == NULL) {
231 fout << "Error allocating memory" << endl;
232 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szMemErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
233 DosClose(win32handle); /* Close the file */
234 errorState = ERROR_INTERNAL;
235 return(FALSE);
236 }
237 rc = DosRead(win32handle, win32file, filesize, &ulRead);
238 if(rc != NO_ERROR) {
239 fout << "DosRead returned " << rc << endl;
240 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szFileErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
241 DosClose(win32handle); /* Close the file */
242 errorState = ERROR_INTERNAL;
243 return(FALSE);
244 }
245
246 if(GetPEFileHeader (win32file, &fh) == FALSE) {
247 fout << "Not a valid PE file (probably a 16 bits windows exe/dll)!" << endl;
248 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szPEErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
249 DosClose(win32handle); /* Close the file */
250 errorState = ERROR_INTERNAL;
251 return(FALSE);
252 }
253
254 if(!(fh.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {//not valid
255 fout << "Not a valid PE file!" << endl;
256 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szPEErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
257 DosClose(win32handle); /* Close the file */
258 errorState = ERROR_INTERNAL;
259 return(FALSE);
260 }
261 if(fh.Machine != IMAGE_FILE_MACHINE_I386) {
262 fout << "You need a REAL CPU to run this code" << endl;
263 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szCPUErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
264 DosClose(win32handle); /* Close the file */
265 errorState = ERROR_INTERNAL;
266 return(FALSE);
267 }
268 //IMAGE_FILE_SYSTEM == only drivers (device/file system/video etc)?
269 if(fh.Characteristics & IMAGE_FILE_SYSTEM) {
270 fout << "Can't convert system files" << endl;
271 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szExeErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
272 DosClose(win32handle); /* Close the file */
273 errorState = ERROR_INTERNAL;
274 return(FALSE);
275 }
276
277 if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
278 fout << "No fixups, might not run!" << endl;
279 }
280
281 GetPEOptionalHeader (win32file, &oh);
282 fout << "PE file : " << szFileName << endl;
283 fout << "PE Optional header: " << endl;
284 fout << "Preferred address : " << oh.ImageBase << endl;
285 fout << "Base Of Code : " << oh.BaseOfCode << endl;
286 fout << "CodeSize : " << oh.SizeOfCode << endl;
287 fout << "Base Of Data : " << oh.BaseOfData << endl;
288 fout << "Data Size (uninit): " << oh.SizeOfUninitializedData << endl;
289 fout << "Data Size (init) : " << oh.SizeOfInitializedData << endl;
290 fout << "Entry Point : " << oh.AddressOfEntryPoint << endl;
291 fout << "Section Alignment : " << oh.SectionAlignment << endl;
292 fout << "Stack Reserve size: " << oh.SizeOfStackReserve << endl;
293 fout << "Stack Commit size : " << oh.SizeOfStackCommit << endl;
294 fout << "SizeOfHeapReserve : " << oh.SizeOfHeapReserve << endl;
295 fout << "SizeOfHeapCommit : " << oh.SizeOfHeapCommit << endl;
296 fout << "FileAlignment : " << oh.FileAlignment << endl;
297
298 nSections = NR_SECTIONS(win32file);
299
300 if ((psh = (PIMAGE_SECTION_HEADER)SECTIONHDROFF (win32file)) != NULL) {
301 fout << endl << "*************************PE SECTIONS START**************************" << endl;
302 for (i=0; i<nSections; i++) {
303 fout << "Raw data size: " << hex(psh[i].SizeOfRawData) << endl;
304 fout << "Virtual Address: " << hex(psh[i].VirtualAddress) << endl;
305 fout << "Virtual Size: " << hex(psh[i].Misc.VirtualSize) << endl;
306 fout << "Pointer to raw data: " << hex(psh[i].PointerToRawData) << endl;
307 fout << "Section flags: " << hex(psh[i].Characteristics) << endl << endl;
308 if(strcmp(psh[i].Name, ".reloc") == 0) {
309 fout << ".reloc" << endl << endl;
310 addSection(SECTION_RELOC, (char *)win32file+psh[i].PointerToRawData,
311 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
312 psh[i].Misc.VirtualSize);
313 continue;
314 }
315 if(strcmp(psh[i].Name, ".edata") == 0) {
316 fout << ".edata" << endl << endl;
317 addSection(SECTION_EXPORT, (char *)win32file+psh[i].PointerToRawData,
318 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
319 psh[i].Misc.VirtualSize);
320 continue;
321 }
322 if(strcmp(psh[i].Name, ".rsrc") == 0) {
323 fout << ".rsrc" << endl << endl;
324 addSection(SECTION_RESOURCE, (char *)win32file+psh[i].PointerToRawData,
325 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
326 psh[i].Misc.VirtualSize);
327 continue;
328 }
329 if(strcmp(psh[i].Name, ".tls") == 0)
330 {
331 tlsDir = (IMAGE_TLS_DIRECTORY *)ImageDirectoryOffset(win32file, IMAGE_DIRECTORY_ENTRY_TLS);
332 if(tlsDir) {
333 fout << "TLS Directory" << endl;
334 fout << "TLS Address of Index " << hex((ULONG)tlsDir->AddressOfIndex) << endl;
335 fout << "TLS Address of Callbacks " << hex((ULONG)tlsDir->AddressOfCallBacks) << endl;
336 fout << "TLS SizeOfZeroFill " << hex(tlsDir->SizeOfZeroFill) << endl;
337 fout << "TLS Characteristics " << hex(tlsDir->Characteristics) << endl;
338 addSection(SECTION_TLS, (char *)win32file+psh[i].PointerToRawData,
339 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
340 psh[i].Misc.VirtualSize);
341 }
342 continue;
343 }
344
345 if(strcmp(psh[i].Name, ".debug") == 0) {
346 fout << ".rdebug" << endl << endl;
347 addSection(SECTION_DEBUG, (char *)win32file+psh[i].PointerToRawData,
348 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
349 psh[i].Misc.VirtualSize);
350 continue;
351 }
352 if(IsImportSection(win32file, &psh[i]))
353 {
354 int type = SECTION_IMPORT;
355 fout << "Import Data Section" << endl << endl;
356 if(psh[i].Characteristics & IMAGE_SCN_CNT_CODE) {
357 fout << "Also Code Section" << endl << endl;
358 type |= SECTION_CODE;
359 }
360 addSection(type, (char *)win32file+psh[i].PointerToRawData,
361 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
362 psh[i].Misc.VirtualSize);
363 continue;
364 }
365
366 //KSO Sun 1998-08-09: Borland does not alway set the CODE flag for its "CODE" section
367 if( psh[i].Characteristics & IMAGE_SCN_CNT_CODE ||
368 (psh[i].Characteristics & IMAGE_SCN_MEM_EXECUTE &&
369 !(psh[i].Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA))) //KSO: make sure its not marked as a datasection
370 )
371 {
372 fout << "Code Section" << endl << endl;
373 addSection(SECTION_CODE, (char *)win32file+psh[i].PointerToRawData,
374 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
375 psh[i].Misc.VirtualSize);
376 continue;
377 }
378 if(!(psh[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { //read only data section
379 fout << "Read Only Data Section" << endl << endl;
380 addSection(SECTION_READONLYDATA, (char *)win32file+psh[i].PointerToRawData,
381 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
382 psh[i].Misc.VirtualSize);
383 continue;
384 }
385 if(psh[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
386 fout << "Uninitialized Data Section" << endl << endl;
387 addSection(SECTION_UNINITDATA, (char *)win32file+psh[i].PointerToRawData,
388 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
389 psh[i].Misc.VirtualSize);
390 continue;
391 }
392 if(psh[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
393 fout << "Initialized Data Section" << endl << endl;
394 addSection(SECTION_INITDATA, (char *)win32file+psh[i].PointerToRawData,
395 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
396 psh[i].Misc.VirtualSize);
397 continue;
398 }
399 if(psh[i].Characteristics & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ)) {
400 fout << "Other Section, stored as read/write uninit data" << endl << endl;
401 addSection(SECTION_UNINITDATA, (char *)win32file+psh[i].PointerToRawData,
402 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
403 psh[i].Misc.VirtualSize);
404 continue;
405 }
406 fout << "Unknown section" << endl;
407 errorState = ERROR_INTERNAL;
408 return(FALSE);
409 }
410 }
411 fout << "*************************PE SECTIONS END **************************" << endl;
412 imageSize += imageVirtBase - oh.ImageBase;
413 fout << "Total size of Image " << imageSize << endl;
414 fout << "imageVirtBase " << imageVirtBase << endl;
415 fout << "imageVirtEnd " << imageVirtEnd << endl;
416
417 //In case there are any gaps between sections, adjust size
418 if(imageSize != imageVirtEnd - oh.ImageBase) {
419 fout << "imageSize != imageVirtEnd - oh.ImageBase!" << endl;
420 imageSize = imageVirtEnd - oh.ImageBase;
421 }
422 if(allocSections(reservedMem) == FALSE) {
423 fout << "Failed to allocate image memory, rc " << errorState << endl;
424 return(FALSE);
425 }
426 fout << "OS/2 base address " << realBaseAddress << endl;
427 if(storeSections((char *)win32file) == FALSE) {
428 fout << "Failed to store sections, rc " << errorState << endl;
429 return(FALSE);
430 }
431 if(oh.AddressOfEntryPoint) {
432 entryPoint = realBaseAddress + oh.AddressOfEntryPoint;
433 }
434 else {
435 fout << "EntryPoint == NULL" << endl;
436 entryPoint = NULL;
437 }
438
439 if(tlsDir != NULL) {
440 Section *sect = findSection(SECTION_TLS);
441
442 if(sect == NULL) {
443 fout << "Couldn't find TLS section!!" << endl;
444 return(FALSE);
445 }
446 setTLSAddress((char *)(sect->realvirtaddr + (tlsDir->StartAddressOfRawData - sect->virtaddr)));
447 setTLSInitSize(tlsDir->EndAddressOfRawData - tlsDir->StartAddressOfRawData);
448 setTLSTotalSize(tlsDir->EndAddressOfRawData - tlsDir->StartAddressOfRawData + tlsDir->SizeOfZeroFill);
449
450 sect = findSectionByAddr((ULONG)tlsDir->AddressOfIndex);
451 if(sect == NULL) {
452 fout << "Couldn't find TLS AddressOfIndex section!!" << endl;
453 return(FALSE);
454 }
455 setTLSIndexAddr((LPDWORD)(sect->realvirtaddr + ((ULONG)tlsDir->AddressOfIndex - sect->virtaddr)));
456
457 sect = findSectionByAddr((ULONG)tlsDir->AddressOfCallBacks);
458 if(sect == NULL) {
459 fout << "Couldn't find TLS AddressOfCallBacks section!!" << endl;
460 return(FALSE);
461 }
462 setTLSCallBackAddr((PIMAGE_TLS_CALLBACK *)(sect->realvirtaddr + ((ULONG)tlsDir->AddressOfCallBacks - sect->virtaddr)));
463 }
464
465 if(realBaseAddress != oh.ImageBase) {
466 if(setFixups((PIMAGE_BASE_RELOCATION)ImageDirectoryOffset(win32file, IMAGE_DIRECTORY_ENTRY_BASERELOC)) == FALSE) {
467 fout << "Failed to set fixups" << endl;
468 return(FALSE);
469 }
470 }
471
472 if(processImports((char *)win32file) == FALSE) {
473 fout << "Failed to process imports!" << endl;
474 return(FALSE);
475 }
476
477 if(fh.Characteristics & IMAGE_FILE_DLL) {
478 if(processExports((char *)win32file) == FALSE) {
479 fout << "Failed to process exported apis" << endl;
480 return(FALSE);
481 }
482 }
483 IMAGE_SECTION_HEADER sh;
484 if(GetSectionHdrByName (win32file, &sh, ".rsrc")) {
485 //get offset in resource object of directory entry
486// pResDir = (PIMAGE_RESOURCE_DIRECTORY)ImageDirectoryOffset(win32file, IMAGE_DIRECTORY_ENTRY_RESOURCE);
487 pResDir = (PIMAGE_RESOURCE_DIRECTORY)(sh.VirtualAddress + realBaseAddress);
488 }
489
490 //SvL: Use pointer to image header as module handle now. Some apps needs this
491 hinstance = (HINSTANCE)realBaseAddress;
492
493 //set final memory protection flags (storeSections sets them to read/write)
494 if(setMemFlags() == FALSE) {
495 fout << "Failed to set memory protection" << endl;
496 return(FALSE);
497 }
498
499 //Now it's safe to free win32file
500 free(win32file);
501 DosClose(win32handle); /* Close the file */
502 return(TRUE);
503}
504//******************************************************************************
505//******************************************************************************
506void Win32Image::addSection(ULONG type, char *rawdata, ULONG rawsize, ULONG virtaddress, ULONG virtsize)
507{
508 virtsize = max(rawsize, virtsize);
509
510 section[nrsections].type = type;
511 section[nrsections].rawdata = rawdata;
512 section[nrsections].rawsize = rawsize;
513 section[nrsections].virtaddr = virtaddress;
514
515 if(type == SECTION_RESOURCE) {
516 pResSection = &section[nrsections];
517 }
518 virtsize = ((virtsize - 1) & ~0xFFF) + PAGE_SIZE;
519 imageSize += virtsize;
520 section[nrsections].virtualsize = virtsize;
521
522 if(virtaddress < imageVirtBase)
523 imageVirtBase = virtaddress;
524 if(virtaddress + virtsize > imageVirtEnd)
525 imageVirtEnd = virtaddress + virtsize;
526
527 nrsections++;
528}
529//******************************************************************************
530//******************************************************************************
531BOOL Win32Image::allocSections(ULONG reservedMem)
532{
533 APIRET rc;
534 ULONG baseAddress;
535
536 if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
537 fout << "No fixups, might not run!" << endl;
538 return allocFixedMem(reservedMem);
539 }
540 rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | flAllocMem);
541 if(rc) {
542 errorState = rc;
543 return(FALSE);
544 }
545 realBaseAddress = baseAddress;
546 return(TRUE);
547}
548//******************************************************************************
549//******************************************************************************
550Section *Win32Image::findSection(ULONG type)
551{
552 for(int i=0;i<nrsections;i++) {
553 if(section[i].type == type) {
554 return &section[i];
555 }
556 }
557 return NULL;
558}
559//******************************************************************************
560//******************************************************************************
561Section *Win32Image::findSectionByAddr(ULONG addr)
562{
563 for(int i=0;i<nrsections;i++) {
564 if(section[i].virtaddr <= addr && section[i].virtaddr + section[i].virtualsize > addr) {
565 return &section[i];
566 }
567 }
568 return NULL;
569}
570//******************************************************************************
571#define FALLOC_SIZE (1024*1024)
572//NOTE: Needs testing (while loop)
573//TODO: Free unused (parts of) reservedMem
574//******************************************************************************
575BOOL Win32Image::allocFixedMem(ULONG reservedMem)
576{
577 ULONG address = 0;
578 ULONG *memallocs;
579 ULONG alloccnt = 0;
580 ULONG diff, i, baseAddress;
581 APIRET rc;
582
583 realBaseAddress = 0;
584
585 if(reservedMem && reservedMem <= oh.ImageBase &&
586 ((oh.ImageBase - reservedMem) + imageSize < PELDR_RESERVEDMEMSIZE))
587 {
588 //ok, it fits perfectly
589 realBaseAddress = oh.ImageBase;
590 return TRUE;
591 }
592
593 //Reserve enough space to store 4096 pointers to 1MB memory chunks
594 memallocs = (ULONG *)malloc(4096*sizeof(ULONG *));
595 if(memallocs == NULL) {
596 fout << "allocFixedMem: MALLOC FAILED for memallocs" << endl;
597 return FALSE;
598 }
599
600 while(TRUE) {
601 rc = DosAllocMem((PPVOID)&address, FALLOC_SIZE, PAG_READ | flAllocMem);
602 if(rc) break;
603
604 fout << "DosAllocMem returned " << address << endl;
605 if(address + FALLOC_SIZE >= oh.ImageBase) {
606 if(address > oh.ImageBase) {//we've passed it!
607 DosFreeMem((PVOID)address);
608 break;
609 }
610 //found the right address
611 DosFreeMem((PVOID)address);
612
613 diff = oh.ImageBase - address;
614 if(diff) {
615 rc = DosAllocMem((PPVOID)&address, diff, PAG_READ | flAllocMem);
616 if(rc) break;
617 }
618 rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | flAllocMem);
619 if(rc) break;
620
621 if(diff) DosFreeMem((PVOID)address);
622
623 realBaseAddress = baseAddress;
624 break;
625 }
626 memallocs[alloccnt++] = address;
627 }
628 for(i=0;i<alloccnt;i++) {
629 DosFreeMem((PVOID)memallocs[i]);
630 }
631 free(memallocs);
632
633 if(realBaseAddress == 0) //Let me guess.. MS Office app?
634 return(FALSE);
635
636 return(TRUE);
637}
638//******************************************************************************
639//******************************************************************************
640BOOL Win32Image::storeSections(char *win32file)
641{
642 int i;
643 APIRET rc;
644 ULONG pagFlags = PAG_COMMIT;
645 ULONG headersize;
646 WINIMAGE_LOOKUP *imgLookup;
647
648 //Commit memory for image header
649 headersize = sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) +
650 sizeof(IMAGE_SECTION_HEADER) * fh.NumberOfSections;
651
652 if(headersize + sizeof(WINIMAGE_LOOKUP) < PAGE_SIZE) {
653 headersize = PAGE_SIZE;
654 }
655 else {//ooops, just in case this doesn't work
656 fout << "ERROR: storeSections: header too big!!!!!! Fatal error" << endl;
657 return FALSE;
658 }
659
660 rc = DosSetMem((PVOID)realBaseAddress, headersize, pagFlags | PAG_WRITE | PAG_READ);
661 if(rc) {
662 fout << "DosSetMem failed for Image header! " << rc << endl;
663 return FALSE;
664 }
665 // Store the NT header at the load addr
666 memcpy((char *)realBaseAddress, win32file, sizeof(IMAGE_DOS_HEADER));
667 memcpy((char *)PE_HEADER(realBaseAddress), PE_HEADER(win32file), sizeof(IMAGE_NT_HEADERS));
668 memcpy(PE_SECTIONS(realBaseAddress), PE_SECTIONS(win32file),
669 sizeof(IMAGE_SECTION_HEADER) * fh.NumberOfSections );
670
671 imgLookup = WINIMAGE_LOOKUPADDR(realBaseAddress);
672 imgLookup->image = this;
673 imgLookup->magic = MAGIC_WINIMAGE;
674
675 // Process all the image sections
676 for(i=0;i<nrsections;i++) {
677 section[i].realvirtaddr = realBaseAddress + (section[i].virtaddr - oh.ImageBase);
678 }
679 for(i=0;i<nrsections;i++) {
680 pagFlags = PAG_COMMIT;
681 switch(section[i].type) {
682 case SECTION_CODE:
683 case (SECTION_CODE | SECTION_IMPORT):
684 case SECTION_INITDATA:
685 case SECTION_UNINITDATA:
686 case SECTION_IMPORT:
687 case SECTION_READONLYDATA:
688 case SECTION_RESOURCE:
689 case SECTION_TLS:
690 pagFlags |= PAG_WRITE | PAG_READ;
691 break;
692 case SECTION_EXPORT:
693 case SECTION_DEBUG:
694 case SECTION_RELOC:
695 pagFlags = 0; //don't commit
696 break;
697 }
698 if(pagFlags == 0) continue; //debug or export section
699
700 rc = DosSetMem((PVOID)section[i].realvirtaddr, section[i].virtualsize, pagFlags);
701 if(rc) {
702 errorState = rc;
703 return(FALSE);
704 }
705 if(section[i].type != SECTION_UNINITDATA) {
706 assert(section[i].rawdata);
707 memcpy((char *)section[i].realvirtaddr, section[i].rawdata, section[i].rawsize);
708 }
709 }
710 return(TRUE);
711}
712//******************************************************************************
713//******************************************************************************
714BOOL Win32Image::setMemFlags()
715{
716 int i;
717 APIRET rc;
718 ULONG pagFlags = 0;
719
720 for(i=0;i<nrsections;i++) {
721 pagFlags = 0;
722 switch(section[i].type) {
723 case SECTION_CODE:
724 case (SECTION_CODE | SECTION_IMPORT):
725 pagFlags |= PAG_EXECUTE | PAG_READ;
726 break;
727 case SECTION_INITDATA:
728 case SECTION_UNINITDATA:
729 case SECTION_IMPORT: //TODO: read only?
730 pagFlags |= PAG_WRITE | PAG_READ;
731 break;
732 case SECTION_READONLYDATA:
733 case SECTION_RESOURCE:
734 case SECTION_TLS:
735 pagFlags |= PAG_READ;
736 break;
737 default:
738 continue;
739 }
740 rc = DosSetMem((PVOID)section[i].realvirtaddr, section[i].virtualsize, pagFlags);
741 if(rc) {
742 errorState = rc;
743 return(FALSE);
744 }
745 }
746 return(TRUE);
747}
748//******************************************************************************
749//******************************************************************************
750BOOL Win32Image::setFixups(PIMAGE_BASE_RELOCATION prel)
751{
752 int i, j;
753 char *page;
754 ULONG count;
755
756 if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
757 return(TRUE);
758 }
759
760 if(prel) {
761 j = 1;
762 while(prel->VirtualAddress) {
763 page = (char *)((char *)prel + (ULONG)prel->VirtualAddress);
764 count = (prel->SizeOfBlock - 8)/2;
765 fout.setf(ios::hex, ios::basefield);
766 fout << "Page " << j << " Address " << (ULONG)prel->VirtualAddress << " Count " << count << endl;
767 fout.setf(ios::dec, ios::basefield);
768 j++;
769 for(i=0;i<count;i++) {
770 int type = prel->TypeOffset[i] >> 12;
771 int offset = prel->TypeOffset[i] & 0xFFF;
772 switch(type) {
773 case IMAGE_REL_BASED_ABSOLUTE:
774//// fout << "absolute fixup; unused" << endl;
775 break; //skip
776 case IMAGE_REL_BASED_HIGHLOW:
777//// fout << "address " << offset << " type " << type << endl;
778 AddOff32Fixup(oh.ImageBase +
779 prel->VirtualAddress + offset);
780 break;
781 case IMAGE_REL_BASED_HIGH:
782 AddOff16Fixup(oh.ImageBase + prel->VirtualAddress + offset, TRUE);
783 break;
784 case IMAGE_REL_BASED_LOW:
785 AddOff16Fixup(oh.ImageBase + prel->VirtualAddress + offset, FALSE);
786 break;
787 case IMAGE_REL_BASED_HIGHADJ:
788 case IMAGE_REL_BASED_MIPS_JMPADDR:
789 default:
790 fout << "Unknown/unsupported fixup type!" << endl;
791 break;
792 }
793 }
794 prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock);
795 }//while
796 }
797 else {
798 fout << "No internal fixups found!\n" << endl;
799 errorState = ERROR_INTERNAL;
800 return(FALSE);
801 }
802 return(TRUE);
803}
804//******************************************************************************
805//******************************************************************************
806void Win32Image::AddOff32Fixup(ULONG fixupaddr)
807{
808 ULONG orgaddr;
809 ULONG *fixup;
810
811 fixup = (ULONG *)(fixupaddr - oh.ImageBase + realBaseAddress);
812 orgaddr = *fixup;
813 *fixup = realBaseAddress + (*fixup - oh.ImageBase);
814}
815//******************************************************************************
816//******************************************************************************
817void Win32Image::AddOff16Fixup(ULONG fixupaddr, BOOL fHighFixup)
818{
819 ULONG orgaddr;
820 USHORT *fixup;
821
822 fixup = (USHORT *)(fixupaddr - oh.ImageBase + realBaseAddress);
823 orgaddr = *fixup;
824 if(fHighFixup) {
825 *fixup += (USHORT)((realBaseAddress - oh.ImageBase) >> 16);
826 }
827 else {
828 *fixup += (USHORT)((realBaseAddress - oh.ImageBase) & 0xFFFF);
829 }
830}
831//******************************************************************************
832//******************************************************************************
833void Win32Image::StoreImportByOrd(Win32Dll *WinDll, ULONG ordinal, ULONG impaddr)
834{
835 ULONG *import;
836 ULONG apiaddr;
837
838 import = (ULONG *)(impaddr - oh.ImageBase + realBaseAddress);
839 apiaddr = WinDll->getApi(ordinal);
840 if(apiaddr == 0) {
841 fout << "--->>> NOT FOUND!";
842 *import = (ULONG)MissingApi;
843 }
844 else *import = apiaddr;
845}
846//******************************************************************************
847//******************************************************************************
848void Win32Image::StoreImportByName(Win32Dll *WinDll, char *impname, ULONG impaddr)
849{
850 ULONG *import;
851 ULONG apiaddr;
852
853 import = (ULONG *)(impaddr - oh.ImageBase + realBaseAddress);
854 apiaddr = WinDll->getApi(impname);
855 if(apiaddr == 0) {
856 fout << "--->>> NOT FOUND!";
857 *import = (ULONG)MissingApi;
858 }
859 else *import = apiaddr;
860}
861//******************************************************************************
862//******************************************************************************
863BOOL Win32Image::processExports(char *win32file)
864{
865 IMAGE_SECTION_HEADER sh;
866 PIMAGE_EXPORT_DIRECTORY ped;
867 ULONG *ptrNames, *ptrAddress;
868 USHORT *ptrOrd;
869 int i;
870
871 /* get section header and pointer to data directory for .edata section */
872 if((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset
873 (win32file, IMAGE_DIRECTORY_ENTRY_EXPORT)) != NULL &&
874 GetSectionHdrByImageDir(win32file, IMAGE_DIRECTORY_ENTRY_EXPORT, &sh) ) {
875
876 fout << "Exported Functions: " << endl;
877 ptrOrd = (USHORT *)((ULONG)ped->AddressOfNameOrdinals -
878 (ULONG)sh.VirtualAddress +
879 (ULONG)sh.PointerToRawData + (ULONG)win32file);
880 ptrNames = (ULONG *)((ULONG)ped->AddressOfNames -
881 (ULONG)sh.VirtualAddress +
882 (ULONG)sh.PointerToRawData + (ULONG)win32file);
883 ptrAddress = (ULONG *)((ULONG)ped->AddressOfFunctions -
884 (ULONG)sh.VirtualAddress +
885 (ULONG)sh.PointerToRawData + (ULONG)win32file);
886 nrOrdExports = ped->NumberOfFunctions;
887 nrNameExports = ped->NumberOfNames;
888
889 int ord, RVAExport;
890 char *name;
891 for(i=0;i<ped->NumberOfNames;i++) {
892 ord = ptrOrd[i] + ped->Base;
893 name = (char *)((ULONG)ptrNames[i] - (ULONG)sh.VirtualAddress +
894 (ULONG)sh.PointerToRawData + (ULONG)win32file);
895 RVAExport = ptrAddress[ptrOrd[i]];
896#ifdef FORWARDERS
897 if(RVAExport < sh.VirtualAddress || RVAExport > sh.VirtualAddress + sh.SizeOfRawData) {
898#endif
899 //points to code (virtual address relative to oh.ImageBase
900 fout << "address 0x";
901 fout.setf(ios::hex, ios::basefield);
902 fout << RVAExport;
903 fout.setf(ios::dec, ios::basefield);
904 fout << " " << name << "@" << ord << endl;
905 AddNameExport(oh.ImageBase + RVAExport, name, ord);
906#ifdef FORWARDERS
907
908 }
909 else {//forwarder
910 char *forward = (char *)((ULONG)RVAExport -
911 (ULONG)sh.VirtualAddress +
912 (ULONG)sh.PointerToRawData +
913 (ULONG)win32file);
914 fout << RVAExport << " " << name << " @" << ord << " is forwarder to " << (int)forward << endl;
915 }
916#endif
917 }
918 for(i=0;i<max(ped->NumberOfNames,ped->NumberOfFunctions);i++) {
919 ord = ped->Base + i; //Correct??
920 RVAExport = ptrAddress[i];
921#ifdef FORWARDERS
922 if(RVAExport < sh.VirtualAddress || RVAExport > sh.VirtualAddress + sh.SizeOfRawData) {
923#endif
924 if(RVAExport) {
925 //points to code (virtual address relative to oh.ImageBase
926 fout << "ord " << ord << " at 0x";
927 fout.setf(ios::hex, ios::basefield);
928 fout << RVAExport << endl;
929 fout.setf(ios::dec, ios::basefield);
930 AddOrdExport(oh.ImageBase + RVAExport, ord);
931 }
932#ifdef FORWARDERS
933 }
934 else {//forwarder or empty
935 char *forward = (char *)((ULONG)RVAExport -
936 (ULONG)sh.VirtualAddress +
937 (ULONG)sh.PointerToRawData +
938 (ULONG)win32file);
939 fout << "ord " << ord << " at 0x";
940 fout.setf(ios::hex, ios::basefield);
941 fout << RVAExport << " is forwarder to 0x" << (int)forward << endl;
942 fout.setf(ios::dec, ios::basefield);
943 }
944#endif
945 }
946 }
947 return(TRUE);
948}
949//******************************************************************************
950//******************************************************************************
951void Win32Image::AddNameExport(ULONG virtaddr, char *apiname, ULONG ordinal)
952{
953 ULONG nsize;
954
955 if(nameexports == NULL) {
956 nameExportSize= 4096;
957 nameexports = (NameExport *)malloc(nameExportSize);
958 curnameexport = nameexports;
959 }
960 nsize = (ULONG)curnameexport - (ULONG)nameexports;
961 if(nsize + sizeof(NameExport) + strlen(apiname) > nameExportSize) {
962 nameExportSize += 4096;
963 char *tmp = (char *)nameexports;
964 nameexports = (NameExport *)malloc(nameExportSize);
965 memcpy(nameexports, tmp, nsize);
966 curnameexport = (NameExport *)((ULONG)nameexports + nsize);
967 free(tmp);
968 }
969 curnameexport->virtaddr = realBaseAddress + (virtaddr - oh.ImageBase);
970 curnameexport->ordinal = ordinal;
971 *(ULONG *)curnameexport->name = 0;
972 strcpy(curnameexport->name, apiname);
973
974 curnameexport->nlength = strlen(apiname) + 1;
975 if(curnameexport->nlength < sizeof(curnameexport->name))
976 curnameexport->nlength = sizeof(curnameexport->name);
977
978 curnameexport = (NameExport *)((ULONG)curnameexport->name + curnameexport->nlength);
979}
980//******************************************************************************
981//******************************************************************************
982void Win32Image::AddOrdExport(ULONG virtaddr, ULONG ordinal)
983{
984 if(ordexports == NULL) {
985 ordexports = (OrdExport *)malloc(nrOrdExports * sizeof(OrdExport));
986 curordexport = ordexports;
987 }
988 curordexport->virtaddr = realBaseAddress + (virtaddr - oh.ImageBase);
989 curordexport->ordinal = ordinal;
990 curordexport++;
991}
992//******************************************************************************
993/** All initial processing of imports is done here
994 * Should now detect most Borland styled files including the GifCon32.exe and
995 * loader32 from SoftIce. (Stupid Borland!!!)
996 *
997 * knut [Jul 22 1998 2:44am]
998 **/
999//******************************************************************************
1000BOOL Win32Image::processImports(char *win32file)
1001{
1002 PIMAGE_IMPORT_DESCRIPTOR pID;
1003 IMAGE_SECTION_HEADER shID;
1004 IMAGE_SECTION_HEADER shExtra = {0};
1005 PIMAGE_OPTIONAL_HEADER pOH;
1006 int i,j;
1007 BOOL fBorland = 0;
1008 int cModules;
1009 char *pszModules;
1010 char *pszCurModule;
1011 char *pszTmp;
1012 ULONG *pulImport;
1013 ULONG ulCurFixup;
1014 int Size;
1015 Win32Dll *WinDll;
1016
1017/* "algorithm:"
1018 * 1) get module names and store them
1019 * a) check dwRVAModuleName is within .idata seg - if not find section
1020 * 2) iterate thru functions of each module
1021 * a) check OriginalFirstThunk is not 0 and that it points to a RVA.
1022 * b) if not a) borland-styled PE-file - ARG!!!
1023 * check FirstThunk
1024 * c) check OriginalFirstThunk/FirstThunk ok RVAs and find right section
1025 * d) store ordinal/name import
1026 * 3) finished
1027 */
1028
1029 /* 1) get module names */
1030 pID = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryOffset(win32file, IMAGE_DIRECTORY_ENTRY_IMPORT);
1031 if (pID == NULL)
1032 return TRUE;
1033 if (!GetSectionHdrByImageDir(win32file, IMAGE_DIRECTORY_ENTRY_IMPORT, &shID))
1034 return TRUE;
1035
1036 //calc size of module list
1037 i = Size = cModules = 0;
1038 while (pID[i].Name != 0)
1039 {
1040 //test RVA inside ID-Section
1041 if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData)) {
1042 pszTmp = (char*)(pID[i].Name- shID.VirtualAddress + shID.PointerToRawData + (ULONG)win32file);
1043 }
1044 else {
1045 //is the "Extra"-section already found or do we have to find it?
1046 if (pID[i].Name < shExtra.VirtualAddress || pID[i].Name >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData)) {
1047 if (!GetSectionHdrByRVA(win32file, &shExtra, pID[i].Name))
1048 return FALSE;
1049 }
1050 pszTmp = (char*)(pID[i].Name- shExtra.VirtualAddress + shExtra.PointerToRawData + (ULONG)win32file);
1051 }
1052 Size += strlen(pszTmp) + 1;
1053 i++;
1054 cModules++;
1055 }
1056
1057 pszModules = (char*)malloc(Size);
1058 assert(pszModules != NULL);
1059 j = 0;
1060 for (i = 0; i < cModules; i++)
1061 {
1062 //test RVA inside ID-Section
1063 if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData)) {
1064 pszTmp = (char*)(pID[i].Name- shID.VirtualAddress + shID.PointerToRawData + (ULONG)win32file);
1065 }
1066 else {
1067 fBorland = TRUE;
1068 //is the "Extra"-section already found or do we have to find it?
1069 if (pID[i].Name < shExtra.VirtualAddress || pID[i].Name >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
1070 {
1071 if (GetSectionHdrByRVA(win32file, &shExtra, pID[i].Name)) {
1072 free(pszModules);
1073 return FALSE;
1074 }
1075 }
1076 pszTmp = (char*)(pID[i].Name- shExtra.VirtualAddress + shExtra.PointerToRawData + (ULONG)win32file);
1077 }
1078
1079 strcpy(pszModules+j, pszTmp);
1080 j += strlen(pszTmp) + 1;
1081 }
1082 fout << endl;
1083 if (fBorland)
1084 fout << "Borland-styled PE-File." << endl;
1085 //Store modules
1086 fout << cModules << " imported Modules: " << endl;
1087
1088 /* 2) functions */
1089 pszCurModule = pszModules;
1090 pOH = (PIMAGE_OPTIONAL_HEADER)OPTHEADEROFF(win32file);
1091 for (i = 0; i < cModules; i++)
1092 {
1093 fout << "Module " << pszCurModule << endl;
1094 // a) check that OriginalFirstThunk not is 0 and look for Borland-styled PE
1095 if (i == 0)
1096 {
1097 //heavy borland-style test - assume array of thunks is within that style does not change
1098 if((ULONG)pID[i].u.OriginalFirstThunk == 0 ||
1099 (ULONG)pID[i].u.OriginalFirstThunk < shID.VirtualAddress ||
1100 (ULONG)pID[i].u.OriginalFirstThunk >= shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData) ||
1101 (ULONG)pID[i].u.OriginalFirstThunk >= pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress &&
1102 (ULONG)pID[i].u.OriginalFirstThunk < sizeof(*pID)*cModules + pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
1103 {
1104 fBorland = TRUE;
1105 }
1106 }
1107 //light borland-style test
1108 if (pID[i].u.OriginalFirstThunk == 0 || fBorland)
1109 pulImport = (ULONG*)pID[i].FirstThunk;
1110 else pulImport = (ULONG*)pID[i].u.OriginalFirstThunk;
1111
1112 // b) check if RVA ok
1113 if (!(pulImport > 0 && (ULONG)pulImport < pOH->SizeOfImage)) {
1114 fout << "Invalid RVA " << hex((ULONG)pulImport) << endl;
1115 break;
1116 }
1117 // check section
1118 if ((ULONG)pulImport < shExtra.VirtualAddress || (ULONG)pulImport >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData))
1119 {
1120 if (!GetSectionHdrByRVA(win32file, &shExtra, (ULONG)pulImport))
1121 {
1122 fout << "warning: could not find section for Thunk RVA " << hex((ULONG)pulImport) << endl;
1123 break;
1124 }
1125 }
1126
1127 //SvL: Load dll if needed
1128 fout << "**********************************************************************" << endl;
1129 fout << "************** Import Module " << pszCurModule << endl;
1130 fout << "**********************************************************************" << endl;
1131 WinDll = Win32Dll::findModule(pszCurModule);
1132 if(WinDll == NULL)
1133 { //not found, so load it
1134 WinDll = new Win32Dll(pszCurModule, this);
1135
1136 if(WinDll == NULL) {
1137 fout << "WinDll: Error allocating memory" << endl;
1138 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szMemErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
1139 errorState = ERROR_INTERNAL;
1140 return(FALSE);
1141 }
1142 fout << "**********************************************************************" << endl;
1143 fout << "********************** Loading Module *********************" << endl;
1144 fout << "**********************************************************************" << endl;
1145 if(WinDll->init(0) == FALSE) {
1146 fout << "Internal WinDll error " << WinDll->getError() << endl;
1147 return(FALSE);
1148 }
1149 if(WinDll->attachProcess() == FALSE) {
1150 fout << "attachProcess failed!" << endl;
1151 errorState = ERROR_INTERNAL;
1152 return(FALSE);
1153 }
1154 fout << "**********************************************************************" << endl;
1155 fout << "********************** Finished Loading Module *********************" << endl;
1156 fout << "**********************************************************************" << endl;
1157 }
1158 else fout << "Already found " << pszCurModule << endl;
1159
1160 WinDll->AddRef();
1161
1162 pulImport = (PULONG)((ULONG)pulImport - shExtra.VirtualAddress + (ULONG)win32file + shExtra.PointerToRawData);
1163 j = 0;
1164 ulCurFixup = (ULONG)pID[i].FirstThunk + pOH->ImageBase;
1165 while (pulImport[j] != 0) {
1166 if (pulImport[j] & IMAGE_ORDINAL_FLAG) { //ordinal
1167 fout.setf(ios::hex, ios::basefield);
1168 fout << "0x" << ulCurFixup << " Imported function " << pszCurModule << "@" << (pulImport[j] & ~IMAGE_ORDINAL_FLAG) << endl;
1169 fout.setf(ios::dec, ios::basefield);
1170 StoreImportByOrd(WinDll, pulImport[j] & ~IMAGE_ORDINAL_FLAG, ulCurFixup);
1171 }
1172 else { //name
1173 //check
1174 if (pulImport[j] < shExtra.VirtualAddress || pulImport[j] >= shExtra.VirtualAddress + max(shExtra.Misc.VirtualSize, shExtra.SizeOfRawData)) {
1175 if (!GetSectionHdrByRVA(win32file, &shExtra, pulImport[j]))
1176 {
1177 fout << "warning: could not find section for Import Name RVA " << hex(pulImport[j]) << endl;
1178 break;
1179 }
1180 }
1181 //KSO - Aug 6 1998 1:15am:this eases comparing...
1182 char *pszFunctionName = (char*)(pulImport[j] + (ULONG)win32file + shExtra.PointerToRawData - shExtra.VirtualAddress + 2);
1183 fout.setf(ios::hex, ios::basefield);
1184 fout << "0x" << ulCurFixup << " Imported function " << pszFunctionName << endl;
1185 fout.setf(ios::dec, ios::basefield);
1186 StoreImportByName(WinDll, pszFunctionName, ulCurFixup);
1187 }
1188 ulCurFixup += sizeof(IMAGE_THUNK_DATA);
1189 j++;
1190 }
1191 fout << "**********************************************************************" << endl;
1192 fout << "************** End Import Module " << pszCurModule << endl;
1193 fout << "**********************************************************************" << endl;
1194
1195 pszCurModule += strlen(pszCurModule) + 1;
1196 fout << endl;
1197 }//for (i = 0; i < cModules; i++)
1198
1199 free(pszModules);
1200 return TRUE;
1201}
1202//******************************************************************************
1203//******************************************************************************
1204BOOL Win32Image::isPEImage(char *szFileName)
1205{
1206 IMAGE_FILE_HEADER fh;
1207 HFILE win32handle;
1208 ULONG ulAction = 0; /* Action taken by DosOpen */
1209 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
1210 APIRET rc = NO_ERROR; /* Return code */
1211 LPVOID win32file = NULL;
1212 ULONG ulRead;
1213 int nSections, i;
1214
1215 rc = DosOpen(szFileName, /* File path name */
1216 &win32handle, /* File handle */
1217 &ulAction, /* Action taken */
1218 0L, /* File primary allocation */
1219 0L, /* File attribute */
1220 OPEN_ACTION_FAIL_IF_NEW |
1221 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
1222 OPEN_FLAGS_NOINHERIT |
1223 OPEN_SHARE_DENYNONE |
1224 OPEN_ACCESS_READONLY, /* Open mode of the file */
1225 0L); /* No extended attribute */
1226
1227 if (rc != NO_ERROR)
1228 {
1229 dprintf(("KERNEL32:Win32Image::isPEImage(%s) failed with %u\n",
1230 szFileName, rc));
1231 return(FALSE);
1232 }
1233
1234 /* Move the file pointer back to the beginning of the file */
1235 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
1236
1237 IMAGE_DOS_HEADER *pdoshdr = (IMAGE_DOS_HEADER *)malloc(sizeof(IMAGE_DOS_HEADER));
1238 if(pdoshdr == NULL) {
1239 DosClose(win32handle); /* Close the file */
1240 return(FALSE);
1241 }
1242 rc = DosRead(win32handle, pdoshdr, sizeof(IMAGE_DOS_HEADER), &ulRead);
1243 if(rc != NO_ERROR) {
1244 DosClose(win32handle); /* Close the file */
1245 return(FALSE);
1246 }
1247 ULONG hdrsize = pdoshdr->e_lfanew + SIZE_OF_NT_SIGNATURE + sizeof(IMAGE_FILE_HEADER);
1248 free(pdoshdr);
1249
1250 /* Move the file pointer back to the beginning of the file */
1251 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
1252
1253 win32file = malloc(hdrsize);
1254 if(win32file == NULL) {
1255 DosClose(win32handle); /* Close the file */
1256 return(FALSE);
1257 }
1258 rc = DosRead(win32handle, win32file, hdrsize, &ulRead);
1259 if(rc != NO_ERROR) {
1260 goto failure;
1261 }
1262
1263 if(GetPEFileHeader (win32file, &fh) == FALSE) {
1264 goto failure;
1265 }
1266
1267 if(!(fh.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {//not valid
1268 goto failure;
1269 }
1270 if(fh.Machine != IMAGE_FILE_MACHINE_I386) {
1271 goto failure;
1272 }
1273 //IMAGE_FILE_SYSTEM == only drivers (device/file system/video etc)?
1274 if(fh.Characteristics & IMAGE_FILE_SYSTEM) {
1275 goto failure;
1276 }
1277 DosClose(win32handle);
1278 return(TRUE);
1279
1280failure:
1281 free(win32file);
1282 DosClose(win32handle);
1283 return(FALSE);
1284}
1285//******************************************************************************
1286//******************************************************************************
1287void Win32Image::setFullPath(char *name)
1288{
1289 dassert(name, ("setFullPath, name == NULL"));
1290 fullpath = (char *)malloc(strlen(name)+1);
1291 dassert(fullpath, ("setFullPath, fullpath == NULL"));
1292 strcpy(fullpath, name);
1293}
1294//******************************************************************************
1295//******************************************************************************
1296ULONG MissingApi()
1297{
1298 static BOOL fIgnore = FALSE;
1299 int r;
1300
1301 dprintf(("Missing api called!\n"));
1302 if(fIgnore)
1303 return(0);
1304
1305 do {
1306 r = WinMessageBox(HWND_DESKTOP, NULLHANDLE, "The application has called a non-existing api\n",
1307 "Internal Error", 0, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION | MB_MOVEABLE);
1308 }
1309 while(r == MBID_RETRY); //giggle
1310
1311 if( r != MBID_IGNORE )
1312 exit(987);
1313
1314 fIgnore = TRUE;
1315 return(0);
1316}
1317/******************************************************************************/
1318/******************************************************************************/
1319/*heximal(decimal) KSO Sun 24.05.1998*/
1320char szHexBuffer[30];
1321
1322char *hex(ULONG num)
1323{
1324 sprintf(szHexBuffer, "0x%+08x (%lu)",num,num);
1325 return szHexBuffer;
1326}
1327//******************************************************************************
1328//******************************************************************************
Note: See TracBrowser for help on using the repository browser.