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

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

PE loader bugfixes

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