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

Last change on this file since 99 was 99, checked in by phaller, 26 years ago

Add: added cvs variable $Id$ to source files.

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