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

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

PE loader changes

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