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

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

Readonly memory mapped files work now + PE loader uses those apis

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