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

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

PE loader changes (exes without fixups + TLS support)

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