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

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

* empty log message *

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