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

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

better error reporting for pe loader

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