source: trunk/src/win32k/pe2lx/lxfile.cpp@ 847

Last change on this file since 847 was 847, checked in by bird, 26 years ago

Initial checkin of Win32k. (not tested & pe2lx not up-to-date!)

File size: 105.9 KB
Line 
1/* $Id: lxfile.cpp,v 1.1 1999-09-06 02:20:05 bird Exp $
2 *
3 * PE2LX/win32k - Implementation of the class LXFile.
4 *
5 * Copyright 1998-1999 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
6 *
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12/*******************************************************************************
13* Header Files *
14*******************************************************************************/
15#include <stdarg.h>
16
17#include "pe2lx.h" /* toplevel includefile */
18/* Extra Ring0 stuff */
19#include "OS2Krnl.h"
20#include "ldrCalls.h"
21#include "sprintf.h"
22#include "Yield.h"
23
24/* resource includes */
25#include "accelerator.h"
26#include "cursor.h"
27#include "cursorgrp.h"
28#include "dialog.h"
29#include "icon.h"
30#include "icongrp.h"
31#include "menu.h"
32#include "bitmap.h"
33#include "rcdata.h"
34#include "strings.h"
35
36#include <versionos2.h>
37
38
39
40/*******************************************************************************
41* Global Variables *
42*******************************************************************************/
43/** heximal(decimal) Buffer for hex(ULONG) */
44char szHexBuffer[30];
45
46
47
48/**
49 * Print a number on the form "0xNUMINHEX (NUMINDEC)".
50 * Example: hex(1024) returns "0x00000400 (1024)".
51 * @return pointer
52 */
53char *hex(ULONG num)
54{
55 sprintf(szHexBuffer, "0x%+08x (%lu)",num,num);
56 return szHexBuffer;
57}
58
59/** PE Resource Types */
60char *ResTypes[] =
61 {"niks", "CURSOR", "BITMAP", "ICON", "MENU", "DIALOG", "STRING",
62 "FONTDIR", "FONT", "ACCELERATOR", "RCDATA", "MESSAGETABLE",
63 "GROUP_CURSOR", "niks", "GROUP_ICON", "niks", "VERSION"};
64
65
66
67#ifdef RING0_DEBUG_IN_RING3
68
69 #define _ldrRead __ldrRead
70
71 /** Ring3 repacement for the os2krnls _ldrRead function*/
72 ULONG __ldrRead(
73 SFN hFile,
74 ULONG ulOffset,
75 PVOID pBuffer,
76 ULONG ulFlags ,
77 ULONG ulBytesToRead,
78 PMTE pMTE
79 )
80 {
81 ULONG ulRead, ulMoved;
82 APIRET rc;
83
84 rc = DosSetFilePtr(hFile, ulOffset, FILE_BEGIN, &ulMoved);
85 if (rc == NO_ERROR)
86 rc = DosRead(hFile, pBuffer, ulBytesToRead, &ulRead);
87 else
88 cout << "DosSetFilePtr(hfile, " << ulOffset << ",..,..) failed with rc = " << rc << endl;
89 return rc;
90 }
91
92#endif
93
94
95
96/**
97 * Constructor.
98 */
99LXFile::LXFile()
100{
101 cout << "LXFile::LXFile()" << endl;
102 inited = 0;
103 hFile = 0;
104 nSections = 0;
105 pObjectTable = NULL;
106 pObjectPageTable = NULL;
107 pFixupTable = NULL;
108 pFixupRecordTable = NULL;
109
110 //fixup stuff:
111 fCrossed = FALSE;
112 crossedpageaddress = 0;
113
114 lastord = 0;
115 fFirstIcon = FALSE;
116}
117
118
119
120/**
121 * Destructor
122 */
123LXFile::~LXFile()
124{
125 cout << "LXFile::~LXFile()" << endl;
126 if (pFixupTable) free (pFixupTable);
127 if (pFixupRecordTable) free (pFixupRecordTable);
128 if (pObjectTable) free (pObjectTable);
129 if (pObjectPageTable) free (pObjectPageTable);
130}
131
132
133
134/**
135 * Initiating conversion of the PE file.
136 * @param hFile Handle(SystemFileNumber) to the PE-file.
137 * @param pHdr Pointer to the PE signature(if any) and the following 196 (size of a LX-header).
138 * @param PEOffset Offset, into the PE-file, of the PE signature. (That is offset of the data pHdr points to.)
139 * @return Boolean. True if successful (converting of PE) else False.
140 * @remark Should only be called one time! Object should not be used if init(...) failes!
141 */
142BOOL LXFile::init(SFN hFile, PIMAGE_SIG_FILE_HEADER pHdr, ULONG PEOffset)
143{
144 ULONG rc;
145 PIMAGE_SECTION_HEADER pSectionTable = NULL;
146 int i,j;
147 char *pszSectionName = (char*)malloc(IMAGE_SIZEOF_SHORT_NAME + 1);
148
149 cout << "LXFile::init!" << endl;
150
151 /* validate file header */
152 if(!isPEFile(pHdr))
153 {
154 kprintf(("LXFile::init: Sorry. Not a pe file.\n"));
155 return 0;
156 }
157
158 /* ok copy file handler, offset and pHdr*/
159 LXFile::hFile = hFile;
160 ulPEOffset = PEOffset;
161 memcpy(&PEHdrs.Signature, &pHdr->Signature, sizeof(DWORD) );
162 memcpy(&PEHdrs.FileHeader, &pHdr->FileHeader, sizeof(IMAGE_FILE_HEADER) );
163
164 /* Exe or DLL? */
165 if(PEHdrs.FileHeader.Characteristics & IMAGE_FILE_DLL)
166 SetExeType(FALSE);
167 else
168 SetExeType(TRUE);
169
170 /* Relocations ? */
171 if(PEHdrs.FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
172 {
173 cout << "No fixups, might not run - yet!" << endl;
174 SetNoFixups();
175 }
176
177 /* Read optional header */
178 rc = _ldrRead(
179 hFile,
180 PEOffset + IMAGE_SIZEOF_FILE_HEADER + sizeof(DWORD)/*(sizeof signature)*/,
181 &PEHdrs.OptionalHeader,
182 0,
183 sizeof(IMAGE_OPTIONAL_HEADER),
184 NULL
185 );
186
187 if (rc != NO_ERROR)
188 {
189 kprintf(("Oops - error while reading optional header rc=%d \n", rc));
190 return FALSE;
191 }
192
193 if (PEHdrs.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
194 {
195 kprintf(("Oops - incorrect Magic word in optional header.\n"));
196 return FALSE;
197 }
198
199
200 cout << "PE Optional header: " << endl;
201 cout << "Preferred address : " << hex(PEHdrs.OptionalHeader.ImageBase) << endl;
202 cout << "Base Of Code : " << hex(PEHdrs.OptionalHeader.BaseOfCode) << endl;
203 cout << "CodeSize : " << hex(PEHdrs.OptionalHeader.SizeOfCode) << endl;
204 cout << "Base Of Data : " << hex(PEHdrs.OptionalHeader.BaseOfData) << endl;
205 cout << "Data Size (uninit): " << hex(PEHdrs.OptionalHeader.SizeOfUninitializedData) << endl;
206 cout << "Data Size (init) : " << hex(PEHdrs.OptionalHeader.SizeOfInitializedData) << endl;
207 cout << "Entry Point : " << hex(PEHdrs.OptionalHeader.AddressOfEntryPoint) << endl;
208 cout << "Section Alignment : " << hex(PEHdrs.OptionalHeader.SectionAlignment) << endl;
209 cout << "Stack Reserve size: " << hex(PEHdrs.OptionalHeader.SizeOfStackReserve) << endl;
210 cout << "Stack Commit size : " << hex(PEHdrs.OptionalHeader.SizeOfStackCommit) << endl;
211 cout << "SizeOfHeapReserve : " << hex(PEHdrs.OptionalHeader.SizeOfHeapReserve) << endl;
212 cout << "SizeOfHeapCommit : " << hex(PEHdrs.OptionalHeader.SizeOfHeapCommit) << endl;
213 cout << "FileAlignment : " << hex(PEHdrs.OptionalHeader.FileAlignment) << endl;
214
215 /* Module Type GUI/console (SetExeType must have been called before!) */
216 if (PEHdrs.OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_GUI)
217 {
218 if (PEHdrs.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
219 {
220 SetModuleType(SYSTEM_CHARACTER);
221 //cout << "Console app" << endl;
222 }
223 else
224 {
225 cout << "Sorry subsystem ";
226 switch (PEHdrs.OptionalHeader.Subsystem)
227 {
228 case IMAGE_SUBSYSTEM_NATIVE:
229 cout << "native";
230 break;
231 case IMAGE_SUBSYSTEM_OS2_CUI:
232 cout << "os2 cui";
233 break;
234 case IMAGE_SUBSYSTEM_POSIX_CUI:
235 cout << "posix";
236 break;
237 default:
238 cout << "unknown" << PEHdrs.OptionalHeader.Subsystem;
239 }
240 cout << " is not supported - yet." << endl;
241 return FALSE;
242 }
243 }
244 else
245 {
246 SetModuleType(SYSTEM_GUI);
247 //cout << "GUI app" << endl;
248 }
249
250 /* StackSize */
251 SetStackSize(max(PEHdrs.OptionalHeader.SizeOfStackCommit, PEHdrs.OptionalHeader.SizeOfStackReserve));
252
253
254 /* Sections */
255 nSections = PEHdrs.FileHeader.NumberOfSections;
256 ltassert( SetNrSections(nSections));
257
258 /* read read section Table */
259 pSectionTable = (PIMAGE_SECTION_HEADER)malloc(nSections*sizeof(IMAGE_SECTION_HEADER)); /* don't forget to free pSectionTable! */
260 ltassert(pSectionTable != NULL);
261
262 rc = _ldrRead(
263 hFile,
264 ulPEOffset+sizeof(IMAGE_NT_HEADERS),
265 pSectionTable,
266 0,
267 nSections*sizeof(IMAGE_SECTION_HEADER),
268 NULL
269 );
270
271 if (rc != NO_ERROR)
272 {
273 cout << endl << "Oops! error while reading section table, rc" << rc << endl;
274 free(pSectionTable);
275 return FALSE;
276 }
277
278 /* Create TIBSection ?! */
279 if (!(options.noExeTIBFix && IsEXE))
280 ltassert(CreateTIBSection(&PEHdrs.OptionalHeader));
281
282 /* iterate thru the sections */
283 cout << endl;
284 for (i = 0; i < nSections; i++)
285 {
286 memset(pszSectionName,0,9);
287 strncpy(pszSectionName, pSectionTable[i].Name, IMAGE_SIZEOF_SHORT_NAME);
288
289 cout << "Section Name: " << pszSectionName << endl;
290 cout << "Raw data size: " << hex(pSectionTable[i].SizeOfRawData) << endl;
291 cout << "Virtual Address: " << hex(pSectionTable[i].VirtualAddress) << endl;
292 cout << "Virtual Size: " << hex(pSectionTable[i].Misc.VirtualSize) << endl;
293 cout << "Pointer to raw data: " << hex(pSectionTable[i].PointerToRawData) << endl;
294 cout << "Section flags: " << hex(pSectionTable[i].Characteristics) << endl;
295 /* ignore .reloc */
296 if (strcmp(pszSectionName, ".reloc") == 0) {
297 cout << ".reloc" << endl << endl;
298 continue;
299 }
300 /* ignore .edata - later */
301 if (strcmp(pszSectionName, ".edata") == 0) {
302 cout << ".edata" << endl << endl;
303 continue;
304 }
305 /* ignore .pdata - what is in this section?*/
306 if (strcmp(pszSectionName, ".pdata") == 0) {
307 cout << ".pdata" << endl << endl;
308 continue;
309 }
310 /* ignore .rsrc - later */
311 if (strcmp(pszSectionName, ".rsrc") == 0) {
312 cout << ".rsrc" << endl << endl;
313 continue;
314 }
315 /* ignore .debug */
316 if (strcmp(pszSectionName, ".debug") == 0) {
317 cout << ".rdebug" << endl << endl;
318 continue;
319 }
320
321 /* import */
322 if (strcmp(pszSectionName, ".idata") == 0 || PEIsImportDataSection(&pSectionTable[i]))
323 {
324 int type = SECTION_IMPORT;
325
326 cout << "Import Data Section" << endl << endl;
327 if(pSectionTable[i].Characteristics & IMAGE_SCN_CNT_CODE)
328 {
329 cout << "Also Code Section" << endl << endl;
330 type |= SECTION_CODE;
331 }
332 StoreSection(
333 pSectionTable[i].PointerToRawData,
334 pSectionTable[i].SizeOfRawData,
335 pSectionTable[i].Misc.VirtualSize,
336 pSectionTable[i].VirtualAddress + PEHdrs.OptionalHeader.ImageBase,
337 type);
338 continue;
339 }
340 /* code section */
341 if ((pSectionTable[i].Characteristics & IMAGE_SCN_CNT_CODE)
342 //KSO Sun 1998-08-09: Borland does not alway set the CODE flag for its "CODE" section (TIB fix need to have the first section marked as code)
343 || (pSectionTable[i].Characteristics & IMAGE_SCN_MEM_EXECUTE &&
344 !(pSectionTable[i].Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA)) //KSO: make sure its not marked as a datasection
345 )
346 )
347 {
348 cout << "Code Section" << endl << endl;
349 StoreSection(
350 pSectionTable[i].PointerToRawData,
351 pSectionTable[i].SizeOfRawData,
352 pSectionTable[i].Misc.VirtualSize,
353 pSectionTable[i].VirtualAddress + PEHdrs.OptionalHeader.ImageBase,
354 SECTION_CODE);
355 continue;
356 }
357 /* readonly data */
358 if(!(pSectionTable[i].Characteristics & IMAGE_SCN_MEM_WRITE)) //read only data section
359 {
360 cout << "Read Only Data Section" << endl << endl;
361 StoreSection(
362 pSectionTable[i].PointerToRawData,
363 pSectionTable[i].SizeOfRawData,
364 pSectionTable[i].Misc.VirtualSize,
365 pSectionTable[i].VirtualAddress + PEHdrs.OptionalHeader.ImageBase,
366 SECTION_READONLYDATA);
367 continue;
368 }
369 /* uninit. data */
370 if(pSectionTable[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
371 {
372 cout << "Uninitialized Data Section" << endl << endl;
373 StoreSection(
374 pSectionTable[i].PointerToRawData,
375 pSectionTable[i].SizeOfRawData,
376 pSectionTable[i].Misc.VirtualSize,
377 pSectionTable[i].VirtualAddress + PEHdrs.OptionalHeader.ImageBase,
378 SECTION_UNINITDATA);
379 continue;
380 }
381 /* init. data */
382 if(pSectionTable[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
383 {
384 cout << "Initialized Data Section" << endl << endl;
385 StoreSection(
386 pSectionTable[i].PointerToRawData,
387 pSectionTable[i].SizeOfRawData,
388 pSectionTable[i].Misc.VirtualSize,
389 pSectionTable[i].VirtualAddress + PEHdrs.OptionalHeader.ImageBase,
390 SECTION_INITDATA);
391 continue;
392 }
393 /* other */
394 if(pSectionTable[i].Characteristics & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ))
395 {
396 cout << "Other Section, stored as read/write uninit data" << endl << endl;
397 StoreSection(
398 pSectionTable[i].PointerToRawData,
399 pSectionTable[i].SizeOfRawData,
400 pSectionTable[i].Misc.VirtualSize,
401 pSectionTable[i].VirtualAddress + PEHdrs.OptionalHeader.ImageBase,
402 SECTION_UNINITDATA);
403 continue;
404 }
405 }
406
407 /*SvL: Align and/or concatenate code & data sections*/
408 if (options.AlignSections)
409 if (!AlignSections(&PEHdrs.OptionalHeader))
410 {
411 free(pSectionTable);
412 return FALSE;
413 }
414
415 if (options.noExeTIBFix && IsEXE)
416 {
417 /* here we set the entrypoint for EXEs which don't have a TIBFix */
418 ltasserthp2(SetEntryAddress(PEHdrs.OptionalHeader.AddressOfEntryPoint + PEHdrs.OptionalHeader.ImageBase), free(pSectionTable));
419 }
420
421 Yield();
422
423 /* BASE RELOCATIONS */
424 if (!ProcessFixups(pSectionTable))
425 {
426 free(pSectionTable);
427 return FALSE;
428 }
429
430 Yield();
431
432 /* EXPORTS */
433 if (!ProcessExports(pSectionTable))
434 {
435 free(pSectionTable);
436 return FALSE;
437 }
438
439 Yield();
440
441 /* IMPORTS */
442 if (!ProcessImports(pSectionTable))
443 {
444 free(pSectionTable);
445 return FALSE;
446 }
447
448 Yield();
449
450 /* RESOURCES */
451 if (!ProcessResources(pSectionTable))
452 {
453 free(pSectionTable);
454 return FALSE;
455 }
456
457 Yield();
458
459 /* processing PE file is finished */
460 /* no use for SectionTable any more - free the space */
461 free(pSectionTable);
462 pSectionTable = NULL;
463
464 /* build LX file */
465 rc = PrepareLX();
466
467 Yield();
468
469 return rc;
470}
471
472
473
474/**
475 * Build the virtual LX - file.
476 * @return True on success. False on failiure - object is then unusable.
477 */
478BOOL LXFile::PrepareLX()
479{
480 int rc;
481
482 realintfixup *currealrec;
483 intfixup *frec;
484 namefixup *imprec;
485
486 int pagetblidx, i, j, k, idx, rawsize, objectsize;
487 int nrpages, pagedataoffset;
488 //BOOL fFirstCode = FALSE;
489 int objcnt;
490
491
492
493 //*************************************/
494 //* Object Table && Object Page Table */
495 //*************************************/
496 pagetblidx = 1; //start met 1
497 pagedataoffset = 0;
498 nrpages = GetNrPages();
499
500 LXHdr.e32_objcnt = GetNrObjects2(); //NB! All Objects
501 LXHdr.e32_mpages = 0;
502
503 pObjectTable = (struct o32_obj*)malloc((LXHdr.e32_objcnt)*sizeof(o32_obj));
504 ltassert(pObjectTable != NULL);
505 memset(pObjectTable,0,LXHdr.e32_objcnt*sizeof(o32_obj));
506
507 //Stack is not contained within the "Object Page Table". [KSO Jun 24 1998 5:43am]
508 //pObjectPageTable = (struct o32_map*)malloc((nrpages-(StackSize+0xFFF>>PAGE_SHIFT))*sizeof(o32_map));
509 pObjectPageTable = (struct o32_map*)malloc(nrpages*sizeof(o32_map));
510 ltassert(pObjectPageTable != NULL);
511 //pObjectPageTable = (struct o32_map*)malloc((nrpages)*sizeof(o32_map));
512
513 idx = -1;
514 objcnt = 1;
515
516 /* section -> object */
517 for ( i = 0; i < nrsections; i++)
518 {
519 pObjectTable[objcnt-1].o32_reserved = 0;
520 pObjectTable[objcnt-1].o32_pagemap = pagetblidx;
521 if (PESection[i].fInvalid)
522 continue;
523
524 switch (PESection[i].type)
525 {
526 case (SECTION_CODE | SECTION_TIBFIX): //KSO Aug 16 1998: TIBFixObject
527 case (SECTION_CODE | SECTION_IMPORT):
528 case SECTION_CODE:
529 pObjectTable[objcnt-1].o32_flags = OBJREAD | NSEXRD | OBJBIGDEF;
530 break;
531 case SECTION_IMPORT:
532 pObjectTable[objcnt-1].o32_flags = OBJREAD | OBJBIGDEF;
533 break;
534 case SECTION_INITDATA:
535 pObjectTable[objcnt-1].o32_flags = OBJREAD | OBJWRITE | OBJBIGDEF;
536 break;
537 case SECTION_COMBINEDDATA:
538 pObjectTable[objcnt-1].o32_flags = OBJREAD | OBJWRITE | OBJBIGDEF;
539 break;
540 case SECTION_RESOURCE_ORG:
541 case SECTION_UNINITDATA:
542 //SvL: Zero filled flag maps on Permanent flag, so ditch it
543 pObjectTable[objcnt-1].o32_flags = OBJREAD | OBJWRITE | OBJBIGDEF; //read/write/big
544 break;
545 case SECTION_READONLYDATA:
546 pObjectTable[objcnt-1].o32_flags = OBJREAD | OBJBIGDEF;
547 break;
548 }
549 //OS/2 doesn't seem to mind if the sizes of all the pages in an object
550 //exceeds the object size....
551 if (PESection[i].type == SECTION_UNINITDATA)
552 objectsize = PESection[i].virtualsize; //rawsize == 0
553 else
554 objectsize = PESection[i].rawsize;
555
556 pObjectTable[objcnt-1].o32_mapsize = PESection[i].nrpages;
557 pObjectTable[objcnt-1].o32_mapsize += PESection[i].nrinvalidpages;
558 pObjectTable[objcnt-1].o32_base = PESection[i].address;
559 pObjectTable[objcnt-1].o32_size = pObjectTable[objcnt-1].o32_mapsize*PAGE_SIZE;
560
561 rawsize = PESection[i].rawsize;
562 for ( j = 0; j < pObjectTable[objcnt-1].o32_mapsize; j++)
563 {
564 idx = pagetblidx+j-1;
565 pObjectPageTable[idx].o32_pagedataoffset = pagedataoffset;
566
567 if (j < PESection[i].nrinvalidpages)
568 {
569 pObjectPageTable[idx].o32_pagesize = 0;
570 //SvL: Invalid pages are not properly handled by the OS/2 loader -> make 'em zeroed
571 pObjectPageTable[idx].o32_pageflags = ZEROED;
572 }
573 else
574 {
575 if (PESection[i].type == SECTION_COMBINEDDATA)
576 {
577 //KSO Aug 16 1998: TIBFixObject - some code removed
578 int didx = j - PESection[i].nrinvalidpages;
579 pObjectPageTable[idx].o32_pagesize = datapage[didx].size;
580 pObjectPageTable[idx].o32_pageflags = datapage[didx].flags;
581 pagedataoffset += pObjectPageTable[idx].o32_pagesize;
582 if (pObjectPageTable[idx].o32_pageflags == 0)
583 LXHdr.e32_mpages++;
584 }
585 else
586 if (PESection[i].type == SECTION_UNINITDATA || rawsize == 0)
587 {
588 pObjectPageTable[idx].o32_pagesize = 0;
589 pObjectPageTable[idx].o32_pagedataoffset = pagedataoffset;
590 pObjectPageTable[idx].o32_pageflags = ZEROED;
591 }
592 else //KSO Aug 16 1998: no more TIBFix code to think about
593 {
594 if (rawsize > PAGE_SIZE)
595 pObjectPageTable[idx].o32_pagesize = PAGE_SIZE;
596 else
597 pObjectPageTable[idx].o32_pagesize = rawsize;
598 rawsize -= pObjectPageTable[idx].o32_pagesize;
599 pObjectPageTable[idx].o32_pageflags = 0;
600 LXHdr.e32_mpages++;
601 pagedataoffset += pObjectPageTable[idx].o32_pagesize;
602 }
603 }
604 }
605
606 if (IsEXE && i == nrsections - 1)
607 {//SvL: 25-7-'97 Add stack pages to last data object
608 LXHdr.e32_stackobj = objcnt;
609 LXHdr.e32_autodata = LXHdr.e32_stackobj;
610 pObjectTable[objcnt-1].o32_flags |= OBJWRITE;
611 pObjectTable[objcnt-1].o32_size += StackSize;
612 LXHdr.e32_esp = pObjectTable[objcnt-1].o32_size; //highest address in object
613 }
614
615 pagetblidx += pObjectTable[objcnt-1].o32_mapsize;
616 objcnt++;
617 }//for("nrsections")
618
619 /* fix entry for TIBFixObject */
620 if (!(options.noExeTIBFix && IsEXE))
621 {
622 int iPESection = GetTIBSectionIdx(); //
623 LXHdr.e32_eip = 0;
624 LXHdr.e32_startobj = GetTIBObjectNo();
625 ltassert(LXHdr.e32_startobj != -1 && iPESection!= -1);
626 TIBEntry = PEHdrs.OptionalHeader.AddressOfEntryPoint //RVA
627 + PEHdrs.OptionalHeader.ImageBase
628 - (PESection[iPESection].address + TIBOffCall + SIZE_TIBCALL);
629 }
630 else
631 {
632 /* no TIB stuff at all */
633 SetEntryAddress(PEHdrs.OptionalHeader.AddressOfEntryPoint + PEHdrs.OptionalHeader.ImageBase);
634 }
635
636
637
638 //***********************************************/
639 //* Resource Table && Object Page Table (cont.) */
640 //***********************************************/
641 if (nrresources)
642 {
643 //Correct count in case there are string tables which aren't completely filled
644 nrresources = curresource;
645 //Objects are ALL counted! //LXHdr.e32_objcnt++;
646 pObjectTable[objcnt-1].o32_pagemap = pagetblidx;
647 pObjectTable[objcnt-1].o32_flags = NSSHARED | OBJREAD | OBJRSRC | OBJBIGDEF;
648 pObjectTable[objcnt-1].o32_mapsize = ResSection.rawsize >> PAGE_SHIFT;
649
650 pObjectTable[objcnt-1].o32_base = 0; //SvL: Set to 0 in PM exes (plf)
651 pObjectTable[objcnt-1].o32_size = ResSection.rawsize;
652
653 for ( j = 0; j < pObjectTable[objcnt-1].o32_mapsize; j++)
654 {
655 idx = pagetblidx + j - 1;
656 pObjectPageTable[idx].o32_pagedataoffset = pagedataoffset;
657 pObjectPageTable[idx].o32_pagesize = PAGE_SIZE;
658 pObjectPageTable[idx].o32_pageflags = 0;
659 LXHdr.e32_mpages++;
660 pagedataoffset += PAGE_SIZE;
661 }
662 if ((pObjectTable[objcnt-1].o32_size & 0xFFF) != 0)
663 {
664 pObjectTable[objcnt-1].o32_mapsize++;
665 LXHdr.e32_mpages++;
666 idx++;
667 pObjectPageTable[idx].o32_pagedataoffset = pagedataoffset;
668 pObjectPageTable[idx].o32_pagesize = (USHORT)(pObjectTable[objcnt-1].o32_size & 0xFFF);
669 pObjectPageTable[idx].o32_pageflags = 0;
670 pagedataoffset += pObjectPageTable[idx].o32_pagesize;
671 }
672
673 pagetblidx += pObjectTable[objcnt-1].o32_mapsize;
674
675 //fill in object nr's in resource table entries
676 for ( i = 0; i < nrresources; i++)
677 {
678 os2resource[i].obj = LXHdr.e32_objcnt;
679 }
680 }// if (nrresources)
681
682 /* Object Page Table finished */
683 //object page records offset:
684 LXHdr.e32_objmap = LXHdr.e32_objtab + LXHdr.e32_objcnt*sizeof(pObjectTable[objcnt-1]);
685 //size tables vanaf object table t/m impproc (eigenlijk pagesum ook..)
686 LXHdr.e32_ldrsize = LXHdr.e32_objcnt*sizeof(pObjectTable[objcnt-1]);
687 //LXHdr.e32_ldrsize += (nrpages-(StackSize+0xFFF>>PAGE_SHIFT))*sizeof(o32_map);
688 LXHdr.e32_ldrsize += nrpages*sizeof(o32_map);
689
690 //resource table:
691 LXHdr.e32_rsrctab = LXHdr.e32_ldrsize + LXHdr.e32_objtab;
692 LXHdr.e32_rsrccnt = nrresources;
693 LXHdr.e32_ldrsize += nrresources*sizeof(rsrc32);
694 LXHdr.e32_restab = LXHdr.e32_rsrctab + nrresources*sizeof(rsrc32);
695
696
697
698 //**************************************/
699 //* Resident Name Table && Entry Table */
700 //**************************************/
701 #if 1 //KSO Aug 16 1998: exports from exes and dll without exports: TODO cleanup!
702 if (exports)
703 {
704 //write DLL export information
705 int len = 0;
706
707 //save resident name table
708 if (exports)
709 {
710 len = curexport - exports + 1; // + 0 byte to signal end of table
711 LXHdr.e32_ldrsize += len;
712 }
713
714 //save entry table
715 LXHdr.e32_enttab = LXHdr.e32_restab + len;
716 //TODO: Forwarders!
717 len = (int)curexpb - (int)expbundle + 1; // + 0 byte to signal end of table
718 if (len > 1)
719 LXHdr.e32_ldrsize += len;
720 }
721 else
722 {
723 int modlen;
724 //save resident name table
725 //KSO: modname has right format - Jun 16 1998 4:27pm
726 modlen = (char)modulename[0];
727 modlen += 1 + 2 + 1; //len byte + ord word + 0 byte
728
729 //save entry table
730 LXHdr.e32_enttab = LXHdr.e32_restab + modlen; //points to 0 byte
731 LXHdr.e32_ldrsize += 1 + modlen;
732 }
733
734 #else
735
736 if (IsEXE == TRUE)
737 {
738 int modlen;
739 //save resident name table
740 //KSO: modname has right format - Jun 16 1998 4:27pm
741 modlen = (char)modulename[0];
742 modlen += 1 + 2 + 1; //len byte + ord word + 0 byte
743
744 //save entry table
745 LXHdr.e32_enttab = LXHdr.e32_restab + modlen; //points to 0 byte
746 LXHdr.e32_ldrsize += 1 + modlen;
747 }
748 else
749 {
750 //write DLL export information
751 int len = 0;
752
753 //save resident name table
754 if (exports)
755 {
756 len = curexport - exports + 1; // + 0 byte to signal end of table
757 LXHdr.e32_ldrsize += len;
758 }
759
760 //save entry table
761 LXHdr.e32_enttab = LXHdr.e32_restab + len;
762 //TODO: Forwarders!
763 len = (int)curexpb - (int)expbundle + 1; // + 0 byte to signal end of table
764 if (len > 1)
765 LXHdr.e32_ldrsize += len;
766 }
767 #endif
768
769
770 Yield();
771
772
773 //********************/
774 //* Fixup Page Table */
775 //********************/
776 //#pages * offset naar import fixups + 1 eind offset
777 LXHdr.e32_fpagetab = LXHdr.e32_ldrsize + LXHdr.e32_objtab;
778 LXHdr.e32_frectab = LXHdr.e32_fpagetab + (nrpages + 1) * sizeof(int);
779 pFixupTable = (int*)malloc((nrpages + 1) * sizeof(int));
780 ltassert(pFixupTable != NULL)
781
782 for ( i = 0; i <= nrpages; i++)
783 pFixupTable[i] = 0;
784
785 //dump alle fixup records in 1 memory block en bepaal offsets in fixup page table
786 frec = &intfixuprec[0];
787 imprec = &impfixuprec[0];
788 pFixupRecordTable = (realintfixup*)malloc(
789 (nrintfixups + 1) * sizeof(realintfixup) //KSO Aug 16 1998: "+1": internal entrypointfixup
790 + (nrimpfixups + EXTRA_FIXUPS) * sizeof(realnamefixup)
791 );
792 ltassert2(pFixupRecordTable != NULL, free(pFixupTable);pFixupTable = NULL);
793
794 /* KSO Aug 16 1998: we need the pageno of the TIBSection */
795 int TIBPageNo = GetTIBSectionIdx();
796 ltassert(TIBPageNo != -1);
797 TIBPageNo = GetPageNoByVA(PESection[TIBPageNo].address);
798
799 currealrec = pFixupRecordTable;
800 j = 0;
801 k = 0;
802 for (i = 0; i < nrpages; i++)
803 {
804 pFixupTable[i] = (int)currealrec - (int)pFixupRecordTable;
805 if (i == TIBPageNo && !(IsEXE && options.noExeTIBFix))
806 {
807 //add kernel32:registerresourceinfo import
808 realordfixup *kerord = (realordfixup *)currealrec;
809 kerord->nr_stype = 0x07; //32 bits offset
810 kerord->nr_flags = 0x01 | 0x40; //import by ordinal + mod offset = 16 bits
811 kerord->r32_soff = TIBOffKerImport;
812 kerord->r32_objmod = kernel32Object + 1;
813 if (IsEXE)
814 kerord->ord = ORD_REGISTERRESOURCEINFO;
815 else
816 kerord->ord = ORD_REGISTERDLL;
817
818 currealrec = (realintfixup *)((int)currealrec + sizeof(realnamefixup));
819 ltasserthp(currealrec); //pFixupTable & pFixupRecordTable will be freed by the destructor
820 if (!IsEXE)
821 {
822 kerord = (realordfixup *)currealrec;
823 kerord->nr_stype = 0x08; //32 bits self referencing offset
824 kerord->nr_flags = 0x01 | 0x40; //import by ordinal + mod offset = 16 bits
825 kerord->r32_soff = DLL_OFF_KERIMP2;
826 kerord->r32_objmod = kernel32Object + 1;
827 kerord->ord = ORD_KERNEL32DLLEXITLIST;
828 currealrec = (realintfixup *)((int)currealrec + sizeof(realnamefixup));
829 }
830
831 /* add entrypoint internal fixup */
832 realintfixup *pEntInt = currealrec;
833 pEntInt->nr_stype = 0x08; //self referencing
834 pEntInt->nr_flags = 0x00 | 0x10 | 0x40;
835 pEntInt->r32_soff = TIBOffEntry;
836 pEntInt->targetaddr = PEHdrs.OptionalHeader.ImageBase + PEHdrs.OptionalHeader.AddressOfEntryPoint;
837 pEntInt->targetobj = GetObjectNoByVA(pEntInt->targetaddr);
838 ltassert(pEntInt->targetobj != -1);
839 pEntInt->targetaddr -= pObjectTable[pEntInt->targetobj - 1].o32_base;
840 currealrec++;
841 }// if (i == 0)
842
843 //SvL: 16-9-'97, for multiple import pages
844 while (k < nrimpfixups && imprec->srcpage == i)
845 {
846 //sizeof(realordfixup) == sizeof(realnamefixup)
847 memcpy(currealrec, imprec, sizeof(realnamefixup));
848 currealrec = (realintfixup *)((int)currealrec + sizeof(realnamefixup));
849 ltasserthp(currealrec); //pFixupTable & pFixupRecordTable will be freed by the destructor
850 imprec++;
851 ltasserthp(imprec); //pFixupTable & pFixupRecordTable will be freed by the destructor
852 k++;
853 }
854 while (j < nrintfixups && frec->srcpage == i)
855 {
856 memcpy(currealrec, frec, sizeof(realintfixup));
857 // cout << "src address " << frec->r32_soff << " srcpage " << frec->srcpage << " target " << frec->targetaddr << " frec " << (int)frec << endl;
858 frec++;
859 ltasserthp(frec); //pFixupTable & pFixupRecordTable will be freed by the destructor
860 currealrec++;
861 ltasserthp(currealrec); //pFixupTable & pFixupRecordTable will be freed by the destructor
862 j++;
863 }
864
865 }//for
866 pFixupTable[nrpages] = (int)currealrec - (int)pFixupRecordTable;
867
868 //Add extra kernel32 imports and evt. internal entrypoint-fixup
869 if (IsEXE)
870 nrimpfixups++;
871 else
872 nrimpfixups += EXTRA_FIXUPS;
873 nrintfixups += 1; //KSO Aug 16 1998: internal entrypoint fixup
874
875 /* impfixuprec and intfixuprec are not needed any more */
876 if (impfixuprec != NULL)
877 {
878 free(impfixuprec);
879 impfixuprec = NULL;
880 }
881 if (intfixuprec != NULL)
882 {
883 free(intfixuprec);
884 intfixuprec = NULL;
885 }
886
887 //fixup page + record + import name + module table size
888 LXHdr.e32_fixupsize = (nrpages+1)*sizeof(int)
889 + (ULONG)currealrec - (ULONG)pFixupRecordTable
890 + impmodulesize
891 + impnamesize;
892
893 //size tables vanaf object table t/m impproc (eigenlijk pagesum ook..)
894 LXHdr.e32_ldrsize += LXHdr.e32_fixupsize;
895
896 //offset naar module name array
897 LXHdr.e32_impmod = LXHdr.e32_frectab + ((ULONG)currealrec - (ULONG)pFixupRecordTable);
898 //offset naar proc name array
899 LXHdr.e32_impproc = LXHdr.e32_impmod + impmodulesize;
900
901
902 Yield();
903
904
905 //*************/
906 //* Code/Data */
907 //*************/
908 //pointer naar begin code/data
909 if (options.lxoffset)
910 ulPEOffset = LXHEADER_OFFSET;
911
912 LXHdr.e32_datapage = LXHdr.e32_impproc + impnamesize + ulPEOffset; //relative to begin of file
913
914 ULONG ulCurrentOffset = LXHdr.e32_datapage;
915 for (i = 0; i < nrsections; i++)
916 {
917 //zero filled pages, niet nodig om op te slaan
918 if (PESection[i].type != SECTION_UNINITDATA && PESection[i].rawdata)
919 {
920 PESection[i].lxoffset = ulCurrentOffset;
921 ulCurrentOffset += PESection[i].rawsize;
922 }
923 }
924
925
926
927 //*************/
928 //* Resources */
929 //*************/
930 if (nrresources)
931 ResSection.lxoffset = ulCurrentOffset;
932
933 cout << "LXFile::PrepareLX is finished" << endl;
934 inited = TRUE;
935
936 #ifndef RELEASE
937 //Lets have a look at how much mem is used by this module...
938 if (options.fLogging)
939 queryMemoryUsage();
940 #endif
941
942 return (TRUE);
943}
944
945
946
947/**
948 * Process Fixups in a PE file.
949 * @param pSectionTable Pointer to Section Table.
950 * @return TRUE on success. FALSE on failiure - object is then unusable.
951 */
952BOOL LXFile::ProcessFixups(PIMAGE_SECTION_HEADER pSectionTable)
953{
954 /* BASE RELOCATIONS */
955 int i,j,rc;
956 ULONG VARead;
957
958 ULONG offRel = PEImageDirectoryOffset (pSectionTable, IMAGE_DIRECTORY_ENTRY_BASERELOC);
959 ltassert(SetNrOff32Fixups((offRel > 0) ? PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size/2 : 0)); //size/2 is approixmate... or?
960
961 if ( offRel != 0 && PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size > 0)
962 {
963 PIMAGE_BASE_RELOCATION pRelocations, prel, end;
964 int count;
965 char *page;
966
967 /* page currently processed */
968 char *pPage = (char*)malloc(PAGE_SIZE * 2);
969 ltassert(pPage != NULL);
970
971 /* allocate memory for base reallocations */
972 pRelocations = (PIMAGE_BASE_RELOCATION)malloc(PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
973 ltasserthp2(pRelocations, free(pPage));
974
975 /* read them */
976 rc = _ldrRead(
977 hFile,
978 offRel,
979 pRelocations,
980 0,
981 PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size,
982 NULL
983 );
984 if (rc != NO_ERROR)
985 {
986 cout << "Error while trying to read base relocatations. rc=" << rc << endl;
987 free(pRelocations);
988 free(pPage);
989 return FALSE;
990 }
991
992 prel = pRelocations;
993 end = (PIMAGE_BASE_RELOCATION)((ULONG)pRelocations + PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
994 j = 1;
995 VARead = ~0;
996 while (prel < end && prel->VirtualAddress)
997 {
998 AddOff32FinishCrossPageFixup();
999 page = (char *)prel + (int)prel->VirtualAddress;
1000 count = (prel->SizeOfBlock - 8)/2;
1001 cout.setf(ios::hex, ios::basefield);
1002 cout << "Page " << j << " Address " << (ULONG)prel->VirtualAddress << " Count " << count << endl;
1003 cout.setf(ios::dec, ios::basefield);
1004
1005 /* page buffer */
1006 if (VARead == prel->VirtualAddress)
1007 memcpy(pPage, pPage+PAGE_SIZE, PAGE_SIZE);
1008 else
1009 {
1010 /*read it */
1011 rc = ReadPageByAddress(
1012 PEHdrs.OptionalHeader.ImageBase + prel->VirtualAddress,
1013 pPage
1014 );
1015
1016 if (rc != NO_ERROR && rc != -2)
1017 {
1018 cout << "error reading the page. rc=" << rc << endl;
1019 return 0;
1020 }
1021 }
1022 /* process all fixups for this page */
1023 for (i = 0; i < count; i++)
1024 {
1025 int type = prel->TypeOffset[i] >> 12;
1026 int offset = prel->TypeOffset[i] & 0xFFF;
1027 switch (type)
1028 {
1029 case IMAGE_REL_BASED_ABSOLUTE:
1030 //cout << "absolute fixup; unused" << endl;
1031 break; //skip
1032
1033 case IMAGE_REL_BASED_HIGHLOW:
1034 //cout << "address " << hex(offset) << " type " << type; // << endl;
1035
1036 /* check if this is an crosspage fixup */
1037 if (offset > PAGE_SIZE-4)
1038 {
1039 /* read folowing page */
1040 VARead = prel->VirtualAddress + PAGE_SIZE;
1041 rc = ReadPageByAddress(
1042 PEHdrs.OptionalHeader.ImageBase + VARead,
1043 pPage + PAGE_SIZE
1044 );
1045 if ( rc != NO_ERROR && rc != -2 )
1046 {
1047 cout << "warning: could not read next page - cross page fixup have incorrect target address. rc=" << rc << endl;
1048 VARead = ~0;
1049 memset(pPage+PAGE_SIZE, 0, 4);
1050 }
1051 }
1052 rc = AddOff32Fixup(PEHdrs.OptionalHeader.ImageBase + prel->VirtualAddress + offset, pPage);
1053 //cout << endl;
1054 break;
1055
1056 case IMAGE_REL_BASED_HIGH:
1057 case IMAGE_REL_BASED_LOW:
1058 case IMAGE_REL_BASED_HIGHADJ:
1059 case IMAGE_REL_BASED_MIPS_JMPADDR:
1060 default:
1061 cout << "Unknown/unsupported fixup type!" << endl;
1062 break;
1063 }//switch
1064 }//for
1065
1066 /* check if the next page is the one we read */
1067 /* we must read ahead because of fixups that overlap pages */
1068 prel = (PIMAGE_BASE_RELOCATION)((ULONG)prel + prel->SizeOfBlock);
1069 j++;
1070 }//while
1071 AddOff32FinishCrossPageFixup(); //catch evt. crosspagefixup on the last page with fixup(s). This may work...
1072 free(pPage);
1073 free(pRelocations);
1074 }
1075
1076 return TRUE;
1077}
1078
1079
1080
1081/**
1082 * Process Exports in a PE file.
1083 * @return True on success. False on failiure - object is then unusable.
1084 * @param pSectionTable Pointer to Section Table.
1085 */
1086BOOL LXFile::ProcessExports(PIMAGE_SECTION_HEADER pSectionTable)
1087{
1088 int rc, i;
1089
1090 /* EXPORTS */
1091 /* get section header and pointer to data directory for .edata section */
1092 //if (PEHdrs.FileHeader.Characteristics & IMAGE_FILE_DLL) - this won't do for Borland exes!!
1093 //{
1094 PCHAR pExportSection = NULL;
1095 PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;
1096 PIMAGE_SECTION_HEADER pESH = PEGetSectionHdrByImageDir(pSectionTable, IMAGE_DIRECTORY_ENTRY_EXPORT);
1097 ULONG offExportDirectory = PEImageDirectoryOffset (pSectionTable, IMAGE_DIRECTORY_ENTRY_EXPORT);
1098
1099 if ( offExportDirectory > 0 && pESH != NULL)
1100 {
1101 /* allocate memory for exportsection */
1102 pExportSection = (PCHAR)malloc(max(pESH->Misc.VirtualSize, pESH->SizeOfRawData));
1103 ltassert(pExportSection != NULL);
1104
1105 /* read exportsection */
1106 rc = _ldrRead(
1107 hFile,
1108 pESH->PointerToRawData,
1109 pExportSection,
1110 0,
1111 max(pESH->Misc.VirtualSize, pESH->SizeOfRawData),
1112 NULL
1113 );
1114 if (rc != NO_ERROR)
1115 {
1116 cout << "Error while trying to read exportsection. rc=" << rc << endl;
1117 free(pExportSection);
1118 free(pSectionTable);
1119 return FALSE;
1120 }
1121
1122 pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG)pExportSection + (offExportDirectory - pESH->PointerToRawData)); //??
1123 ltasserthp2(pExportDirectory,free(pExportSection));
1124
1125
1126 int *ptrNames;
1127 int *ptrAddress;
1128 USHORT *ptrOrd;
1129
1130 cout << "Exported Functions: " << endl;
1131 ptrOrd =(USHORT *)((ULONG)pExportDirectory->AddressOfNameOrdinals - (ULONG)pESH->VirtualAddress + (ULONG)pExportSection);
1132 ptrNames = (int *)((int)pExportDirectory->AddressOfNames - (ULONG)pESH->VirtualAddress + (ULONG)pExportSection);
1133 ptrAddress = (int *)((int)pExportDirectory->AddressOfFunctions - (ULONG)pESH->VirtualAddress + (ULONG)pExportSection);
1134 ltasserthp2(ptrOrd, free(pExportSection));
1135 ltasserthp2(ptrNames, free(pExportSection));
1136 ltasserthp2(ptrAddress,free(pExportSection));
1137 ltassert2(SetNrExtFixups(max(pExportDirectory->NumberOfNames, pExportDirectory->NumberOfFunctions)), free(pExportSection));
1138
1139
1140 int ord;
1141 int RVAExport;
1142 char *name;
1143
1144 for ( i = 0; i < pExportDirectory->NumberOfNames; i++)
1145 {
1146 ord = ptrOrd[i] + pExportDirectory->Base;
1147 name = (char *)((ULONG)ptrNames[i] - (ULONG)pESH->VirtualAddress + (ULONG)pExportSection);
1148 ltasserthp2(name, free(pExportSection));
1149
1150 RVAExport = ptrAddress[ptrOrd[i]];
1151 // RVAExport = ptrAddress[i];
1152#ifdef FORWARDERS
1153 if (RVAExport < pESH->VirtualAddress || RVAExport > pESH->VirtualAddress + pESH->SizeOfRawData)
1154 {
1155#endif
1156 //points to code (virtual address relative to oh.ImageBase
1157 cout << "address 0x";
1158 cout.setf(ios::hex, ios::basefield);
1159 cout << RVAExport;
1160 cout.setf(ios::dec, ios::basefield);
1161 cout << " " << name << "@" << ord << endl;
1162 ltassert2(AddNameExport(PEHdrs.OptionalHeader.ImageBase + RVAExport, name, ord), free(pExportSection));
1163#ifdef FORWARDERS
1164
1165 }
1166 else
1167 {//forwarder
1168 char *forward = (char *)((ULONG)RVAExport -
1169 (ULONG)pESH->VirtualAddress +
1170 (ULONG)pExportSection);
1171 ltasserthp2(forward, free(pExportSection));
1172 cout << RVAExport << " " << name << " @" << ord << " is forwarder to " << (int)forward << endl;
1173 //ltassert2(AddForwarder(name, ord, forward), free(pExportSection);
1174 }
1175#endif
1176 }//for
1177
1178 for ( i = 0; i < max(pExportDirectory->NumberOfNames, pExportDirectory->NumberOfFunctions); i++)
1179 {
1180 ord = pExportDirectory->Base + i; //Correct??
1181 RVAExport = ptrAddress[i];
1182#ifdef FORWARDERS
1183 if (RVAExport < pESH->VirtualAddress || RVAExport > pESH->VirtualAddress + pESH->SizeOfRawData)
1184 {
1185#endif
1186 if (RVAExport)
1187 {
1188 //points to code (virtual address relative to oh.ImageBase
1189 cout << "ord " << ord << " at 0x";
1190 cout.setf(ios::hex, ios::basefield);
1191 cout << RVAExport << endl;
1192 cout.setf(ios::dec, ios::basefield);
1193 ltassert2(AddOrdExport(PEHdrs.OptionalHeader.ImageBase + RVAExport, ord), free(pExportSection));
1194 }
1195#ifdef FORWARDERS
1196 }
1197 else
1198 {//forwarder or empty
1199 char *forward = (char *)((int)RVAExport -
1200 (int)pESH->VirtualAddress +
1201 (ULONG)pExportSection);
1202 ltasserthp2(forward, free(pExportSection));
1203 cout << "ord " << ord << " at 0x";
1204 cout.setf(ios::hex, ios::basefield);
1205 cout << RVAExport << " is forwarder to 0x" << (int)forward << endl;
1206 cout.setf(ios::dec, ios::basefield);
1207 //ltassert2(AddForwarder(NULL, ord, forward), free(pExportSection));
1208 }
1209#endif
1210 }//for
1211
1212 free(pExportSection);
1213 }
1214
1215
1216 /* realloc exports */
1217 if (exports != NULL)
1218 {
1219 char *pTmp;
1220 pTmp = (char*)realloc(exports, curexport - exports + 1);
1221 if(pTmp != NULL)
1222 {
1223 curexport += pTmp-exports;
1224 exports = pTmp;
1225 }
1226 else
1227 kprintf(("LXFile::PrepareLX:realloc(exports, curexport-exports+1 failed.\n"));
1228 }
1229
1230 return TRUE;
1231}
1232
1233
1234
1235/**
1236 * Process Imports in a PE file.
1237 * @param pFile Pointer to start of PE-file.
1238 * @return True on success. False on failiure - object is then unusable.
1239 * @algo 1) get module names and store them<br>
1240 * a) check dwRVAModuleName is within .idata seg - if not find section<br>
1241 * 2) iterate thru functions of each module<br>
1242 * a) check OriginalFirstThunk is not 0 and that it points to a RVA.<br>
1243 * b) if not a) borland-styled PE-file - ARG!!! check FirstThunk<br>
1244 * c) check OriginalFirstThunk/FirstThunk ok RVAs and find right section<br>
1245 * d) store ordinal/name import<br>
1246 * 3) finished<br>
1247 * @remark Should now detect most Borland styled files including the GifCon32.exe and
1248 * loader32 from SoftIce. (Stupid Borland!!!)<br>
1249 * KSO [Jul 22 1998 2:44am]<br>
1250 * <I>This function has a sister function in (pe.cpp)ProcessImports - update always both</I>
1251 */
1252BOOL LXFile::ProcessImports(PIMAGE_SECTION_HEADER pSH)
1253{
1254 PIMAGE_IMPORT_DESCRIPTOR pID;
1255 PIMAGE_SECTION_HEADER pshID;
1256 PCHAR pSectionID = NULL;
1257 PIMAGE_SECTION_HEADER pshExtra = NULL;
1258 PCHAR pSectionExtra = NULL;
1259 PIMAGE_OPTIONAL_HEADER pOH;
1260
1261 int i,j;
1262 BOOL fBorland = 0;
1263 int cModules;
1264 char *pszModules;
1265 char *pszCurModule;
1266 char *pszTmp;
1267 ULONG *pulImport;
1268 ULONG ulCurFixup;
1269 int Size;
1270
1271
1272 /* 1) get module names */
1273 if ((pshID = PEGetSectionHdrByImageDir(pSH, IMAGE_DIRECTORY_ENTRY_IMPORT)) == NO_ERROR)
1274 return FALSE;
1275
1276 pSectionID = (char*)PEReadSection(pshID); //remeber to free this
1277 ltassert(pSectionID != NULL);
1278
1279 pID = (PIMAGE_IMPORT_DESCRIPTOR)(
1280 (ULONG)pSectionID
1281 + PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
1282 - pshID->VirtualAddress
1283 );
1284 ltasserthp2(pID, free(pSectionID))
1285
1286 //calc size of module list
1287 i = Size = cModules = 0;
1288 while (pID[i].Name != 0)
1289 {
1290 //test RVA inside ID-Section
1291 if (pID[i].Name >= pshID->VirtualAddress && pID[i].Name < pshID->VirtualAddress + max(pshID->Misc.VirtualSize, pshID->SizeOfRawData))
1292 pszTmp = (char*)(pID[i].Name - pshID->VirtualAddress + pSectionID);
1293 else
1294 {
1295 //is the "Extra"-section already found or do we have to find it?
1296 if (pshExtra == 0 || pID[i].Name < pshExtra->VirtualAddress || pID[i].Name >= pshExtra->VirtualAddress + max(pshExtra->Misc.VirtualSize, pshExtra->SizeOfRawData))
1297 {
1298 if ((pshExtra = PEGetSectionHdrByRVA(pSH, pID[i].Name)) != NULL)
1299 {
1300 if (pSectionExtra != NULL) free(pSectionExtra);
1301 if ((pSectionExtra = (char*)PEReadSection(pshExtra)) == NULL)
1302 {
1303 free(pSectionID);
1304 return FALSE;
1305 }
1306 }
1307 else
1308 {
1309 free(pSectionID);
1310 if (pSectionExtra != NULL) free(pSectionExtra);
1311 return FALSE;
1312 }
1313 }
1314 pszTmp = (char*)(pID[i].Name - pshExtra->VirtualAddress + pSectionExtra);
1315 }
1316 Size += strlen(pszTmp) + 1;
1317 i++;
1318 cModules++;
1319 }
1320
1321 pszModules = (char*)malloc(Size);
1322 assert(pszModules != NULL);
1323 j = 0;
1324 for (i = 0; i < cModules; i++)
1325 {
1326 //test RVA inside ID-Section
1327 if (pID[i].Name >= pshID->VirtualAddress && pID[i].Name < pshID->VirtualAddress + max(pshID->Misc.VirtualSize, pshID->SizeOfRawData))
1328 pszTmp = (char*)(pID[i].Name - pshID->VirtualAddress + pSectionID);
1329 else
1330 {
1331 //is the "Extra"-section already found or do we have to find it?
1332 if (pshExtra == 0 || pID[i].Name < pshExtra->VirtualAddress || pID[i].Name >= pshExtra->VirtualAddress + max(pshExtra->Misc.VirtualSize, pshExtra->SizeOfRawData))
1333 {
1334 if ((pshExtra = PEGetSectionHdrByRVA(pSH, pID[i].Name)) != NULL)
1335 {
1336 if (pSectionExtra != NULL) free(pSectionExtra);
1337 if ((pSectionExtra = (char*)PEReadSection(pshExtra)) == NULL)
1338 {
1339 free(pSectionID);
1340 return FALSE;
1341 }
1342 }
1343 else
1344 {
1345 free(pSectionID);
1346 if (pSectionExtra != NULL) free(pSectionExtra);
1347 return FALSE;
1348 }
1349 }
1350 pszTmp = (char*)(pID[i].Name - pshExtra->VirtualAddress + pSectionExtra);
1351 }
1352 strcpy(pszModules+j, pszTmp);
1353 j += strlen(pszTmp) + 1;
1354 }
1355 cout << endl;
1356 if (fBorland)
1357 cout << "Borland-styled PE-File." << endl;
1358 //Store modules
1359 cout << cModules << " imported Modules: " << endl;
1360 StoreImportModules(pszModules, cModules);
1361
1362
1363 /* 2) functions */
1364 pszCurModule = pszModules;
1365 pOH = &PEHdrs.OptionalHeader;
1366 for (i = 0; i < cModules; i++)
1367 {
1368 cout << "Module " << pszCurModule << endl;
1369 // a) check that OriginalFirstThunk not is 0 and look for Borland-styled PE
1370 if (i == 0)
1371 {
1372 //heavy borland-style test - assume array of thunks is within that style does not change
1373 if ((ULONG)pID[i].u.OriginalFirstThunk == 0
1374 ////|| (ULONG)pID[i].OriginalFirstThunk < pOH->SizeOfImage
1375 || (ULONG)pID[i].u.OriginalFirstThunk < pshID->VirtualAddress
1376 || (ULONG)pID[i].u.OriginalFirstThunk >= pshID->VirtualAddress + max(pshID->Misc.VirtualSize, pshID->SizeOfRawData)
1377 || (ULONG)pID[i].u.OriginalFirstThunk >= pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
1378 && (ULONG)pID[i].u.OriginalFirstThunk < sizeof(*pID)*cModules + pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
1379 // && (ULONG)pID[i].OriginalFirstThunk < pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size + pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
1380 )
1381 fBorland = TRUE;
1382 }
1383
1384 //light borland-style test
1385 if (pID[i].u.OriginalFirstThunk == 0 || fBorland)
1386 pulImport = (ULONG*)pID[i].FirstThunk;
1387 else
1388 pulImport = (ULONG*)pID[i].u.OriginalFirstThunk;
1389
1390 // b) check if RVA ok
1391 if (!(pulImport > 0 && (ULONG)pulImport < pOH->SizeOfImage))
1392 {
1393 cout << "Invalid RVA " << hex((ULONG)pulImport) << endl;
1394 break;
1395 }
1396
1397 // check section
1398 if ((ULONG)pulImport < pshID->VirtualAddress || (ULONG)pulImport >= pshID->VirtualAddress + max(pshID->Misc.VirtualSize, pshID->SizeOfRawData))
1399 {
1400 if (pshExtra == 0 || (ULONG)pulImport < pshExtra->VirtualAddress || (ULONG)pulImport >= pshExtra->VirtualAddress + max(pshExtra->Misc.VirtualSize, pshExtra->SizeOfRawData))
1401 {
1402 if ((pshExtra = PEGetSectionHdrByRVA(pSH, (ULONG)pulImport)) != NULL)
1403 {
1404 if (pSectionExtra != NULL) free(pSectionExtra);
1405 if ((pSectionExtra = (char*)PEReadSection(pshExtra)) == NULL)
1406 {
1407 free(pSectionID);
1408 cout << "warning: could not read section for Thunk RVA " << hex((ULONG)pulImport) << endl;
1409 return FALSE;
1410 }
1411 }
1412 else
1413 {
1414 free(pSectionID);
1415 if (pSectionExtra != NULL) free(pSectionExtra);
1416 cout << "warning: could not find section for Thunk RVA " << hex((ULONG)pulImport) << endl;
1417 return FALSE;
1418 }
1419 }
1420 pulImport = (PULONG)((ULONG)pulImport - pshExtra->VirtualAddress + (ULONG)pSectionExtra);
1421 }
1422 else
1423 pulImport = (PULONG)((ULONG)pulImport - pshID->VirtualAddress + (ULONG)pSectionID);
1424 j = 0;
1425 ulCurFixup = (ULONG)pID[i].FirstThunk + pOH->ImageBase;
1426 while (pulImport[j] != 0)
1427 {
1428 if (pulImport[j] & IMAGE_ORDINAL_FLAG)
1429 { //ordinal
1430 cout.setf(ios::hex, ios::basefield);
1431 cout << "0x" << ulCurFixup << " Imported function " << pszCurModule << "@" << (pulImport[j] & ~IMAGE_ORDINAL_FLAG) << endl;
1432 cout.setf(ios::dec, ios::basefield);
1433 StoreImportByOrd(i, pulImport[j] & ~IMAGE_ORDINAL_FLAG, ulCurFixup);
1434 }
1435 else
1436 { //name
1437 //check
1438 if (pulImport[j] < pshID->VirtualAddress || pulImport[j] >= pshID->VirtualAddress + max(pshID->Misc.VirtualSize, pshID->SizeOfRawData))
1439 {
1440 if (pshExtra == 0 || pulImport[j] < pshExtra->VirtualAddress || pulImport[j] >= pshExtra->VirtualAddress + max(pshExtra->Misc.VirtualSize, pshExtra->SizeOfRawData))
1441 {
1442 if ((pshExtra = PEGetSectionHdrByRVA(pSH, (ULONG)pulImport)) != NULL)
1443 {
1444 if (pSectionExtra != NULL) free(pSectionExtra);
1445 if ((pSectionExtra = (char*)PEReadSection(pshExtra)) == NULL)
1446 {
1447 free(pSectionID);
1448 cout << "warning: could not read section for Import Name RVA " << hex(pulImport[j]) << endl;
1449 break; //return FALSE;
1450 }
1451 }
1452 else
1453 {
1454 free(pSectionID);
1455 if (pSectionExtra != NULL) free(pSectionExtra);
1456 cout << "warning: could not find section for Thunk RVA " << hex(pulImport[j]) << endl;
1457 break; //return FALSE;
1458 }
1459 }
1460 pulImport[j] += (ULONG)pSectionExtra - pshExtra->VirtualAddress;
1461 }
1462 else
1463 pulImport[j] += (ULONG)pSectionID - pshID->VirtualAddress;
1464
1465 cout.setf(ios::hex, ios::basefield);
1466 cout << "0x" << ulCurFixup << " Imported function " << (char*)(pulImport[j] + 2) << endl;
1467 cout.setf(ios::dec, ios::basefield);
1468 StoreImportByName(pszCurModule, i, (char *)(pulImport[j] + 2), ulCurFixup);
1469 }
1470 ulCurFixup += sizeof(IMAGE_THUNK_DATA);
1471 j++;
1472 }
1473
1474 pszCurModule += strlen(pszCurModule) + 1;
1475 cout << endl;
1476 }//for (i = 0; i < cModules; i++)
1477
1478 free(pszModules);
1479 return TRUE;
1480}
1481
1482
1483
1484/**
1485 * Processes the resources in the PE-file.
1486 * @param pSectionTable Pointer to sectiontable
1487 * @return TRUE on success. FALSE on failure.
1488 */
1489BOOL LXFile::ProcessResources(PIMAGE_SECTION_HEADER pSectionTable)
1490{
1491 /* RESOURCES */
1492 PIMAGE_SECTION_HEADER pRSH;
1493 PIMAGE_RESOURCE_DIRECTORY prdRoot, prdType;
1494 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
1495 PIMAGE_RESOURCE_DATA_ENTRY pData;
1496 ULONG offType;
1497 ULONG offRoot;
1498 int i,j,id,rc = TRUE;
1499
1500 pRSH = PEGetSectionHdrByName(pSectionTable, ".rsrc"); // maybe we should check the ImageDirectory instead?
1501 if (pRSH != NULL)
1502 {
1503
1504 cout << "Resource section: " << endl;
1505 cout << "Raw data size: " << hex(pRSH->SizeOfRawData) << endl;
1506 cout << "Virtual Address: " << hex(pRSH->VirtualAddress) << endl;
1507 cout << "Pointer to raw data: " << hex(pRSH->PointerToRawData) << endl;
1508 cout << "Section flags: " << hex(pRSH->Characteristics) << endl << endl;
1509
1510 /* get root directory of resource tree */
1511 offRoot = PEImageDirectoryOffset(pSectionTable, IMAGE_DIRECTORY_ENTRY_RESOURCE);
1512
1513 if (offRoot != 0)
1514 {
1515
1516 /* allocate and read resource section */
1517 if (PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress != pRSH->VirtualAddress)
1518 cout << "Info: Resource directory does not start at beginning of .rsrc section." << endl;
1519 /*alloc*/
1520 //prdRoot = (PIMAGE_RESOURCE_DIRECTORY)malloc(max(PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size, min(pRSH->VirtualAddress, pRSH->SizeOfRawData)));
1521 prdRoot = (PIMAGE_RESOURCE_DIRECTORY)malloc(PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size);
1522 ltassert(prdRoot != NULL);
1523 /*read*/
1524 rc = _ldrRead(
1525 hFile,
1526 offRoot,
1527 prdRoot,
1528 0,
1529 //max(PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size, min(pRSH->VirtualAddress, pRSH->SizeOfRawData)),
1530 PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size, //until this crashes keep it!
1531 NULL
1532 );
1533 if (rc != NULL)
1534 {
1535 cout << "error while reading resourceses, rc=" << rc <<endl;
1536 free(prdRoot);
1537 return FALSE;
1538 }
1539
1540 cout << "Resources: " << endl;
1541 ltassert2(SetResourceSize(max(pRSH->Misc.VirtualSize, pRSH->SizeOfRawData)), free(prdRoot));
1542 ltassert2(SetNrResources(PEGetNumberOfResources(prdRoot)), free(prdRoot)); //these functions allocate much memory!
1543
1544 /* set pointer to first resource type entry */
1545 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
1546 ltasserthp2(prde, free(prdRoot));
1547 rc = TRUE;
1548 //SvL: Store all resource ids so we can safely allocate unique ids for name ids
1549 for ( i = 0; i < prdRoot->NumberOfNamedEntries + prdRoot->NumberOfIdEntries && rc; i++)
1550 {
1551 /* locate directory or each resource type */
1552 offType = prde->u2.OffsetToData;
1553 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (offType & ~0x80000000));
1554 ltasserthp2(prdType, free(prdRoot);OS2Icon::DestroyAll();OS2Cursor::DestroyAll());
1555 if (i < prdRoot->NumberOfNamedEntries)
1556 {
1557 //SvL: 30-10-'97, high bit is set, so clear to get real offset
1558 prde->u1.Name &= ~0x80000000;
1559 char *resname = UnicodeToAscii(*(WCHAR *)((int)prdRoot + (int)prde->u1.Name), (WCHAR *)((int)prdRoot + (int)prde->u1.Name + sizeof(WCHAR))); // first word = string length
1560
1561 for (j = 0; j < (sizeof(ResTypes) / sizeof(ResTypes[0])); j++)
1562 {
1563 if (strcmp(resname, ResTypes[j]) == 0)
1564 break;
1565 }
1566 if (j == (sizeof(ResTypes) / sizeof(ResTypes[0])))
1567 id = NTRT_RCDATA;
1568 else
1569 id = j;
1570 }
1571 else
1572 id = prde->u1.Id;
1573
1574 ltassert2(offType & 0x80000000, free(prdRoot);OS2Icon::DestroyAll();OS2Cursor::DestroyAll());
1575 rc = StoreIdResSubDir(prdType, 1, prdRoot, pRSH->VirtualAddress, id, 0);
1576
1577 /* increment to next entry */
1578 prde++;
1579 }
1580
1581 /* set pointer to first resource type entry */
1582 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
1583 ltasserthp2(prde, free(prdRoot);OS2Icon::DestroyAll();OS2Cursor::DestroyAll());
1584
1585 /* loop through all resource directory entry types */
1586 //eerste level -> types
1587 //tweede level -> names
1588 //derde level -> language
1589 cout << "Name entries: " << endl;
1590 cout << "ID entries: " << endl;
1591 for (i=0; i < prdRoot->NumberOfNamedEntries+prdRoot->NumberOfIdEntries && rc; i++)
1592 {
1593 /* locate directory or each resource type */
1594 offType = prde->u2.OffsetToData;
1595 prdType = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (offType & ~0x80000000));
1596 ltasserthp2(prdType, free(prdRoot);OS2Icon::DestroyAll();OS2Cursor::DestroyAll());
1597
1598 if (i<prdRoot->NumberOfNamedEntries)
1599 {
1600 //SvL: 30-10-'97, high bit is set, so clear to get real offset
1601 prde->u1.Name &= ~0x80000000;
1602 char *resname = UnicodeToAscii(*(WCHAR *)((int)prdRoot + (int)prde->u1.Name), (WCHAR *)((int)prdRoot + (int)prde->u1.Name + sizeof(WCHAR))); // first word = string length
1603
1604 cout << "Type " << resname << endl;
1605 for (j=0; j < (sizeof(ResTypes) / sizeof(ResTypes[0])); j++)
1606 {
1607 if (strcmp(resname, ResTypes[j]) == 0)
1608 break;
1609 }
1610 if (j == (sizeof(ResTypes) / sizeof(ResTypes[0])))
1611 id = NTRT_RCDATA;
1612 else
1613 id = j;
1614 }
1615 else
1616 {
1617 if (prde->u1.Id < (sizeof(ResTypes) / sizeof(ResTypes[0])))
1618 cout << "Type " << ResTypes[prde->u1.Id] << endl;
1619 else
1620 cout << "Custom Type " << prde->u1.Id << endl;
1621 id = prde->u1.Id;
1622 }
1623
1624 if (offType & 0x80000000)
1625 {//subdirectory?
1626 rc = ProcessResSubDir(prdType, 1, prdRoot, pRSH->VirtualAddress, id, 0);
1627 }
1628 else
1629 {
1630 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType;
1631 cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
1632 cout << "Resource Data entry of size " << hex(pData->Size) << endl;
1633 cout << "Resource Data RVA " << hex(pData->OffsetToData) << endl;
1634 cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
1635 ltassert2(offType & 0x80000000, free(prdRoot);OS2Icon::DestroyAll();OS2Cursor::DestroyAll());
1636 }
1637
1638 /* increment to next entry */
1639 prde++;
1640 ltasserthp2(prde, free(prdRoot);OS2Icon::DestroyAll();OS2Cursor::DestroyAll());
1641 }
1642
1643 free(prdRoot);
1644 }
1645 OS2Icon::DestroyAll();
1646 OS2Cursor::DestroyAll();
1647 }
1648
1649
1650 if (rc)
1651 {//if all went ok...
1652 rc = SaveConvertedNames();
1653
1654 /* freeing now unused memory */
1655 free(cvtname);
1656 cvtname = NULL;
1657 free(resids);
1658 resids = NULL;
1659 free(orgrestable);
1660 orgrestable = NULL;
1661
1662
1663 //done with resources
1664 if (nrresources)
1665 {
1666 ResSection.virtualsize = ResSection.curoff;
1667 ResSection.rawsize = ResSection.curoff;
1668 }
1669
1670
1671 /* do some resizing */
1672 if ((void*)ResSection.rawdata != NULL && rc)
1673 {
1674 void *pTmp;
1675 cout << "resizing: " << _msize((void*)ResSection.rawdata) << " ?? " << ResSection.rawsize << endl;
1676 pTmp = realloc((void*)ResSection.rawdata, ResSection.rawsize);
1677 if (pTmp != NULL)
1678 ResSection.rawdata = (ULONG)pTmp;
1679 else
1680 cout << "LXFile::PrepareLX: warning - could not reallocate ResSection.rawdata." << endl;
1681 }
1682 }
1683
1684 return rc;
1685}
1686
1687
1688
1689/**
1690 * Check if an valid PE-Header is presented.
1691 * @param pHdr Is a pointer to the PE Signature and the following Fileheader.<br>
1692 * Size: 196 bytes (size of an LX-header)
1693 */
1694BOOL LXFile::isPEFile(PIMAGE_SIG_FILE_HEADER pHdr)
1695{
1696 ltassert(pHdr != NULL);
1697
1698 /*signature*/
1699 if (pHdr->Signature != IMAGE_NT_SIGNATURE)
1700 {
1701 //kprintf(("LXFile::isPEFile: Invalid PE signature\n"));
1702 return FALSE;
1703 }
1704
1705 if (!(pHdr->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE))
1706 {
1707 kprintf(("LXFile::isPEFile: Not a valid PE file!\n"));
1708 return FALSE;
1709 }
1710
1711 if (pHdr->FileHeader.Machine != IMAGE_FILE_MACHINE_I386)
1712 {
1713 kprintf(("LXFile::isPEFile: Not i386 code.\n"));
1714 return FALSE;
1715 }
1716
1717 if (pHdr->FileHeader.Characteristics & IMAGE_FILE_SYSTEM)
1718 {
1719 kprintf(("LXFile::isPEFile: Sorry. Can't convert file system drivers.\n"));
1720 return FALSE;
1721 }
1722
1723 if (pHdr->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER))
1724 {
1725 kprintf(("LXFile::isPEFile: Incorrect optional header size(%d).\n", pHdr->FileHeader.SizeOfOptionalHeader));
1726 return FALSE;
1727 }
1728
1729 return TRUE;
1730}
1731
1732
1733
1734/**
1735 * Query if psh is a importdata section.
1736 * @param psh Pointer to sectionheader.
1737 * @return TRUE if psh is an importdata section else FALSE.
1738 */
1739BOOL LXFile::PEIsImportDataSection(PIMAGE_SECTION_HEADER psh)
1740{
1741 DWORD VAImageDir;
1742
1743 /* locate specific image directory's relative virtual address */
1744 VAImageDir = PEHdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
1745
1746 return psh->VirtualAddress <= VAImageDir && psh->VirtualAddress + psh->SizeOfRawData > VAImageDir;
1747}
1748
1749
1750
1751/**
1752 * Get offset to section(data) - by a Data Directory entry.
1753 * @param psh Pointer to Section Table.
1754 * @param dwIMAGE_DIRECTORY Datadirectory index.
1755 * @return On success a offset to the section data, else NULL.
1756 */
1757DWORD LXFile::PEImageDirectoryOffset(PIMAGE_SECTION_HEADER psh, DWORD dwIMAGE_DIRECTORY)
1758{
1759 int i = 0;
1760 DWORD VAImageDir;
1761
1762 /* must be 0 thru (NumberOfRvaAndSizes-1) */
1763 if (dwIMAGE_DIRECTORY >= PEHdrs.OptionalHeader.NumberOfRvaAndSizes)
1764 return NULL;
1765
1766 /* locate specific image directory's relative virtual address */
1767 VAImageDir = PEHdrs.OptionalHeader.DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress;
1768
1769 /* locate section containing image directory */
1770 while (i++ < nSections)
1771 {
1772 if (psh->VirtualAddress <= VAImageDir && psh->VirtualAddress + psh->SizeOfRawData > VAImageDir)
1773 break;
1774 psh++;
1775 }
1776
1777 if (i > nSections)
1778 return NULL;
1779
1780 /* return image directory file offset */
1781 return (VAImageDir - psh->VirtualAddress + psh->PointerToRawData);
1782}
1783
1784
1785
1786/**
1787 * Get pointer to section header - by a Data Directory entry.
1788 * @param psh Pointer to Section Table.
1789 * @param dwIMAGE_DIRECTORY Datadirectory index.
1790 * @return On success a pointer to the sectionheader, else NULL pointer.
1791 */
1792PIMAGE_SECTION_HEADER LXFile::PEGetSectionHdrByImageDir(PIMAGE_SECTION_HEADER psh, DWORD dwIMAGE_DIRECTORY)
1793{
1794 int i = 0;
1795 DWORD VAImageDir;
1796
1797 /* must be 0 thru (NumberOfRvaAndSizes-1) */
1798 if (dwIMAGE_DIRECTORY >= PEHdrs.OptionalHeader.NumberOfRvaAndSizes)
1799 return FALSE;
1800
1801 /* locate specific image directory's relative virtual address */
1802 VAImageDir = (ULONG)PEHdrs.OptionalHeader.DataDirectory[dwIMAGE_DIRECTORY].VirtualAddress;
1803
1804 /* locate section containing image directory */
1805 while (i++ < nSections)
1806 {
1807 if (psh->VirtualAddress <= VAImageDir && psh->VirtualAddress + psh->SizeOfRawData > VAImageDir)
1808 break;
1809 psh++;
1810 }
1811 if (i > nSections)
1812 return NULL;
1813
1814 return psh;
1815}
1816
1817
1818
1819/**
1820 * Get pointer to section header - by the name of the section.
1821 * @param psh Pointer to Section Table.
1822 * @param szSection Name of the section to find the header of.
1823 * @return On success a pointer to the sectionheader, else NULL pointer.
1824 */
1825PIMAGE_SECTION_HEADER LXFile::PEGetSectionHdrByName(IMAGE_SECTION_HEADER *psh, char *szSection)
1826{
1827 int i;
1828
1829 /* find the section by name */
1830 i = 0;
1831 while (i < nSections && strcmp(psh[i].Name, szSection) != 0)
1832 i++;
1833
1834 if (i < nSections)
1835 return &psh[i];
1836 else
1837 return NULL;
1838}
1839
1840
1841
1842/**
1843 * Get pointer to section header - by a RVA in that section.
1844 * @param psh Pointer to Section Table.
1845 * @param rva RVA address into a section.
1846 * @return On success a pointer to the sectionheader, else NULL pointer.
1847 */
1848PIMAGE_SECTION_HEADER LXFile::PEGetSectionHdrByRVA(IMAGE_SECTION_HEADER *psh, ULONG rva)
1849{
1850 int i;
1851
1852 /* find the section by name */
1853 i = 0;
1854 while (i < nSections
1855 && !(rva >= psh[i].VirtualAddress && rva < psh[i].VirtualAddress + max(psh[i].Misc.VirtualSize, psh[i].SizeOfRawData))
1856 )
1857 i++;
1858
1859 if (i < nSections)
1860 return &psh[i];
1861 else
1862 return NULL;
1863}
1864
1865
1866
1867/**
1868 * Read Section based on section header.
1869 * @param pSH Pointer to section header of the section to be read.
1870 * @return Pointer to Section data on success, else NULL pointer.
1871 * @remark <b>Do not forget to free the return pointer!</b>
1872 */
1873PVOID LXFile::PEReadSection(PIMAGE_SECTION_HEADER pSH)
1874{
1875 PCHAR pSection = NULL;
1876 ULONG rc;
1877 ULONG ulRSize; //Rawsize
1878 ULONG ulVSize; //Virtualsize
1879
1880 if(pSH != NULL)
1881 {
1882 //warning: Watcom sets .idata-sections virtual size to 0
1883 ulRSize = minnotnull(pSH->SizeOfRawData, pSH->Misc.VirtualSize);
1884 ulVSize = max(pSH->SizeOfRawData, pSH->Misc.VirtualSize);
1885
1886 pSection = (char*)malloc(ulVSize);
1887 ltassert(pSection != NULL);
1888
1889 //pad to end of section
1890 memset(pSection + ulRSize, 0, ulVSize - ulRSize);
1891
1892 rc = _ldrRead(
1893 hFile,
1894 pSH->PointerToRawData,
1895 pSection,
1896 0,
1897 ulRSize,
1898 NULL
1899 );
1900
1901 if (rc != NO_ERROR)
1902 {
1903 //warning: Sectionname is not necessarily null terminated (if 8 chars long..)
1904 char szName[IMAGE_SIZEOF_SHORT_NAME+1];
1905 memset(SSToDS(szName),0,IMAGE_SIZEOF_SHORT_NAME+1);
1906 strncpy((char*)SSToDS(szName), pSH->Name, 8);
1907 cout << "error while reading section " << szName << ", rc=" << rc << endl;
1908 free(pSection);
1909 pSection = NULL;
1910 }
1911 }
1912
1913 return (PVOID)pSection;
1914}
1915
1916
1917
1918/**
1919 * Determine the total number of resources in the section
1920 * @param prdRoot Pointer to root node in the resource directory.
1921 * @return Number of resources in the directory.
1922 */
1923int LXFile::PEGetNumberOfResources(PIMAGE_RESOURCE_DIRECTORY prdRoot)
1924{
1925 PIMAGE_RESOURCE_DIRECTORY prdType;
1926 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
1927 int nCnt=0, i, j, id;
1928 char *resname;
1929
1930 /* set pointer to first resource type entry */
1931 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((ULONG)prdRoot + sizeof (IMAGE_RESOURCE_DIRECTORY));
1932
1933 /* loop through all resource directory entry types */
1934 for ( i = 0; i < prdRoot->NumberOfNamedEntries + prdRoot->NumberOfIdEntries; i++)
1935 {
1936 ltasserthp(prde);
1937
1938 /* locate directory or each resource type */
1939 prdType = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)prdRoot + (prde->u2.OffsetToData & ~0x80000000));
1940 ltasserthp(prdType);
1941
1942 if (i < prdRoot->NumberOfNamedEntries)
1943 {
1944 //SvL: 30-10-'97, high bit is set, so clear to get real offset
1945 prde->u1.Name &= ~0x80000000;
1946 for (j = 0; j < (sizeof(ResTypes) / sizeof(ResTypes[0])); j++)
1947 {
1948 resname = UnicodeToAscii( *(WCHAR *)((ULONG)prdRoot + (ULONG)prde->u1.Name), (WCHAR *)((ULONG)prdRoot + (ULONG)prde->u1.Name + sizeof(WCHAR))); // first word = string length
1949 if (strcmp(resname, ResTypes[j]) == 0)
1950 break;
1951 }
1952 if (j == (sizeof(ResTypes) / sizeof(ResTypes[0])))
1953 {
1954 //SvL: 30-10-'97, not found = custom resource type (correct?)
1955 id = NTRT_RCDATA;
1956 }
1957 else
1958 id = j;
1959 }
1960 else
1961 id = prde->u1.Id;
1962
1963
1964 /* increment count of name'd and ID'd resources in directory */
1965 if (id == NTRT_STRING)
1966 {
1967 //String tables can contain up to 16 individual resources!
1968 nCnt += prdType->NumberOfNamedEntries*16 + prdType->NumberOfIdEntries*16;
1969 }
1970 else
1971 {
1972 //Only icon groups are stored as resources in the LX file
1973 //Icon groups contain one or more icons
1974 if (id != NTRT_ICON)
1975 nCnt += prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries;
1976 }
1977 /* increment to next entry */
1978 prde++;
1979 }
1980
1981 return nCnt;
1982}
1983
1984
1985
1986/**
1987 * @remark Have similar function in pe.cpp - remeber to update both.<br>
1988 * No support for multiple languages; just select the first one
1989 * present and ignore the rest
1990 */
1991BOOL LXFile::ProcessResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType, int level,
1992 PIMAGE_RESOURCE_DIRECTORY prdRoot, int VirtualAddress,
1993 int type, int id)
1994{
1995 PIMAGE_RESOURCE_DIRECTORY prdType2;
1996 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
1997 PIMAGE_RESOURCE_DIR_STRING_U pstring;
1998 PIMAGE_RESOURCE_DATA_ENTRY pData;
1999 ULONG offType2;
2000 int i;
2001 BOOL rc = TRUE;;
2002
2003 switch (level)
2004 {
2005 case 1:
2006 cout << "Names.." << endl;
2007 break;
2008 case 2:
2009 cout << "Language.." << endl;
2010 break;
2011 }
2012 cout << "Subdir with " << prdType->NumberOfNamedEntries << " Name entries" << endl;
2013 cout << "Subdir with " << prdType->NumberOfIdEntries << " id entries" << endl;
2014
2015 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
2016 for ( i = 0; i < prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries && rc; i++)
2017 {
2018 ltasserthp(prde);
2019
2020 /* locate directory or each resource type */
2021 offType2 = prde->u2.OffsetToData;
2022 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (offType2 & ~0x80000000));
2023 ltasserthp(prdType2);
2024
2025 if (i < prdType->NumberOfNamedEntries)
2026 {//name or id entry?
2027 if (prde->u1.s.NameIsString) //unicode directory string /*PLF Sat 97-06-21 22:30:35*/
2028 prde->u1.Name &= ~0x80000000;
2029 pstring = (PIMAGE_RESOURCE_DIR_STRING_U)((int)prdRoot + (int)prde->u1.Name);
2030 ltasserthp(pstring);
2031 cout << "Name = " << UnicodeToAscii(pstring->Length, pstring->NameString) << endl;
2032 if (level == 1)
2033 {
2034 id = ConvertNametoId(UnicodeToAscii(pstring->Length, pstring->NameString));
2035 }
2036 }
2037 else
2038 {
2039 cout << "Id " << prde->u1.Id << endl;
2040 if (level == 1)
2041 id = prde->u1.Id;
2042 }
2043
2044 if (offType2 & 0x80000000)
2045 {//subdirectory?
2046 rc = ProcessResSubDir(prdType2, 2, prdRoot, VirtualAddress, type, id);
2047 }
2048 else
2049 {
2050 pData = (PIMAGE_RESOURCE_DATA_ENTRY)prdType2;
2051 cout << "Resource Data entry of size " << hex(pData->Size) << endl;
2052 cout << "Resource Data RVA " << hex(pData->OffsetToData - VirtualAddress) << endl;
2053 if (pData->Size)
2054 {//winamp17 winzip archive has resource with size 0
2055 switch (type)
2056 {
2057 case NTRT_MENU:
2058 rc = ShowMenu(*this, id, (MenuHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size, 437);
2059 break;
2060 case NTRT_ICON:
2061 new OS2Icon(id, (WINBITMAPINFOHEADER *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
2062 rc = OS2Icon::GetIcon(id) != NULL;
2063 break;
2064 case NTRT_BITMAP:
2065 //KSO Oct 8 1998: testing
2066 rc = ShowBitmap(*this, id, (WINBITMAPINFOHEADER *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
2067 /*rc = StoreResource(id, RT_BITMAP, pData->Size + ((int)prdRoot + pData->OffsetToData - VirtualAddress) - (int)pData,
2068 (char*)pData); */
2069 break;
2070 case NTRT_GROUP_ICON:
2071 rc = ShowGroupIcon(*this, id, (IconHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
2072 break;
2073 case NTRT_CURSOR:
2074 new OS2Cursor(id, (CursorComponent *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
2075 rc = OS2Cursor::GetCursor(id) != NULL;
2076 break;
2077 case NTRT_GROUP_CURSOR:
2078 rc = ShowGroupCursor(*this, id, (CursorHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
2079 break;
2080 case NTRT_DIALOG:
2081 rc = ShowDialog(*this, id, (DialogBoxHeader *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size, 437);
2082 break;
2083 case NTRT_VERSION:
2084 //Store version resource as OS/2 RT_RCDATA resource
2085 //to retrieve the original for win32's version apis
2086 //TODO: Only supports one version resource (who would want to use more??)
2087 SetVersionResourceId(id);
2088 case NTRT_RCDATA:
2089 rc = ShowRCData(*this, id, (char *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
2090 break;
2091 case NTRT_STRING:
2092 //String format: tables of 16 strings stored as one resource
2093 //upper 12 bits of resource id passed by user determines block (res id)
2094 //lower 4 bits are an index into the string table
2095 //Best solution is to split the strings up and store them as RCDATA
2096 rc = ShowStrings(*this, id, (char *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size, 437);
2097 break;
2098 case NTRT_ACCELERATORS:
2099 rc = ShowAccelerator(*this, id, (WINACCEL *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
2100 break;
2101 default:
2102 cout << "!!Unsupported resource type!! : " << type << endl;
2103 //Just save it as rcdata
2104 rc = ShowRCData(*this, id, (char *)((char *)prdRoot + pData->OffsetToData - VirtualAddress), pData->Size);
2105 break;
2106 }//switch
2107 }//if size > 0
2108 }
2109 if (level == 2) break; //only support one language!
2110
2111 prde++;
2112 cout << endl;
2113 }
2114
2115 return rc;
2116}
2117
2118
2119
2120/**
2121 * @remark Have similar function in pe.cpp - remeber to update both.
2122 */
2123BOOL LXFile::StoreIdResSubDir(PIMAGE_RESOURCE_DIRECTORY prdType, int level,
2124 PIMAGE_RESOURCE_DIRECTORY prdRoot, int VirtualAddress,
2125 int type, int id)
2126{
2127 PIMAGE_RESOURCE_DIRECTORY prdType2;
2128 PIMAGE_RESOURCE_DIRECTORY_ENTRY prde;
2129 ULONG offType2;
2130 int i, j;
2131
2132
2133 prde = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)((DWORD)prdType + sizeof (IMAGE_RESOURCE_DIRECTORY));
2134
2135 for (i = 0; i < prdType->NumberOfNamedEntries + prdType->NumberOfIdEntries; i++)
2136 {
2137 ltasserthp(prde);
2138
2139 /* locate directory or each resource type */
2140 offType2 = prde->u2.OffsetToData;
2141 prdType2 = (PIMAGE_RESOURCE_DIRECTORY)((int)prdRoot + (offType2 & ~0x80000000));
2142 ltasserthp(prdType2);
2143
2144 if (i >= prdType->NumberOfNamedEntries)
2145 {//name or id entry?
2146 if (level == 1)
2147 id = prde->u1.Id;
2148 }
2149 else
2150 {
2151 prde++;
2152 continue; //skip name ids
2153 }
2154
2155 if (offType2 & 0x80000000)
2156 {//subdirectory?
2157 ltassert(StoreIdResSubDir(prdType2, 2, prdRoot, VirtualAddress, type, id));
2158 }
2159 else
2160 {
2161 if (type == NTRT_STRING)
2162 {
2163 for (j = 0; j < 16; j++)
2164 ltassert(StoreResourceId((id-1)*16+j));
2165 }
2166 else
2167 ltassert(StoreResourceId(id));
2168 }
2169 if (level == 2)
2170 break; //only support one language!
2171 prde++;
2172 }
2173 return TRUE;
2174}
2175
2176
2177
2178/**
2179 * Add 32-bit offset fixup.
2180 * @param address Address(RVA) of the fixup
2181 * @param pPage Pointer to the data of the page which address refers to.
2182 * @return NO_ERROR on success or ignorable errors.<br>
2183 * -1 on error<br>
2184 * -2 on crosspagefixup<br>
2185 * @remark This function replaces the AddOff32Fixup(int address) found in
2186 * LXHeaderSuper for LXFile - the one in LXHeaderSuper shall
2187 * <b>not</b> be used.<br>
2188 * Errors may be ignored - if you dare.
2189 */
2190int LXFile::AddOff32Fixup(int address, char *pPage)
2191{
2192 intfixup *pFixRec;
2193 int i;
2194 int no;
2195 int targetaddr;
2196 int rc = NO_ERROR;
2197
2198 pFixRec = &intfixuprec[nrintfixups];
2199
2200 cltassert(nrintfixups < nrofintfixups);
2201
2202 pFixRec->nr_stype = 0x07; //32 bits offset fixup
2203 pFixRec->nr_flags = 0x00 | 0x10 | 0x40; //internal fixup + 32 bits offset + 16 bits object nr
2204 pFixRec->r32_soff = (SHORT)(address & 0xFFF);
2205
2206 no = GetObjectNoByVA(address);
2207 if (no == -1)
2208 {
2209 cout << "Oops, fixup error 1...." << endl;
2210 return -1;
2211 }
2212 pFixRec->srcpage = (USHORT)GetPageNoByVA(address);
2213 pFixRec->srcobj = (USHORT)no;
2214
2215 /*KSO: get targetaddress*/
2216 targetaddr = *(int*)&pPage[pFixRec->r32_soff];
2217 //cout << " targetaddr: " << hex(targetaddr);
2218
2219 i = GetSectionIdxByVA(targetaddr);
2220 no = GetObjectNoByVA(targetaddr);
2221 if (i == -1 || no == -1)
2222 {
2223 cout << "Oops, fixup error 2....(" << (ULONG)targetaddr << ")" << endl;
2224 return -1;
2225 }
2226 pFixRec->targetaddr = targetaddr - PESection[i].address; //relatief
2227 pFixRec->targetobj = (USHORT)no;
2228
2229 //SvL: Check for fixups that cross page boundaries
2230 // If I read the lx doc right, you need to add two fixups in
2231 // this case, one for original page and one for original page + 1
2232 //KSO: Hopefully it will now work even if the last page contains such a fixup!
2233 if (pFixRec->r32_soff + 4 > PAGE_SIZE)
2234 {
2235 memcpy((char *)&crossedpage, (char *)pFixRec, sizeof(crossedpage));
2236 //crossed page boundary -> negative offset in next page
2237 crossedpage.r32_soff = (SHORT)((pFixRec->r32_soff & 0xFFF) - PAGE_SIZE);
2238 crossedpage.srcpage = pFixRec->srcpage+1;
2239 crossedpageaddress = (address + PAGE_SIZE) & ~0xFFF;
2240 fCrossed = TRUE;
2241 rc = -2;
2242 }
2243
2244 nrintfixups++;
2245
2246 return rc;
2247}
2248
2249
2250
2251/**
2252 * Adds the crosspagefixup if present.
2253 * @return NO_ERROR on success<br>
2254 * Something else on error.
2255 */
2256int LXFile::AddOff32FinishCrossPageFixup(void)
2257{
2258 intfixup *pFixRec;
2259 pFixRec = &intfixuprec[nrintfixups];
2260
2261 cltassert(nrintfixups < nrofintfixups);
2262
2263 //Check if we need to insert a crossed page fixup
2264 if (fCrossed == TRUE)
2265 {
2266 memcpy((char *)pFixRec, (char *)&crossedpage, sizeof(crossedpage));
2267 fCrossed = FALSE;
2268 crossedpageaddress = 0;
2269 nrintfixups++;
2270 pFixRec++;
2271 //cout << "CrossPageFixup: Finished." << endl;
2272 }
2273
2274 return NO_ERROR;
2275}
2276
2277
2278
2279#ifdef MIN
2280 #undef MIN
2281#endif
2282#define MIN(a,b) (a <= b ? a : b)
2283#define POST \
2284 ulOffset += ulToRead; \
2285 ulBytesToRead -= ulToRead; \
2286 pBuffer = (PVOID)((ULONG)pBuffer + ulToRead); \
2287 if (ulBytesToRead == 0) \
2288 { \
2289 *pulBytesRead -= ulBytesToRead; \
2290 return rc; \
2291 }
2292
2293
2294
2295/**
2296 * Read data from the virtual LX-file.
2297 * @param ulOffset Offset (into the virtual lx file) of the data to read
2298 * @param pBuffer Pointer to buffer where data is to be put.
2299 * @param ulBytesToRead Bytes to be read.
2300 * @param pulBytesRead Bytes actualy read. (Out)
2301 * @param ulFlag Flags from and to the _ldrRead call.
2302 * @return NO_ERROR if successful something else if not.
2303 * @remark Should only be called one time! Object should not be used if init(...) failes!
2304 */
2305ULONG LXFile::read(ULONG ulOffset, PVOID pBuffer, ULONG ulBytesToRead, PULONG pulBytesRead, ULONG ulFlag)
2306{
2307 ULONG ulToRead = 0;
2308 int i;
2309 int rc = NO_ERROR;
2310
2311 cltassert((ULONG)pulBytesRead > 0x10000);
2312 cltassert((ULONG)pBuffer > 0x10000);
2313
2314 cout.setf(ios::hex, ios::basefield);
2315 cout << "LXFile::read(0x" << ulOffset << ", 0x" << pBuffer << ", 0x" << ulBytesToRead << ");" << endl;
2316 cout.setf(ios::dec, ios::basefield);
2317
2318 if (!inited)
2319 {
2320 kprintf(("LXFile::read: object not inited!"));
2321 *pulBytesRead = 0;
2322 return ERROR_READ_FAULT;
2323 }
2324
2325 *pulBytesRead = ulBytesToRead;
2326
2327
2328 /* PRE LXHdr */
2329 if (ulOffset < ulPEOffset /*LXHEADER_OFFSET*/)
2330 {
2331 if (ulOffset == 0) cout << "LXFile::read: NEHdr at offset "<< hex(ulOffset) << endl ;
2332 /* the loader will never request this */
2333 if(!options.ourstub)
2334 {
2335 /* original stub */
2336 ulToRead = MIN(ulBytesToRead, ulPEOffset /*LXHEADER_OFFSET*/ - ulOffset);
2337 rc = _ldrRead(hFile, ulOffset, pBuffer, 0, ulToRead, NULL);
2338 }
2339 else
2340 { /* our stub */
2341 /* correct PE offset in MZ header */
2342 ulToRead = MIN(ulBytesToRead, LXHEADER_OFFSET - ulOffset);
2343 if (ulOffset < 0x40 )
2344 *(PULONG)(achDosHeader+0x3c) = ulPEOffset;
2345 memcpy(pBuffer,(PVOID)((ULONG)achDosHeader + ulOffset), ulToRead);
2346
2347 if (ulPEOffset > LXHEADER_OFFSET)
2348 {
2349 POST;
2350 ulToRead = MIN(ulBytesToRead,ulPEOffset - ulOffset);
2351 memset(pBuffer,0,ulToRead);
2352 }
2353 }
2354 POST;
2355 }
2356
2357
2358 /* LXHdr */
2359 if (!rc && ulOffset < ulPEOffset /*LXHEADER_OFFSET*/ + sizeof(e32_exe))
2360 {
2361 if (ulOffset == ulPEOffset /*LXHEADER_OFFSET*/) cout << "LXFile::read: LXHdr at offset "<< hex(ulOffset) << endl ;
2362 ulToRead = MIN(ulBytesToRead, sizeof(e32_exe)-(ulOffset - ulPEOffset /*LXHEADER_OFFSET*/));
2363 //printf("LXHdr: %d %d\n", ulOffset, ulToRead);
2364 memcpy(pBuffer,(PVOID)((ULONG)&LXHdr + ulOffset - ulPEOffset /*LXHEADER_OFFSET*/), ulToRead);
2365 POST;
2366 }
2367
2368
2369 /* the folowing section uses offset relative to linear EXE header */
2370 ulOffset -= ulPEOffset /*LXHEADER_OFFSET*/;
2371
2372
2373 /* Object Table */
2374 if (!rc && ulOffset < LXHdr.e32_objmap)
2375 {
2376 if (ulOffset == LXHdr.e32_objtab) cout << "LXFile::read: Object Table at offset "<< hex(ulOffset+ulPEOffset /*LXHEADER_OFFSET*/) << endl ;
2377 ulToRead = MIN(ulBytesToRead, LXHdr.e32_objmap - ulOffset);
2378 //cout << "LXFile::read: Object Table: ulOffset " << ulOffset << " ulToRead " << ulToRead << endl;
2379 memcpy(pBuffer, (PVOID)((ULONG)pObjectTable + ulOffset - LXHdr.e32_objtab), ulToRead);
2380 POST;
2381 }
2382
2383
2384 /* Object Page Table */
2385 if (!rc && ulOffset < LXHdr.e32_rsrctab)
2386 {
2387 if (ulOffset == LXHdr.e32_objmap) cout << "LXFile::read: Object Page Table at offset "<< hex(ulOffset+ulPEOffset /*LXHEADER_OFFSET*/) << endl ;
2388 ulToRead = MIN(ulBytesToRead, LXHdr.e32_rsrctab - ulOffset);
2389 //cout << "LXFile::read: Object Page Table: ulOffset " << ulOffset << " ulToRead " << ulToRead << endl;
2390 memcpy(pBuffer, (PVOID)((ULONG)pObjectPageTable + ulOffset - LXHdr.e32_objmap), ulToRead);
2391 POST;
2392 }
2393
2394
2395 /* Resource Table */
2396 if (!rc && ulOffset < LXHdr.e32_restab)
2397 {
2398 if (ulOffset == LXHdr.e32_rsrctab) cout << "LXFile::read: Resource Table at offset "<< hex(ulOffset+ulPEOffset /*LXHEADER_OFFSET*/) << endl ;
2399 ulToRead = MIN(ulBytesToRead, LXHdr.e32_restab - ulOffset);
2400 //cout << "LXFile::read: Resource Table: ulOffset " << ulOffset << " ulToRead " << ulToRead << " Relativ Offset "<< (void*)(ulOffset - LXHdr.e32_rsrctab) << endl;
2401 memcpy(pBuffer, (PVOID)((ULONG)os2resource + ulOffset - LXHdr.e32_rsrctab), ulToRead);
2402 POST;
2403 }
2404
2405
2406 /* Resident Name Table && Entry Table */
2407 if (!rc && ulOffset < LXHdr.e32_fpagetab)
2408 {
2409 if (ulOffset < LXHdr.e32_enttab)
2410 {
2411 if (ulOffset == LXHdr.e32_restab) cout << "LXFile::read: Resident Name Table at offset "<< hex(ulOffset+ulPEOffset /*LXHEADER_OFFSET*/) << endl ;
2412 ulToRead = MIN(ulBytesToRead, LXHdr.e32_enttab - ulOffset);
2413 //cout << "Resident Name Table: ulOffset " << (void*)(ulOffset + ulPEOffset /*LXHEADER_OFFSET*/) << " ulToRead " << MIN(ulBytesToRead, LXHdr.e32_enttab - ulOffset) << endl;
2414 memcpy(pBuffer, (PVOID)((ULONG)((exports!=NULL)?exports : modulename)+ulOffset-LXHdr.e32_restab) , ulToRead);
2415 POST
2416 }
2417
2418 if (ulOffset < LXHdr.e32_fpagetab && LXHdr.e32_restab < LXHdr.e32_enttab)
2419 {
2420 if (ulOffset == LXHdr.e32_enttab) cout << "LXFile::read: Entry Table at offset "<< hex(ulOffset) << endl ;
2421 ulToRead = MIN(ulBytesToRead, LXHdr.e32_fpagetab - ulOffset);
2422 //cout << "Entry Table: ulOffset " << (void*)(ulOffset + ulPEOffset /*LXHEADER_OFFSET*/) << " ulToRead " << MIN(ulBytesToRead, LXHdr.e32_fpagetab - ulOffset) << endl;
2423 if (expbundle != NULL)
2424 memcpy(pBuffer, (PVOID)((ULONG)expbundle + ulOffset - LXHdr.e32_enttab), ulToRead);
2425 else
2426 memset(pBuffer, 0, ulToRead);
2427 POST;
2428 }
2429 }
2430
2431
2432 /* FixupTable */
2433 if (!rc && ulOffset < LXHdr.e32_frectab)
2434 {
2435 if (ulOffset == LXHdr.e32_fpagetab) cout << "LXFile::read: Fixup Table at offset "<< hex(ulOffset+ulPEOffset /*LXHEADER_OFFSET*/) << endl ;
2436 ulToRead = MIN(ulBytesToRead, LXHdr.e32_frectab - ulOffset);
2437 cout << "LXFile::read: FixupTable: ulOffset " << (void*)(ulOffset+ulPEOffset /*LXHEADER_OFFSET*/) << " ulToRead " << ulToRead << " Relativ Offset "<< (void*)(ulOffset - LXHdr.e32_fpagetab) << endl;
2438 memcpy(pBuffer, (PVOID)((ULONG)pFixupTable + ulOffset - LXHdr.e32_fpagetab), ulToRead);
2439 POST;
2440 }
2441
2442
2443 /* Fixup Record Table */
2444 if (!rc && ulOffset < LXHdr.e32_impmod)
2445 {
2446 if (ulOffset == LXHdr.e32_frectab) cout << "LXFile::read: Fixup Record Table at offset "<< hex(ulOffset+ulPEOffset /*LXHEADER_OFFSET*/) << endl ;
2447 ulToRead = MIN(ulBytesToRead, LXHdr.e32_impmod - ulOffset);
2448 memcpy(pBuffer, (PVOID)((ULONG)pFixupRecordTable + ulOffset - LXHdr.e32_frectab), ulToRead);
2449 POST;
2450 }
2451
2452
2453 /* Import Module Name Table */
2454 if (!rc && ulOffset < LXHdr.e32_impproc)
2455 {
2456 if (ulOffset == LXHdr.e32_impmod) cout << "LXFile::read: Import Module Name Table at offset "<< hex(ulOffset+ulPEOffset /*LXHEADER_OFFSET*/) << endl ;
2457 ulToRead = MIN(ulBytesToRead, LXHdr.e32_impproc - ulOffset);
2458 //kprintf("Import Module Name Table: offset %d relative offset %d ulToRead %d\n", ulOffset, ulOffset - LXHdr.e32_impmod , ulToRead);
2459 memcpy(pBuffer, (PVOID)((ULONG)impmodules + ulOffset - LXHdr.e32_impmod), ulToRead);
2460 POST;
2461 }
2462
2463
2464 /* Import Procedure Name Table */
2465 if (!rc && ulOffset < LXHdr.e32_datapage - ulPEOffset /*LXHEADER_OFFSET*/)
2466 {
2467 if (ulOffset == LXHdr.e32_impproc) cout << "LXFile::read: Import Procedure Name Table at offset "<< hex(ulOffset+ulPEOffset /*LXHEADER_OFFSET*/) << endl ;
2468 ulToRead = MIN(ulBytesToRead, LXHdr.e32_datapage - ulPEOffset /*LXHEADER_OFFSET*/ - ulOffset );
2469 //kprintf("Import Procedure Name Table: offset %d relative offset %d ulToRead %d\n", ulOffset, ulOffset - LXHdr.e32_impproc , ulToRead);
2470 memcpy(pBuffer, (PVOID)((ULONG)impnames + ulOffset - LXHdr.e32_impproc), ulToRead);
2471 POST;
2472 }
2473
2474
2475 /* CODE/DATA are relative file start offset */
2476 ulOffset += ulPEOffset /*LXHEADER_OFFSET*/;
2477 if (!rc)
2478 {
2479 NextSection:
2480 //cout << "Section - ";
2481 /* Determin which section no. */
2482 i = 0;
2483 while (i < nrsections
2484 &&
2485 !(PESection[i].rawsize != 0
2486 && PESection[i].type != SECTION_UNINITDATA
2487 && ulOffset < (PESection[i].lxoffset + PESection[i].rawsize)
2488 && ulOffset >= PESection[i].lxoffset
2489 )/*!*/
2490 )
2491 i++;
2492
2493 if ( i >= nrsections )
2494 {
2495 /* find section nearest to ulOffset */
2496 int iTmp;
2497 //cout << "attempt find next section" << endl;
2498 iTmp = 0;
2499 i = 0;
2500 //cout << endl<< "ulOffset:" << ulOffset<< endl;
2501 while (i < nrsections)
2502 {
2503 //cout << "i="<< i << " lxoffset:" << PESection[i].lxoffset<<endl;
2504 if (PESection[i].lxoffset > ulOffset
2505 && (PESection[i].lxoffset < PESection[iTmp].lxoffset || PESection[iTmp].lxoffset < ulOffset)
2506 )
2507 iTmp = i;
2508 i++;
2509 }
2510 i = (iTmp > 0 || PESection[iTmp].lxoffset > ulOffset) ? iTmp : nrsections;
2511
2512 if (i < nrsections)
2513 {
2514 //fill gap
2515 ulToRead = MIN(ulBytesToRead, (PESection[i].lxoffset - ulOffset));
2516 cout << "alignment - fill " << ulToRead << "bytes." << endl;
2517 memset(pBuffer, 0xBB, ulToRead);
2518 POST;
2519 cout << "Section ";
2520 }
2521 }
2522
2523 if (i < nrsections)
2524 {
2525 if (ulOffset == PESection[i].lxoffset) cout << "LXFile::read: Section no."<< i << " at offset "<< hex(ulOffset) << endl;
2526
2527 /* read */
2528 ulToRead = MIN(ulBytesToRead, (PESection[i].lxoffset + PESection[i].rawsize) - ulOffset);
2529 //cout << i << ": offset " << ulOffset << " relative offset " << ulOffset - PESection[i].lxoffset << " ulToRead " << ulToRead << endl;
2530 if (!(PESection[i].type & SECTION_TIBFIX))
2531 {
2532 rc = _ldrRead(
2533 hFile,
2534 PESection[i].rawdata + (ulOffset - PESection[i].lxoffset),
2535 pBuffer,
2536 0,
2537 ulToRead,
2538 NULL
2539 );
2540 }
2541 else
2542 {
2543 AdjustTIB();
2544 memcpy(pBuffer, (void*)((ULONG)szTIBFix + (ulOffset - PESection[i].lxoffset)), ulToRead);
2545 }
2546 if (rc || ulToRead == ulBytesToRead)
2547 return rc;
2548
2549 /* read crosses section boundrary */
2550 ulOffset += ulToRead;
2551 ulBytesToRead -= ulToRead;
2552 pBuffer = (void*)((ULONG)pBuffer + ulToRead);
2553 //cout << "rec" << endl;
2554 //return read(ulOffset, pBuffer, ulBytesToRead);
2555 goto NextSection;
2556 }
2557
2558
2559 /* resource */
2560 if (!rc && nrresources > 0)
2561 {
2562 //cout << "debug: nrresources " << nrresources << endl;
2563 //cout << "debug: ulOffset " << ulOffset << endl;
2564 //cout << "debug: ResSection.lxoffset " << ResSection.lxoffset << endl;
2565 //cout << "debug: ResSection.rawsize " << ResSection.rawsize << endl;
2566 //cout << "debug: ResSection.rawsize " << ResSection.virtualsize << endl;
2567 if (!rc && ulOffset < ResSection.lxoffset + ResSection.rawsize)
2568 {
2569 if (ulOffset == ResSection.lxoffset) cout << "LXFile::read: ResSection at offset "<< hex(ulOffset) << endl;
2570 ulToRead = MIN(ulBytesToRead, ResSection.lxoffset + ResSection.rawsize - ulOffset);
2571 //cout << "LXFile::read: ResSection: ulOffset " << ulOffset << " relative offset " << ulOffset -ResSection.lxoffset << " ulToRead " << ulToRead << endl;
2572 memcpy(pBuffer, (char*)ResSection.rawdata + (ulOffset - ResSection.lxoffset), ulToRead);
2573 POST;
2574 }
2575 }
2576
2577 /*
2578 While debugging: If this is an partly finished request we pad the last part of it and return NO_ERROR;
2579 Else: fail!
2580 */
2581 #ifdef RING0_DEBUG_IN_RING3
2582 if (!rc && *pulBytesRead > ulBytesToRead)
2583 {
2584 /*pad end*/
2585 ulToRead = ulBytesToRead;
2586 cout << "LXFile::read: WARNING! had to pad end of request!"<< endl;
2587 memset((void*)((ULONG)pBuffer+ulToRead), 0xCC, ulBytesToRead-ulToRead);
2588 *pulBytesRead -= ulBytesToRead;
2589 return -2;
2590 }
2591 #endif
2592
2593 }
2594
2595 return ERROR_READ_FAULT;
2596}
2597
2598
2599
2600/**
2601 * Read a page from the PE-file based on the RVA on the page.
2602 * @param address RVA of the page to be read.
2603 * @param pPage Pointer to output buffer - size: one page.
2604 * @return NO_ERROR on success. Something else on failure.
2605 */
2606int LXFile::ReadPageByAddress(ULONG address, void *pPage)
2607{
2608 int SectNo,rc;
2609 ULONG ulOffset;
2610 ULONG ulToRead;
2611
2612 /* find which section */
2613 SectNo = GetOriginalSectionIdxByVA(address);
2614 if (SectNo == -1)
2615 {
2616 cout << "LXFile::ReadPageByAddress: GetOriginalSectionIdxByVA(" << address << ") == -1 !oops!" << endl;
2617 return -1;
2618 }
2619
2620 ///* check if this is our TIBFix section */
2621 //ulOffset = SectNo == GetTIBSectionIdx() ? ulOffset = 1 : ulOffset = 0;
2622 ulOffset = 0;
2623
2624 /* check if not uninited datasection */
2625 if (PESection[SectNo].rawdata != ~0)
2626 {
2627 ulOffset = PESection[SectNo].rawdata + (address - (PESection[SectNo].address + (PESection[SectNo].nrinvalidpages + ulOffset)*PAGE_SIZE));
2628 ulToRead = MIN(PAGE_SIZE, PESection[SectNo].rawsize - (ulOffset - PESection[SectNo].rawdata));
2629 }
2630 else
2631 {
2632 memset(pPage , 0, PAGE_SIZE);
2633 return NO_ERROR;
2634 }
2635
2636 /* check if last page */
2637 if (ulToRead > 0)
2638 {
2639 /* read page */
2640 rc = _ldrRead(
2641 hFile,
2642 ulOffset,
2643 pPage,
2644 0,
2645 ulToRead,
2646 NULL
2647 );
2648 }
2649 else
2650 if (ulToRead > 0 && ulToRead >= -PAGE_SIZE)
2651 {
2652 ulToRead = 0;
2653 rc = -2; //signal this is less or exactly than one page beyond the last page (used in ProcessFixups)
2654 }
2655 else
2656 return -1; //error!
2657
2658 /* pad the rest of the page buffer */
2659 if (ulToRead < PAGE_SIZE)
2660 memset((void*)((ULONG)pPage + ulToRead), 0, PAGE_SIZE - ulToRead);
2661
2662 return rc;
2663}
2664
2665
2666
2667/**
2668 * Query the total amount of memory used by this object.
2669 * If logging is enabled it will display a list which shows how much
2670 * memory is consumed by each datamember.
2671 *
2672 * @return Memory used in bytes.
2673 * @remark May only be called after init() is completed
2674 */
2675int LXFile::queryMemoryUsage()
2676{
2677 int tsize, size;
2678
2679 ltassert(inited);
2680
2681 tsize = 0;
2682 cout << "LXFile::queryMemoryUsage() :" <<endl;
2683 cout << "----------------------------" <<endl;
2684
2685 tsize += size = sizeof(LXFile);
2686 cout << " LXfile " << hex(size) << "bytes" << endl;
2687
2688
2689 if( pObjectTable != NULL)
2690 tsize += size =_msize(pObjectTable);
2691 else
2692 size = 0;
2693 cout << " LXfile::pObjectTable " << hex(size) << "bytes" << endl;
2694
2695 if( pObjectPageTable != NULL)
2696 tsize += size =_msize(pObjectPageTable);
2697 else
2698 size = 0;
2699 cout << " LXfile::pObjectPageTable " << hex(size) << "bytes" << endl;
2700
2701 if( pFixupTable != NULL)
2702 tsize += size =_msize(pFixupRecordTable);
2703 else
2704 size = 0;
2705 cout << " LXfile::pFixupTable " << hex(size) << "bytes" << endl;
2706
2707 if( pFixupRecordTable != NULL)
2708 tsize += size =_msize(pFixupRecordTable);
2709 else
2710 size = 0;
2711 cout << " LXfile::pFixupRecordTable " << hex(size) << "bytes" << endl;
2712
2713
2714 if( PESection != NULL)
2715 tsize += size =_msize(PESection);
2716 else
2717 size = 0;
2718 cout << " LXHeaderSuper::PESection " << hex(size) << "bytes" << endl;
2719
2720 if( datapage != NULL)
2721 tsize += size =_msize(datapage);
2722 else
2723 size = 0;
2724 cout << " LXHeaderSuper::datapage " << hex(size) << "bytes" << endl;
2725
2726 if( impmodules != NULL)
2727 tsize += size =_msize(impmodules);
2728 else
2729 size = 0;
2730 cout << " LXHeaderSuper::impmodules " << hex(size) << "bytes" << endl;
2731
2732 if( impnames != NULL)
2733 tsize += size =_msize(impnames);
2734 else
2735 size = 0;
2736 cout << " LXHeaderSuper::impnames " << hex(size) << "bytes" << endl;
2737
2738 if( impfixuprec != NULL)
2739 tsize += size =_msize(impfixuprec);
2740 else
2741 size = 0;
2742 cout << " LXHeaderSuper::impfixuprec " << hex(size) << "bytes" << endl;
2743
2744 if( intfixuprec != NULL)
2745 tsize += size =_msize(intfixuprec);
2746 else
2747 size = 0;
2748 cout << " LXHeaderSuper::intfixuprec " << hex(size) << "bytes" << endl;
2749
2750 if( os2resource != NULL)
2751 tsize += size =_msize(os2resource);
2752 else
2753 size = 0;
2754 cout << " LXHeaderSuper::os2resource " << hex(size) << "bytes" << endl;
2755
2756 if( cvtname != NULL)
2757 tsize += size =_msize(cvtname);
2758 else
2759 size = 0;
2760 cout << " LXHeaderSuper::cvtname " << hex(size) << "bytes" << endl;
2761
2762 if( resids != NULL)
2763 tsize += size =_msize(resids);
2764 else
2765 size = 0;
2766 cout << " LXHeaderSuper::resids " << hex(size) << "bytes" << endl;
2767
2768 if( orgrestable != NULL)
2769 tsize += size =_msize(orgrestable);
2770 else
2771 size = 0;
2772 cout << " LXHeaderSuper::orgrestable " << hex(size) << "bytes" << endl;
2773
2774 if( exports != NULL)
2775 tsize += size =_msize(exports);
2776 else
2777 size = 0;
2778 cout << " LXHeaderSuper::exports " << hex(size) << "bytes" << endl;
2779
2780 if( expbundle != NULL)
2781 tsize += size =_msize(expbundle);
2782 else
2783 size = 0;
2784 cout << " LXHeaderSuper::expbundle " << hex(size) << "bytes" << endl;
2785
2786 if( (void*)ResSection.rawdata != NULL)
2787 tsize += size =_msize((void*)ResSection.rawdata);
2788 else
2789 size = 0;
2790 cout << " LXHeaderSuper::ResSection.rawdata " << hex(size) << "bytes" << endl;
2791
2792
2793
2794/*
2795 if( != NULL)
2796 tsize += size =_msize();
2797 else
2798 size = 0;
2799 cout << " LXHeaderSuper:: " << hex(size) << "bytes" << endl;
2800
2801*/
2802
2803
2804 /*end*/
2805 cout << " Total memory usage " << hex(tsize) << "bytes" << endl;
2806
2807 return tsize;
2808}
2809
2810
2811
2812#ifndef __DEBUG_ALLOC__
2813
2814 /**
2815 * No debug new operator
2816 */
2817 void *LXFile::operator new(size_t a)
2818 {
2819 return malloc((ULONG)a);
2820 }
2821
2822
2823
2824 /**
2825 * No debug delete operator
2826 */
2827 void LXFile::operator delete(void *p)
2828 {
2829 free(p);
2830 }
2831
2832#else
2833
2834 /**
2835 * Debug new operator
2836 */
2837 void *LXFile::operator new(size_t a, const char *file, unsigned int line)
2838 {
2839 void* pTmp = malloc(a);
2840 #ifdef ALLOC_VERBOSE
2841 cout << "LXFile::operator new("<<a<<","<<file<<","<<line<<") -->"<< pTmp<<endl;
2842 #endif
2843 return pTmp;
2844 }
2845
2846
2847
2848 /**
2849 * Debug delete operator
2850 */
2851 void LXFile::operator delete(void *p, const char *file, unsigned int line)
2852 {
2853 #ifdef ALLOC_VERBOSE
2854 cout << "LXFile::operator delete("<<p<<","<<file<<","<<line<<");"<<endl;
2855 #endif
2856 free(p);
2857 }
2858
2859#endif
2860
2861
2862
2863/**
2864 * Builds a LX (EXE) header to present to the LDRQAppType call
2865 * @param pHdr Pointer to the buffer in which the LX-header is made.
2866 */
2867void LXFile::buildQAppTypeHeader(struct e32_exe *pHdr)
2868{
2869 BOOL fEXE;
2870
2871 vltassert(pHdr);
2872
2873 fEXE = !(((PIMAGE_FILE_HEADER)((ULONG)pHdr+sizeof(DWORD)))->Characteristics & 0x2000);
2874
2875 memset((void*)pHdr,0,sizeof(struct e32_exe));
2876
2877 pHdr->e32_magic[0] = E32MAGIC1;
2878 pHdr->e32_magic[1] = E32MAGIC2;
2879 pHdr->e32_border = E32LEBO;
2880 pHdr->e32_worder = E32LEWO;
2881 pHdr->e32_level = E32LEVEL;
2882 pHdr->e32_cpu = E32CPU386;
2883 pHdr->e32_os = 0x01; //OS/2
2884 pHdr->e32_ver = 0; //who cares which version...
2885 pHdr->e32_mflags = 0x300 | 0x8000*!fEXE;
2886 pHdr->e32_mpages = 1;
2887 pHdr->e32_startobj = 1; //code
2888 pHdr->e32_eip = 0;
2889 pHdr->e32_stackobj = 3;
2890 pHdr->e32_esp = 0x101000;
2891 pHdr->e32_pagesize = 4096; //default
2892 pHdr->e32_pageshift= 0; //default (doet watcom zo)
2893 pHdr->e32_fixupsize= 0x2c5f;
2894 pHdr->e32_fixupsum = 0; //no checksum supported
2895 pHdr->e32_ldrsize = 0x3507;
2896 pHdr->e32_ldrsum = 0; //no checksum supported
2897 pHdr->e32_objtab = sizeof(struct e32_exe);
2898 pHdr->e32_objcnt = 4;
2899 pHdr->e32_objmap = 0x124;
2900 pHdr->e32_itermap = 0;
2901 pHdr->e32_rsrctab = 0x184;
2902 pHdr->e32_rsrccnt = 0x90;
2903 /* exe! */
2904 pHdr->e32_restab = 0x964;
2905 pHdr->e32_enttab = 0x96b;
2906 /* */
2907 pHdr->e32_dirtab = 0;
2908 pHdr->e32_dircnt = 0;
2909 pHdr->e32_fpagetab = 0x96c;
2910 pHdr->e32_frectab = 0xda0;
2911 pHdr->e32_impmod = 0x305a;
2912 pHdr->e32_impmodcnt= 0x0006;
2913 pHdr->e32_impproc = 0x3085;
2914 pHdr->e32_pagesum = 0;
2915 pHdr->e32_datapage = 0x364b;
2916 pHdr->e32_preload = 0;
2917 pHdr->e32_nrestab = 0;
2918 pHdr->e32_cbnrestab= 0;
2919 pHdr->e32_nressum = 0;
2920 pHdr->e32_autodata = 3;
2921 pHdr->e32_debuginfo= 0;
2922 pHdr->e32_debuglen = 0;
2923 pHdr->e32_instpreload=0;
2924 pHdr->e32_instdemand =0;
2925 pHdr->e32_heapsize =0;
2926 pHdr->e32_stacksize=0;
2927
2928}
2929
2930
2931
2932/**
2933 * Apply changes to the TIBFix code for this object.
2934 * @remark This code is connected to LXHeaderSuper::SaveConvertedNames
2935 */
2936void LXFile::AdjustTIB()
2937{
2938 /* 4th paramenter for RegisterResourceInfo/RegisterDLL */
2939 *(LONG *)&szTIBFix[TIBOffPe2lxVer] = PE2LX_VERSION;
2940
2941 /* 3rd paramenter for RegisterResourceInfo/RegisterDLL */
2942 *(LONG *)&szTIBFix[TIBOffVerResId] = VersionResourceId;
2943
2944 /* 2nd paramenter for RegisterResourceInfo/RegisterDLL */
2945 if (nrcvtnames)
2946 *(LONG*)&szTIBFix[TIBOffName] = cvtnametableid;
2947 else
2948 *(LONG*)&szTIBFix[TIBOffName] = 0x77777777;
2949
2950 /* 1st parameter for RegisterResourceInfo/RegisterDLL */
2951 if (nrorgres)
2952 *(LONG*)&szTIBFix[TIBOffName+5] = (fConsole << 24) | orgrestableid;
2953 else
2954 *(LONG*)&szTIBFix[TIBOffName+5] = (fConsole << 24) | 0x888888;
2955
2956 /* Entry Point */
2957 *(PLONG)&szTIBFix[TIBOffEntry] = TIBEntry;
2958}
2959
2960
2961
2962/**
2963 * Query if szFilename is the name of a present PE module in the tree of Nodes.
2964 * @param szFilename Module name or filename name evt. with partially or full path.
2965 * @return TRUE if szFilename is the tree else FALSE.
2966 */
2967BOOL LXFile::queryIsModuleName(const char *szFilename)
2968{
2969 char fname[CCHMAXPATH];
2970 char *pfname;
2971 pfname = (char*)SSToDS(fname);
2972 strcpy(pfname, szFilename);
2973 UpCase(pfname);
2974 pfname = StripExtension(StripPath((char*)SSToDS(fname)));
2975
2976 return strlen(pfname) == modulename[0] && strncmp(pfname, &modulename[1], modulename[0]) == 0;
2977}
2978
2979
2980
2981/**
2982 * Queries the size of the virtual LX-File.
2983 * @return Virtual LX-File size in bytes.
2984 */
2985ULONG LXFile::queryFileSize()
2986{
2987 if (nrresources > 0)
2988 return ResSection.lxoffset + ResSection.rawsize;
2989 else
2990 if (LXHdr.e32_objcnt != nrsections && nrsections > 1 && PESection != NULL) //COMBINEDDATA
2991 return PESection[nrsections-2].lxoffset + PESection[nrsections-2].rawsize;
2992 else
2993 if (nrsections > 0 && PESection != NULL)
2994 return PESection[nrsections-1].lxoffset + PESection[nrsections-1].rawsize;
2995 else
2996 return ~0;
2997}
2998
Note: See TracBrowser for help on using the repository browser.