source: trunk/src/kernel32/winimagepeldr.cpp@ 1811

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

Rewrite of PE loader code, EB's fixes + VirtualProtect bugfix

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