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

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

Allow executable api exports

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