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

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

Logging change, DosAllocMem for Aurora change (PE loader) + fixed AllocFixedMem

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