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

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

Console fixes

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