source: trunk/src/pe2lx/LX.CPP@ 46

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

* empty log message *

File size: 60.9 KB
Line 
1/*
2 * PE2LX LX code
3 *
4 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
5 * Copyright 1998 Knut St. Osmundsen
6 * Copyright 1998 Peter Fitzsimmons
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_DOSFILEMGR /* File Manager values */
13#define INCL_DOSERRORS /* DOS Error values */
14#define INCL_DOSPROCESS /* DOS Process values */
15#define INCL_DOSMISC /* DOS Miscellanous values */
16#include <os2.h>
17#include <stdio.h>
18#include <string.h>
19#include <stdlib.h>
20#include <iostream.h>
21#include <string.h>
22#include <assert.h>
23#include "lx.h"
24#include "misc.h" /*PLF Wed 98-03-18 02:00:21*/
25#include <versionos2.h>
26
27#define ORD_REGISTERRESOURCEINFO 1203
28#define ORD_KERNEL32DLLEXITLIST 1208
29#define ORD_REGISTERDLL 1209
30
31#define ZERO(a) (memset(&a, 0, sizeof(a)))
32
33#ifndef max /*PLF Sat 97-06-21 22:36:14*/
34#define max(a,b) ((a>b) ? (a) : (b))
35#endif
36
37#ifndef min
38#define min(a,b) ((a<b) ? (a) : (b))
39#endif
40
41//In pe.cpp
42char *hex(ULONG num);
43
44LXHeader OS2Exe;
45
46//Borrowed dos header from executables generated by Watcom
47static unsigned char szDosHeader[128] = {
48 0x4D, 0x5A, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
49 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
52 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x74, 0x68,
53 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6E, 0x20, 0x4F, 0x53, 0x2F, 0x32, 0x20, 0x33, 0x32,
54 0x2D, 0x62, 0x69, 0x74, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x0D,
55 0x0A, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
56
57//Register module in kernel32 (resource managment)
58// EXE:
59//push [esp+4] ;instance handle
60//push internal pe2lx version
61//push version resource id
62//push name_lookup_tableid
63//push orgres_lookup_tableid
64//mov ecx, KERNEL32:RegisterResourceInfo (stdcall)
65//call ecx
66//
67//call original_entrypoint
68//ret
69//
70// DLL:
71//cmp [esp+8], 1
72//je detach
73//push [esp+4] ;instance handle
74//push internal pe2lx version
75//push version resource id
76//push name_lookup_tableid
77//push orgres_lookup_tableid
78//mov ecx, KERNEL32:RegisterDll (stdcall)
79//call ecx
80///DLL entrypoint:
81/// BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
82//push 0
83//mov ecx, [esp+12]
84//xor ecx, 1 //0 -> 1, 1 -> 0
85//push ecx //push entry type (1 = attach process, 0 = detach process)
86//push [esp+12] //push module handle
87//call testje
88//ret
89//detach:
90//push [esp+4] //instance handle
91//call KERNEL32:DllExitList
92//ret
93
94#define EXE_OFF_ENTRYFIX (1+19+2+10)
95#define EXE_OFF_TIBCALL (EXE_OFF_ENTRYFIX-1)
96#define EXE_OFF_NAMETABLE (3+2+10)
97//SvL: 18-7-'98: offsets for internal pe2lx version & version resource id
98#define EXE_OFF_PE2LXVER (5)
99#define EXE_OFF_VERRESID (10)
100#define EXE_TIBSIZE sizeof(szEXETIBFix)
101#define EXE_OFF_KERIMP (EXE_OFF_NAMETABLE+10)
102
103#define DLL_OFF_ENTRYFIX (15+28+10)
104//#define DLL_OFF_ENTRYFIX (16+28+10)
105#define DLL_OFF_TIBCALL (DLL_OFF_ENTRYFIX-1)
106//SvL: 18-7-'98: offsets for internal pe2lx version & version resource id
107#define DLL_OFF_PE2LXVER (12)
108#define DLL_OFF_VERRESID (17)
109#define DLL_OFF_NAMETABLE (12+10)
110//#define DLL_OFF_NAMETABLE 12+1+10
111#define DLL_TIBSIZE sizeof(szDLLTIBFix)
112#define DLL_OFF_KERIMP (DLL_OFF_NAMETABLE+10)
113#define DLL_OFF_KERIMP2 (sizeof(szDLLTIBFix)-5)
114
115#define SIZE_TIBCALL 5
116
117#define EXTRA_FIXUPS 2 //extra kernel32 imports
118
119static unsigned char szEXETIBFix[] = {
120//push [esp+4]
121 0xFF, 0x74, 0x24, 0x04,
122//SvL: 18-7-'98: push internal pe2lx version
123 0x68, 0x00, 0x00, 0x00, 0x00,
124//SvL: 18-7-'98: push version resource id (-1 = no version resource present)
125 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
126//push [table id1] (kernel32 proc depends on 0x77777777 & 0x88888888!!)
127//Svl: So does void LXHeader::SaveConvertedNames()!
128 0x68, 0x77, 0x77, 0x77, 0x77,
129//push [table id1]
130 0x68, 0x88, 0x88, 0x88, 0x88,
131//mov ecx, KERNEL32:RegisterResourceInfo (stdcall)
132 0xB9, 0x99, 0x99, 0x99, 0x99,
133//call ecx
134 0xFF, 0xD1,
135//call entrypoint
136 0xE8, 0x8C, 0xFF, 0xFF, 0xFF,
137//ret
138 0xC3};
139
140//WARNING: Kernel32.dll depends on this layout (offsets of dllexitlist &
141// entry point call are hardcoded! (both calculated in RegisterDll)
142static unsigned char szDLLTIBFix[] = {
143//cmp [esp+8], 1
144// 0xCC, 0x80, 0x7C, 0x24, 0x08, 0x01,
145 0x80, 0x7C, 0x24, 0x08, 0x01,
146//je detach
147 0x74, 0x33,
148//push [esp+4]
149 0xFF, 0x74, 0x24, 0x04,
150//SvL: 18-7-'98: push internal pe2lx version
151 0x68, 0x00, 0x00, 0x00, 0x00,
152//SvL: 18-7-'98: push version resource id (-1 = no version resource present)
153 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
154//push [table id1] (kernel32 proc depends on 0x77777777 & 0x88888888!!)
155//Svl: So does void LXHeader::SaveConvertedNames()!
156 0x68, 0x77, 0x77, 0x77, 0x77,
157//push [table id1]
158 0x68, 0x88, 0x88, 0x88, 0x88,
159//mov ecx, KERNEL32:RegisterDll (stdcall)
160 0xB9, 0x99, 0x99, 0x99, 0x99,
161//call ecx
162 0xFF, 0xD1,
163//push 0
164 0x6A, 0x00,
165 0x8B, 0x4C, 0x24, 0x0C,
166 0x83, 0xF1, 0x01,
167 0x51, 0xFF, 0x74, 0x24, 0x0C,
168//call entrypoint
169 0xE8, 0x80, 0xFF, 0xFF, 0xFF,
170//ret
171 0xC3,
172//detach:
173//push [esp+4]
174 0xFF, 0x74, 0x24, 0x04,
175//call KERNEL32:DllExitList (stdcall)
176 0xE8, 0x00, 0x00, 0x00, 0x00,
177//ret
178 0xC3};
179
180//******************************************************************************
181//******************************************************************************
182
183LXHeader::LXHeader() : fFlags(0), EntryAddress(0), IsEXE(TRUE),
184 impmodules(NULL), impnames(NULL), impfixuprec(NULL),
185 nrimpfixups(0), StackSize(0), nrsections(0),
186 nrintfixups(0), intfixuprec(NULL), os2resource(NULL), nrids(0),
187 nrresources(0), curresource(0), exports(NULL), resids(NULL),
188 nrexports(0), curexport(0), expbundle(NULL), curexpb(NULL),
189 cvtname(NULL), curcvtname(0), nrcvtnames(0), datapage(NULL),
190 cvtnametableid(0), orgrestableid(0), orgrestable(NULL), nrorgres(0),
191 kernel32Object(-1), TIBOffKerImport(0), fConsole(FALSE),
192 VersionResourceId(-1), impnamesize(0), impmodulesize(0)
193{
194 ZERO(LXHdr);
195
196 LXHdr.e32_magic[0] = E32MAGIC1;
197 LXHdr.e32_magic[1] = E32MAGIC2;
198 LXHdr.e32_border = E32LEBO;
199 LXHdr.e32_worder = E32LEWO;
200 LXHdr.e32_level = E32LEVEL;
201 LXHdr.e32_cpu = E32CPU386;
202 LXHdr.e32_os = 0x01; //OS/2
203 LXHdr.e32_ver = 0; //who cares which version...
204 LXHdr.e32_pagesize = 4096; //default
205 LXHdr.e32_pageshift= 0; //default (doet watcom zo)
206 LXHdr.e32_fixupsum = 0; //no checksum supported
207 LXHdr.e32_ldrsum = 0; //no checksum supported
208 LXHdr.e32_mflags = 0;
209 LXHdr.e32_startobj = 1; //code
210 LXHdr.e32_objcnt = 0;
211 LXHdr.e32_objtab = sizeof(LXHdr); //begin hiermee vlak na exe hdr
212 ZERO(ResSection);
213 memset(&PESection[0], 0, sizeof(PESection));
214
215 szTIBFix = &szEXETIBFix[0];
216 TIBSize = EXE_TIBSIZE;
217 TIBOffEntry = EXE_OFF_ENTRYFIX;
218 TIBOffCall = EXE_OFF_TIBCALL;
219 TIBOffName = EXE_OFF_NAMETABLE;
220 //SvL: 18-7-'98: Internal pe2lx version and version resource id offsets
221 TIBOffPe2lxVer = EXE_OFF_PE2LXVER;
222 TIBOffVerResId = EXE_OFF_VERRESID;
223}
224//******************************************************************************
225//******************************************************************************
226LXHeader::~LXHeader()
227{
228 if(impmodules) free(impmodules);
229 if(impnames) free(impnames);
230 if(impfixuprec) free(impfixuprec);
231 if(os2resource) free(os2resource);
232 if(resids) free(resids);
233 if(cvtname) free(cvtname);
234 if(orgrestable) free(orgrestable);
235 if(ResSection.rawdata) free(ResSection.rawdata);
236 if(exports) free(exports);
237 if(expbundle) free(expbundle);
238 if(datapage) free(datapage);
239}
240//******************************************************************************
241//******************************************************************************
242void LXHeader::SetNoFixups()
243{
244 LXHdr.e32_mflags |= E32NOINTFIX;
245}
246//******************************************************************************
247//******************************************************************************
248void LXHeader::SetExeType(BOOL IsEXE)
249{
250 this->IsEXE = IsEXE;
251 if(IsEXE) {
252 szTIBFix = &szEXETIBFix[0];
253 TIBSize = EXE_TIBSIZE;
254 TIBOffEntry = EXE_OFF_ENTRYFIX;
255 TIBOffCall = EXE_OFF_TIBCALL;
256 TIBOffName = EXE_OFF_NAMETABLE;
257 TIBOffKerImport = EXE_OFF_KERIMP;
258 //SvL: 18-7-'98: Internal pe2lx version and version resource id offsets
259 TIBOffPe2lxVer = EXE_OFF_PE2LXVER;
260 TIBOffVerResId = EXE_OFF_VERRESID;
261 LXHdr.e32_mflags |= E32MODEXE;
262 }
263 else {//Assuming per process initialization/termination...
264 szTIBFix = &szDLLTIBFix[0];
265 TIBSize = DLL_TIBSIZE;
266 TIBOffEntry = DLL_OFF_ENTRYFIX;
267 TIBOffCall = DLL_OFF_TIBCALL;
268 TIBOffName = DLL_OFF_NAMETABLE;
269 TIBOffKerImport = DLL_OFF_KERIMP;
270 //SvL: 18-7-'98: Internal pe2lx version and version resource id offsets
271 TIBOffPe2lxVer = DLL_OFF_PE2LXVER;
272 TIBOffVerResId = DLL_OFF_VERRESID;
273 LXHdr.e32_mflags |= E32LIBINIT | E32LIBTERM | E32MODDLL;
274 }
275}
276//******************************************************************************
277//******************************************************************************
278void LXHeader::SetEntryAddress(int address)
279{
280 LXHdr.e32_eip = address;
281}
282//******************************************************************************
283//******************************************************************************
284void LXHeader::SetStackSize(int size)
285{
286 if(IsEXE) {
287 //Open32 requires a stack size of at least 64k
288// if(size < 64*1024) StackSize = 64*1024;
289 if(size < 128*1024) StackSize = 128*1024;
290 else StackSize = size;
291 //KSO - Aug 5 1998 8:13pm: (Borlandfix) stacksize in TIB depend on this.
292 LXHdr.e32_stacksize = StackSize;
293 }
294}
295//******************************************************************************
296//******************************************************************************
297void LXHeader::SetModuleName(char *filename)
298{
299char fname[CCHMAXPATH];
300
301 strcpy(fname, filename);
302 strcpy(modulename, StripExtension(StripPath(fname)));
303 UpCase(modulename);
304}
305//******************************************************************************
306//******************************************************************************
307void LXHeader::StoreSection(char *rawdata, int rawsize, int virtualsize, int address, int type)
308{
309#ifndef RING0
310static int idx = 0, i;
311Section TmpSec[MAX_SECTION];
312
313 //Several exes have sections with virtual size 0
314 if(virtualsize == 0) virtualsize = rawsize;
315
316 assert(rawdata);
317
318 if(nrsections == 0) {
319 PESection[0].type = type;
320 PESection[0].rawdata = rawdata;
321 PESection[0].address = address;
322 PESection[0].rawsize = rawsize;
323//SvL: 5-9-'98
324 PESection[0].virtualsize = max(virtualsize,rawsize);
325// PESection[0].virtualsize = virtualsize;
326 PESection[0].nrpages = ((PESection[0].virtualsize + 0xFFF) & ~0xFFF) >> PAGE_SHIFT;
327 PESection[0].endaddress = address + PESection[0].nrpages*PAGE_SIZE - 1;
328 }
329 else { //anders op volgorde toevoegen
330 memset(&TmpSec[0], 0, sizeof(TmpSec));
331 i = 0;
332 while(i < idx && PESection[i].address < address) {
333 memcpy(&TmpSec[i], &PESection[i], sizeof(PESection[i]));
334 i++;
335 assert( i < MAX_SECTION ); /*PLF Mon 98-02-09 23:44:23*/
336 }
337 TmpSec[i].type = type;
338 TmpSec[i].rawdata = rawdata;
339 TmpSec[i].address = address;
340 TmpSec[i].rawsize = rawsize;
341 TmpSec[i].virtualsize = max(virtualsize,rawsize);
342 TmpSec[i].nrpages = ((TmpSec[i].virtualsize + 0xFFF) & ~0xFFF) >> PAGE_SHIFT;
343 TmpSec[i].endaddress = address + TmpSec[i].nrpages*PAGE_SIZE - 1;
344 while(i < idx && PESection[i].rawdata) {
345 assert( i+1 < MAX_SECTION ); /*PLF Mon 98-02-09 23:44:23*/
346 memcpy(&TmpSec[i+1], &PESection[i], sizeof(PESection[i]));
347 i++;
348 }
349 memcpy(&PESection[0], &TmpSec[0], (idx+1)*sizeof(PESection[0]));
350 }
351 idx++;
352 nrsections++;
353#else
354 int i,j;
355
356
357 //Several exes have sections with virtual size 0
358 if (virtualsize == 0) virtualsize = rawsize;
359
360 /* sorry this was not optimized! */
361 /*find place in section table (sort on address)*/
362 i = 0;
363 while (i < nrsections/*idx?*/ && PESection[i].address < address )
364 i++;
365
366 if ( i != nrsections )
367 {
368 /* move sections from this one entry back */
369 j = nrsections;
370 while(j > i)
371 {
372 memcpy(&PESection[j], &PESection[j-1], sizeof(PESection[j-1]));
373 j--;
374 }
375 }
376
377 PESection[i].type = type;
378 #ifndef RING0
379 PESection[i].rawdata = rawdata;
380 #else
381 PESection[i].rawdata = rawdata ? (rawdata) : ~0;
382 #endif
383 PESection[i].address = address;
384#if 1
385 PESection[i].rawsize = min(rawsize,virtualsize);
386 PESection[i].virtualsize = max(virtualsize,rawsize);
387#else
388 PESection[i].rawsize = rawsize;//min(rawsize,virtualsize);
389 PESection[i].virtualsize = virtualsize;//max(virtualsize,rawsize);
390#endif
391 PESection[i].nrpages = ((virtualsize + 0xFFF) & ~0xFFF) >> PAGE_SHIFT;
392 PESection[i].endaddress = address + PESection[i].nrpages*PAGE_SIZE - 1;
393
394
395 /* Inc number of sections */
396 nrsections++;
397 /* it wasn't that hard was it? - this code will at least not cause a stack overflow. */
398#endif
399}
400//******************************************************************************
401//SvL: Align code section at 64 kb boundary
402//SvL: Put adjacent data section in one big section and align it to a 64 kb
403// boundary
404//ASSUMPTIONS: - Code section comes first
405// - (data) sections that aren't adjacent are aligned at 64kb boundary
406//I could fix the second assumption, but I'm too lazy right now
407//******************************************************************************
408void LXHeader::AlignSections()
409{
410int i, j, idx = 0, rawsize;
411Section CombinedData;
412
413 //Put TIBFix code before actual win32 code (prevents overlaps)!
414 PESection[0].address -= PAGE_SIZE;
415 PESection[0].nrpages++;
416
417 if(!(LXHdr.e32_mflags & E32NOINTFIX))
418 return; //rest not needed if there are internal fixups
419
420 PESection[0].nrinvalidpages = (PESection[0].address & 0xFFFF) >> PAGE_SHIFT;
421 PESection[0].address &= 0xFFFF0000;
422
423 //SvL: Concatenate code & data sections into one LX object
424 memcpy(&CombinedData, &PESection[0], sizeof(Section));
425
426 //Insert invalid pages to align section at 64 kb boundary
427 CombinedData.type = SECTION_COMBINEDDATA;
428 CombinedData.rawdata = NULL; //not used here (just use the originals)
429
430 //too much, but just to be sure (in case we need to add extra invalid pages)
431 //TODO: This should be done safer in the future
432 datapage = (DataPage *)malloc((GetNrPages()+256)*sizeof(DataPage));
433
434 //process pages of first section (code)
435 rawsize = CombinedData.rawsize;
436
437 datapage[0].size = TIBSize;
438 datapage[0].flags = 0;
439 idx = 1;
440 for(j=1;j<CombinedData.nrpages;j++) {
441 if(rawsize < PAGE_SIZE) {
442 datapage[idx].size = rawsize;
443 rawsize = 0;
444 }
445 else {
446 datapage[idx].size = PAGE_SIZE;
447 rawsize -= PAGE_SIZE;
448 }
449 datapage[idx].flags= 0;
450 idx++;
451 }
452
453 for(i=1;i<nrsections;i++) {
454 if(PESection[i].address != CombinedData.endaddress + 1) {
455 if((PESection[i].address & 0xFFFF) == 0) //Watcom generated exe
456 return; //all sections are already properly aligned
457 cout << "Section not aligned at 64 kb boundary!!!" << endl;
458 //Damn, more work to do.
459 int insertpages;
460
461 insertpages = (PESection[i].address - CombinedData.endaddress-1) >> PAGE_SHIFT;
462 for(j=0;j<insertpages;j++) {
463 datapage[idx].size = 0;
464 datapage[idx].flags = ZEROED;
465 idx++;
466 }
467 CombinedData.nrpages += insertpages;
468 }
469
470 CombinedData.nrpages += PESection[i].nrpages;
471 CombinedData.rawsize += PESection[i].rawsize;
472//SvL: 5-9-'98
473 CombinedData.virtualsize += max(PESection[i].rawsize, PESection[i].virtualsize);
474 CombinedData.endaddress = PESection[i].endaddress;
475
476 rawsize = PESection[i].rawsize;
477 for(j=0;j<PESection[i].nrpages;j++) {
478 if(PESection[i].type == SECTION_UNINITDATA || rawsize == 0) {
479 datapage[idx].size = 0;
480 datapage[idx].flags = ZEROED;
481 }
482 else {
483 if(rawsize < PAGE_SIZE) {
484 datapage[idx].size = rawsize;
485 rawsize = 0;
486 }
487 else {
488 datapage[idx].size = PAGE_SIZE;
489 rawsize -= PAGE_SIZE;
490 }
491 datapage[idx].flags= 0;
492 }
493 idx++;
494 }
495 PESection[i].fInvalid = TRUE;
496 }
497 memcpy(&PESection[nrsections++], &CombinedData, sizeof(Section));
498 PESection[0].fInvalid = TRUE;
499}
500//******************************************************************************
501//******************************************************************************
502int LXHeader::GetNrObjects()
503{
504 int nrobjs = 0, i;
505
506 for(i=0;i<nrsections;i++) {
507 if(PESection[i].fInvalid == FALSE)
508 nrobjs++;
509 }
510 return(nrobjs);
511}
512//******************************************************************************
513//******************************************************************************
514#ifdef __WATCOMC__
515#pragma off (unreferenced)
516#endif
517void LXHeader::AddNameExport(int address, char *name, int ordinal)
518#ifdef __WATCOMC__
519#pragma on (unreferenced)
520#endif
521{
522 if(strlen(name) > (127-3)) name[126] = 0; //OS/2 maximum
523
524 *curexport = (BYTE)strlen(name);
525 curexport++;
526 strcpy(curexport, name);
527 curexport += strlen(name);
528 *(USHORT *)curexport = (USHORT)(ordinal);
529 curexport += sizeof(USHORT);
530}
531//******************************************************************************
532//******************************************************************************
533void LXHeader::AddOrdExport(int address, int ordinal)
534{
535 static int lastord = 0;
536 int i;
537
538 if(ordinal > lastord+1) {//add empty record(s)
539 int diff = ordinal - lastord - 1;
540 while(diff) {
541 curexpb->b32_cnt = min(diff, 255);
542 diff -= curexpb->b32_cnt;
543 curexpb->b32_type = EMPTY;
544 curexpb = (exportbundle *)((int)curexpb + 2*sizeof(char));
545 }
546 }
547
548 curexpb->b32_cnt = 1;
549 curexpb->b32_type = ENTRY32;
550 i = GetRealSectionByAddress(address);
551 curexpb->b32_obj = (USHORT)(i + 1); //start at 1 instead of 0
552
553 curexpb->e32_flags = E32EXPORT | E32SHARED;
554 curexpb->e32_offset = address - PESection[i].address;
555 lastord = ordinal;
556 curexpb++;
557}
558//******************************************************************************
559//******************************************************************************
560void LXHeader::SetNrExtFixups(int nr)
561{
562int len;
563
564 exports = (char *)malloc(64+nr*(127+1+2)); //length byte, name (max 127) + ordinal (USHORT)
565 memset(exports, 0, 64+nr*(127+1+2));
566 if(nr > 0) {
567 expbundle = (exportbundle *)malloc(nr*max(sizeof(exportbundle), sizeof(forwardbundle)));
568 memset(expbundle, 0, nr*max(sizeof(exportbundle), sizeof(forwardbundle)));
569 }
570 curexpb = expbundle;
571
572 curexport = exports;
573 //First entry in resident name table is module name
574 strcpy(&curexport[1], modulename);
575 len = strlen(&curexport[1]);
576 *curexport = (char)len;
577 curexport += len+1;
578 *(USHORT *)curexport = 0;
579 curexport += sizeof(USHORT);
580#if 0
581 //first entry in export table is unused
582 curexpb->b32_cnt = 1;
583 curexpb->b32_type = EMPTY;
584 curexpb = (exportbundle *)&curexpb->b32_obj;
585#endif
586}
587//******************************************************************************
588//TODO: finish this
589//forward gives the DLL name and name of the export (i.e. MYDLL.expfunc or MYDLL.#27)
590//******************************************************************************
591#ifdef __WATCOMC__
592#pragma off (unreferenced)
593#endif
594void LXHeader::AddForwarder(char *name, int ordinal, char *forward)
595#ifdef __WATCOMC__
596#pragma on (unreferenced)
597#endif
598{
599#if 0
600
601 *curexport = (BYTE)strlen(name);
602 curexport++;
603 strncpy(curexport, name, 127);
604 curexport += strlen(name);
605 *(USHORT *)curexport = (USHORT)ordinal;
606 curexport += sizeof(USHORT);
607
608 nrexports++;
609#endif
610}
611//******************************************************************************
612//iets te veel, but who cares
613//******************************************************************************
614void LXHeader::SetNrOff32Fixups(int nr)
615{
616 intfixuprec = (intfixup *)malloc(nr*sizeof(intfixup));
617 memset(intfixuprec, 0, nr*sizeof(intfixup));
618}
619//******************************************************************************
620//******************************************************************************
621void LXHeader::AddOff32Fixup(int address)
622{
623 static intfixup crossedpage;
624 static BOOL fCrossed = FALSE;
625 static int crossedpageaddress = 0;
626 intfixup *frec;
627 int type, targetaddr;
628
629 frec = &intfixuprec[nrintfixups];
630 //Check if we need to insert a crossed page fixup
631 if(fCrossed == TRUE && address > crossedpageaddress) {
632 memcpy((char *)frec, (char *)&crossedpage, sizeof(crossedpage));
633 fCrossed = FALSE;
634 crossedpageaddress = 0;
635 nrintfixups++;
636 frec++;
637 }
638 frec->nr_stype = 0x07; //32 bits offset fixup
639 //internal fixup + 32 bits offset + 16 bits object nr
640 frec->nr_flags = 0x00 | 0x10 | 0x40;
641 frec->r32_soff = (SHORT)(address & 0xFFF);
642
643 type = GetSectionByAddress(address);
644 if(type == -1) {
645 cout << "Oops, fixup error 1.... at " << hex(address) << endl;
646 return; //hmmmmmmmmmm
647 }
648 frec->srcpage = (USHORT)GetAddressPage(address);
649 frec->srcobj = (USHORT)type;
650
651 //SvL: address could be aligned at 64 kb boundary, so correct address calculation
652 if(type == 0) { // +1 for tibfix page
653 assert(PESection[type].type & SECTION_CODE);
654 targetaddr = *(int *)(PESection[type].rawdata + (address - (PESection[type].address + (PESection[type].nrinvalidpages+1)*PAGE_SIZE)));
655 }
656 else targetaddr = *(int *)(PESection[type].rawdata + (address - (PESection[type].address + PESection[type].nrinvalidpages*PAGE_SIZE)));
657
658 //SvL: The target object might be the combined data section, so don't use
659 // GetSectionByAddress
660 type = GetRealSectionByAddress(targetaddr);
661 if(type == -1){
662 cout << "Oops, fixup error 2.... at " << hex(targetaddr) << endl;
663 return; //hmmmmmmmmmm
664 }
665
666 //SvL: If it's in the combined data section, the index is incorrect, so
667 // correct it
668 if(PESection[type].type == SECTION_COMBINEDDATA)
669 frec->targetobj = (USHORT)(1+1); //ASSUMPTION
670 else frec->targetobj = (USHORT)(type+1); //vanaf 1
671 frec->targetaddr = targetaddr - PESection[type].address; //relatief
672// cout << "src address " << frec->r32_soff << " srcpage " << frec->srcpage << " target " << frec->targetaddr << " frec " << (int)frec << endl;
673
674 //SvL: Check for fixups that cross page boundaries
675 // If I read the lx doc right, you need to add two fixups in
676 // this case, one for original page and one for original page + 1
677 //TODO: Doesn't work if the last page contains such a fixup!
678 if(frec->r32_soff + 4 > PAGE_SIZE) {
679 memcpy((char *)&crossedpage, (char *)frec, sizeof(crossedpage));
680 //crossed page boundary -> negative offset in next page
681 crossedpage.r32_soff = (SHORT)((frec->r32_soff & 0xFFF) - PAGE_SIZE);
682 crossedpage.srcpage = frec->srcpage+1;
683 crossedpageaddress = (address + PAGE_SIZE) & ~0xFFF;
684 fCrossed = TRUE;
685 }
686
687 nrintfixups++;
688}
689//******************************************************************************
690//SvL: 30-10-'97, assumption about sorting of fixups is incorrect, so:
691//ASSUMPTION: namefixup & ordfixup of same size
692//******************************************************************************
693void LXHeader::StoreAndSortImport(namefixup *newfrec)
694{
695 namefixup *frec;
696 namefixup *tmp;
697 int i;
698
699 if(nrimpfixups != 0) {
700 frec = &impfixuprec[nrimpfixups - 1];
701
702 if(newfrec->srcpage >= frec->srcpage) {
703 memcpy(&impfixuprec[nrimpfixups], newfrec, sizeof(namefixup));
704 nrimpfixups++;
705 return;
706 }
707 }
708 else {
709 memcpy(&impfixuprec[0], newfrec, sizeof(namefixup));
710 nrimpfixups++;
711 return;
712 }
713 tmp = (namefixup *)malloc(nrimpfixups*sizeof(namefixup));
714
715 frec = &impfixuprec[0];
716 for(i=0;i<nrimpfixups;i++) {
717 if(newfrec->srcpage < frec->srcpage) {
718 memcpy(tmp, frec, (nrimpfixups-i)*sizeof(namefixup));
719 memcpy(frec, newfrec, sizeof(namefixup));
720 memcpy(frec+1, tmp, (nrimpfixups-i)*sizeof(namefixup));
721 break;
722 }
723 frec++;
724 }
725 assert(i != nrimpfixups);
726 free(tmp);
727 nrimpfixups++;
728}
729//******************************************************************************
730//******************************************************************************
731void LXHeader::SetNoNameImports()
732{
733 impnames = (char *)malloc(16);
734 memset(impnames, 0, 16);
735 impnameoff = impnames + 1; //SvL: Bugfix: base 1
736 impnamesize = 0; //include ending 0
737}
738//******************************************************************************
739//******************************************************************************
740BOOL LXHeader::StoreImportByName(char *modname, int idxmod, char *name, int offset)
741{
742 namefixup frec;
743
744 if(impfixuprec == NULL) {
745 impfixuprec = (namefixup *)malloc(MAX_IMPORT*sizeof(namefixup));
746 memset(impfixuprec, 0, MAX_IMPORT*sizeof(namefixup));
747 }
748 if(impnames == NULL) {
749 impnames = (char *)malloc(128*1024); //moet genoeg zijn
750 memset(impnames, 0, 128*1024);
751 impnameoff = impnames + 1; //SvL: Bugfix: base 1
752 impnamesize = 1; //include ending 0
753 }
754
755 if(nrimpfixups >= MAX_IMPORT) {
756 cout << "Oops, too many imported functions...." << endl;
757 return(FALSE);
758 }
759
760 frec.nr_stype = 0x07; //32 bits offset
761 frec.nr_flags = 0x02 | 0x40; //import by name + mod offset = 16 bits
762 frec.r32_soff = (SHORT)(offset & 0xFFF); //offset within specific page
763 frec.r32_objmod = (USHORT)(idxmod+1); //vanaf 1!!!!!
764
765 impnameoff[0] = (char)strlen(name);
766 strcpy(&impnameoff[1], name);
767 frec.proc = (USHORT)((int)impnameoff-(int)impnames); //32 bits target flag not set!
768 frec.srcpage = (USHORT)GetAddressPage(offset);
769
770 impnamesize += impnameoff[0]+1;
771 impnameoff += impnameoff[0]+1;
772
773 StoreAndSortImport(&frec);
774 return(TRUE);
775}
776//******************************************************************************
777//******************************************************************************
778BOOL LXHeader::StoreImportByOrd(int idxmod, int ordinal, int offset)
779{
780 ordfixup frec;
781
782 if(impfixuprec == NULL) {
783 impfixuprec = (namefixup *)malloc(MAX_IMPORT*sizeof(namefixup));
784 memset(impfixuprec, 0, MAX_IMPORT*sizeof(namefixup));
785 }
786
787 if(nrimpfixups >= MAX_IMPORT) {
788 cout << "Oops, too many imported functions...." << endl;
789 return(FALSE);
790 }
791
792 frec.nr_stype = 0x07; //32 bits offset
793 frec.nr_flags = 0x01 | 0x40; //import by ordinal + mod offset = 16 bits
794 frec.r32_soff = (SHORT)(offset & 0xFFF); //offset within specific page
795 frec.r32_objmod = (USHORT)(idxmod+1); //vanaf 1!!!!!
796 frec.ord = (USHORT)ordinal;
797 frec.srcpage = (USHORT)GetAddressPage(offset);
798
799 StoreAndSortImport((namefixup *)&frec);
800 return(TRUE);
801}
802//******************************************************************************
803//******************************************************************************
804void LXHeader::StoreImportModules(char *modules, int nrmod)
805{
806int size = 0, i;
807char *src, *dest;
808
809///-4*nrmod = - 4 * .dll
810 impmodules = (char *)malloc(nrmod*9 + 32); /*PLF Sun 97-06-22 00:51:12*/
811 impmodulesize = 0;
812
813 src = modules;
814 dest = impmodules;
815 for(i=0;i<nrmod;i++) {
816 size = min(strlen(src), 12);
817 dest[0] = (char)(size-4);
818 dest++;
819 strncpy(dest, src, size-4);
820 dest[size-4] = 0; // !!!
821 UpCase(dest);
822
823/* @@@PH 98/06/13 NTDLL is available now */
824// if(strcmp(dest, "NTDLL") == 0) {
825// strcpy(dest, "KERNEL32");
826// dest[-1] = 8; //change module name length
827// dest += 8;
828// }
829// else
830
831
832 if(strcmp(dest, "NETAPI32") == 0) {//SvL: Name conflict with MUGLIB\DLL\NETAPI32.DLL
833 strcpy(dest, "WNETAP32");
834 dest += size-4;
835 }
836 else {
837 if(strcmp(dest, "KERNEL32") == 0) {
838 kernel32Object = i;
839 }
840 dest += size-4;
841 }
842 src += strlen(src) + 1; //+ null byte
843 }
844 if(kernel32Object == -1) { //add kernel32
845 kernel32Object = nrmod;
846 dest[0] = 8;
847 strcpy(&dest[1], "KERNEL32");
848 dest += 9;
849 nrmod++;
850 }
851 LXHdr.e32_impmodcnt = nrmod;
852 dest[0] = 0; //end of array
853 impmodulesize = (int)dest - (int)impmodules;
854}
855//******************************************************************************
856char *sysmodules[] = {"KERNEL32",
857 "USER32",
858 "GDI32",
859 "WINMM",
860 "DSOUND",
861 "DDRAW",
862 "WNETAP32",
863 "MPR",
864 "OLE32",
865 "ADVAPI32",
866 "COMMDLG",
867 "NTDLL",
868 "WINSPOOL",
869 "SHELL32",
870 "TAPI32",
871 "CAPI32",
872 "VERSION",
873 "WSOCK32"};
874
875//******************************************************************************
876BOOL LXHeader::IsSystemModule(char *mod, int size)
877{
878 int i;
879
880 for(i=0;i<sizeof(sysmodules)/sizeof(char *);i++) {
881 if(!strncmp(mod, sysmodules[i], size))
882 return(TRUE);
883 }
884 return(FALSE);
885}
886//******************************************************************************
887//******************************************************************************
888int LXHeader::FindName(char *table, int index)
889{
890int i, offset = 0;
891
892 for(i=0;i<index-1;i++) {
893 offset += table[0] + 1;
894 table = table + table[0] + 1;
895 }
896 return(offset);
897}
898//******************************************************************************
899//******************************************************************************
900BOOL LXHeader::SaveNewExeFile(char *filename)
901{
902 HFILE win32handle;
903 ULONG ulAction = 0; /* Action taken by DosOpen */
904 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
905 ULONG ulWrite;
906 APIRET rc;
907 struct o32_obj objtable;
908 struct o32_map *objpage;
909 int pagetblidx, i, j, k, idx, rawsize, objectsize;
910 int nrpages, pagedataoffset, fFirstCode = FALSE;
911 int *fixuptable;
912 char modname[128];
913 intfixup *frec;
914 namefixup *imprec;
915 realintfixup *frealrec, *currealrec;
916
917 rc = DosOpen(filename, /* File path name */
918 &win32handle, /* File handle */
919 &ulAction, /* Action taken */
920 0L, /* File primary allocation */
921 0L, /* File attribute */
922 OPEN_ACTION_CREATE_IF_NEW |
923 OPEN_ACTION_REPLACE_IF_EXISTS, /* Open function type */
924 OPEN_FLAGS_NOINHERIT |
925 OPEN_SHARE_DENYNONE |
926 OPEN_ACCESS_READWRITE, /* Open mode of the file */
927 0L); /* No extended attribute */
928
929 if (rc != NO_ERROR) {
930 cout << "DosOpen returned " << rc << endl;
931 return(FALSE);
932 }
933 /* Move the file pointer back to the beginning of the file */
934 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
935
936 rc = DosWrite(win32handle, szDosHeader, sizeof(szDosHeader), &ulWrite);
937 if(rc != NO_ERROR) {
938 cout << "DosWrite returned " << rc << endl;
939 DosClose(win32handle); /* Close the file */
940 return(FALSE);
941 }
942 //write preliminary lx header
943 DosWrite(win32handle, &LXHdr, sizeof(LXHdr), &ulWrite);
944
945 //First take care of the resources (if present), so GetNrPages()
946 //works correctly
947 if(nrresources) {
948 ResSection.virtualsize = ResSection.curoff;
949 ResSection.rawsize = ResSection.curoff;
950 } //done with resources
951
952 pagetblidx = 1; //start met 1
953 objtable.o32_reserved = 0;
954 pagedataoffset = 0;
955 nrpages = GetNrPages();
956 objpage = (struct o32_map *)malloc((nrpages)*sizeof(o32_map));
957
958 LXHdr.e32_objcnt = GetNrObjects();
959 LXHdr.e32_mpages = 0;
960 idx = -1;
961 int objcnt = 1;
962
963 for(i=0;i<nrsections;i++) {
964 objtable.o32_pagemap = pagetblidx;
965 if(PESection[i].fInvalid) continue;
966
967 switch(PESection[i].type) {
968 case (SECTION_CODE | SECTION_IMPORT):
969 case SECTION_CODE:
970 objtable.o32_flags = OBJREAD | NSEXRD | OBJBIGDEF;
971 if(fFirstCode == FALSE)
972 LXHdr.e32_startobj = i+1;
973 break;
974 case SECTION_IMPORT:
975 objtable.o32_flags = OBJREAD | OBJBIGDEF;
976 break;
977 case SECTION_INITDATA:
978 objtable.o32_flags = OBJREAD | OBJWRITE | OBJBIGDEF;
979 break;
980 case SECTION_COMBINEDDATA:
981 objtable.o32_flags = OBJREAD | OBJWRITE | OBJBIGDEF;
982 LXHdr.e32_startobj = 1;
983 break;
984 case SECTION_RESOURCE_ORG:
985 case SECTION_UNINITDATA:
986 //SvL: Zero filled flag maps on Permanent flag, so ditch it
987 objtable.o32_flags = OBJREAD | OBJWRITE | OBJBIGDEF; //read/write/big
988 break;
989 case SECTION_READONLYDATA:
990 objtable.o32_flags = OBJREAD | OBJBIGDEF;
991 break;
992 }
993 //OS/2 doesn't seem to mind if the sizes of all the pages in an object
994 //exceeds the object size....
995 if(PESection[i].type == SECTION_UNINITDATA)
996 objectsize = PESection[i].virtualsize; //rawsize == 0
997 else objectsize = PESection[i].rawsize;
998
999 objtable.o32_mapsize = PESection[i].nrpages;
1000
1001 objtable.o32_mapsize += PESection[i].nrinvalidpages;
1002 objtable.o32_base = PESection[i].address;
1003 objtable.o32_size = objtable.o32_mapsize*PAGE_SIZE;
1004
1005 rawsize = PESection[i].rawsize;
1006 for(j=0;j<objtable.o32_mapsize;j++) {
1007 idx = pagetblidx+j-1;
1008 objpage[idx].o32_pagedataoffset = pagedataoffset;
1009
1010 if(j < PESection[i].nrinvalidpages) {
1011 objpage[idx].o32_pagesize = 0;
1012//SvL: Invalid pages are not properly handled by the OS/2 loader -> make 'em zeroed
1013 objpage[idx].o32_pageflags = ZEROED;
1014 }
1015 else {
1016 if(PESection[i].type == SECTION_COMBINEDDATA) {
1017 if(j == PESection[i].nrinvalidpages) {
1018 objpage[idx].o32_pagesize = (USHORT)(TIBSize);
1019 objpage[idx].o32_pageflags = 0;
1020 pagedataoffset += TIBSize;
1021 LXHdr.e32_mpages++;
1022 //Modify entry point address, and write original to TIBFix code
1023 *(LONG *)&szTIBFix[TIBOffEntry] = LXHdr.e32_eip + PAGE_SIZE - TIBOffCall - SIZE_TIBCALL;
1024 LXHdr.e32_eip = PAGE_SIZE*PESection[i].nrinvalidpages;
1025 objtable.o32_size = objtable.o32_mapsize*PAGE_SIZE;
1026 }
1027 else {
1028 int didx = j - PESection[i].nrinvalidpages;
1029 objpage[idx].o32_pagesize = datapage[didx].size;
1030 objpage[idx].o32_pageflags = datapage[didx].flags;
1031 pagedataoffset += objpage[idx].o32_pagesize;
1032 if(objpage[idx].o32_pageflags == 0)
1033 LXHdr.e32_mpages++;
1034 }
1035 }
1036 else
1037 if(PESection[i].type == SECTION_UNINITDATA || rawsize == 0) {
1038 objpage[idx].o32_pagesize = 0;
1039 objpage[idx].o32_pagedataoffset = pagedataoffset;
1040 objpage[idx].o32_pageflags = ZEROED;
1041 }
1042 else //take care of TIBFix code!
1043 if(fFirstCode == FALSE && PESection[i].type & SECTION_CODE && j == PESection[i].nrinvalidpages) {
1044 objpage[idx].o32_pagesize = (USHORT)TIBSize;
1045 objpage[idx].o32_pageflags = 0;
1046 pagedataoffset += TIBSize;
1047 LXHdr.e32_mpages++;
1048 //Modify entry point address, and write original to TIBFix code
1049 *(LONG *)&szTIBFix[TIBOffEntry] = LXHdr.e32_eip + PAGE_SIZE - TIBOffCall - SIZE_TIBCALL;
1050
1051 LXHdr.e32_eip = PAGE_SIZE*PESection[i].nrinvalidpages;
1052 }
1053 else {
1054 if(rawsize > PAGE_SIZE)
1055 objpage[idx].o32_pagesize = PAGE_SIZE;
1056 else objpage[idx].o32_pagesize = rawsize;
1057 rawsize -= objpage[idx].o32_pagesize;
1058 objpage[idx].o32_pageflags = 0;
1059 LXHdr.e32_mpages++;
1060 pagedataoffset += objpage[idx].o32_pagesize;
1061 }
1062 }
1063 }
1064
1065 if(IsEXE && i == nrsections - 1)
1066 {//SvL: 25-7-'97 Add stack pages to last data object
1067 LXHdr.e32_stackobj = objcnt;
1068 LXHdr.e32_autodata = LXHdr.e32_stackobj;
1069 objtable.o32_flags |= OBJWRITE;
1070 objtable.o32_size += StackSize;
1071 LXHdr.e32_esp = objtable.o32_size; //highest address in object
1072 }
1073
1074 //Write object table entry to file
1075 DosWrite(win32handle, &objtable, sizeof(objtable), &ulWrite);
1076
1077 if(PESection[i].type & SECTION_CODE)
1078 fFirstCode = TRUE; //dealt with first code section
1079
1080 pagetblidx += objtable.o32_mapsize;
1081 objcnt++;
1082 }
1083 if(nrresources) {
1084 //Correct count in case there are string tables which aren't completely filled
1085 nrresources = curresource;
1086 //Process Resource Object
1087 LXHdr.e32_objcnt++;
1088 objtable.o32_pagemap = pagetblidx;
1089 objtable.o32_flags = NSSHARED | OBJREAD | OBJRSRC | OBJBIGDEF;
1090 objtable.o32_mapsize = ResSection.rawsize >> PAGE_SHIFT;
1091
1092 objtable.o32_base = 0; //SvL: Set to 0 in PM exes (plf)
1093 objtable.o32_size = ResSection.rawsize;
1094
1095 for(j=0;j<objtable.o32_mapsize;j++) {
1096 idx = pagetblidx+j-1;
1097 objpage[idx].o32_pagedataoffset = pagedataoffset;
1098 objpage[idx].o32_pagesize = PAGE_SIZE;
1099 objpage[idx].o32_pageflags = 0;
1100 LXHdr.e32_mpages++;
1101 pagedataoffset += PAGE_SIZE;
1102 }
1103 if((objtable.o32_size & 0xFFF) != 0) {
1104 objtable.o32_mapsize++;
1105 LXHdr.e32_mpages++;
1106 idx++;
1107 objpage[idx].o32_pagedataoffset = pagedataoffset;
1108 objpage[idx].o32_pagesize = (USHORT)(objtable.o32_size & 0xFFF);
1109 objpage[idx].o32_pageflags = 0;
1110 pagedataoffset += objpage[idx].o32_pagesize;
1111 }
1112
1113 //Write resource object table to file
1114 DosWrite(win32handle, &objtable, sizeof(objtable), &ulWrite);
1115 pagetblidx += objtable.o32_mapsize;
1116
1117 //fill in object nr's in resource table entries
1118 for(i=0;i<nrresources;i++) {
1119 os2resource[i].obj = LXHdr.e32_objcnt;
1120 }
1121 }
1122
1123 //Write object page table entries to file
1124 DosWrite(win32handle, objpage, sizeof(*objpage)*nrpages, &ulWrite);
1125
1126 //object page records offset:
1127 LXHdr.e32_objmap = LXHdr.e32_objtab + LXHdr.e32_objcnt*sizeof(objtable);
1128 //size tables vanaf object table t/m impproc (eigenlijk pagesum ook..)
1129 LXHdr.e32_ldrsize = LXHdr.e32_objcnt*sizeof(objtable) + nrpages*sizeof(o32_map);
1130
1131 //resource table:
1132 LXHdr.e32_rsrctab = LXHdr.e32_ldrsize + LXHdr.e32_objtab;
1133 LXHdr.e32_rsrccnt = nrresources;
1134 if(nrresources) {
1135 DosWrite(win32handle, (char *)os2resource, nrresources*sizeof(rsrc32), &ulWrite);
1136 }
1137 LXHdr.e32_ldrsize += nrresources*sizeof(rsrc32);
1138
1139 //resident name table + entry table:
1140 LXHdr.e32_restab = LXHdr.e32_rsrctab + nrresources*sizeof(rsrc32);
1141 if(IsEXE == TRUE) {
1142 int modlen;
1143 //save resident name table
1144 memset(modname, 0, sizeof(modname));
1145 strcpy(&modname[1], modulename);
1146 UpCase(&modname[1]);
1147 modlen = strlen(&modname[1]);
1148 modname[0] = (char)modlen;
1149 modlen += 1 + 2 + 1; //len byte + ord word + 0 byte
1150 DosWrite(win32handle, modname, modlen, &ulWrite);
1151
1152 //save entry table
1153 LXHdr.e32_enttab = LXHdr.e32_restab + modlen; //points to 0 byte
1154 modname[0] = 0;
1155 DosWrite(win32handle, modname, 1, &ulWrite);
1156 LXHdr.e32_ldrsize += 1 + modlen;
1157 }
1158 else {//write DLL export information
1159 int len = 0;
1160
1161 //save resident name table
1162 if(exports) {
1163 len = curexport - exports + 1; // + 0 byte to signal end of table
1164 rc = DosWrite(win32handle, exports, len, &ulWrite);
1165 LXHdr.e32_ldrsize += len;
1166 }
1167
1168 //save entry table
1169 LXHdr.e32_enttab = LXHdr.e32_restab + len;
1170 //TODO: Forwarders!
1171 len = (int)curexpb - (int)expbundle + 1; // + 0 byte to signal end of table
1172 if(len > 1) {
1173 rc = DosWrite(win32handle, expbundle, len, &ulWrite);
1174 LXHdr.e32_ldrsize += len;
1175 }
1176 }
1177
1178 //#pages * offset naar import fixups + 1 eind offset
1179 LXHdr.e32_fpagetab = LXHdr.e32_ldrsize + LXHdr.e32_objtab;
1180 LXHdr.e32_frectab = LXHdr.e32_fpagetab + (nrpages+1)*sizeof(int);
1181 fixuptable = (int *)malloc((nrpages+1)*sizeof(int));
1182 for(i=0;i<nrpages+1;i++) fixuptable[i] = 0;
1183
1184 //dump alle fixup records in 1 memory block en bepaal offsets in fixup page table
1185 frec = &intfixuprec[0];
1186 imprec = &impfixuprec[0];
1187 frealrec = (realintfixup *)malloc(nrintfixups*sizeof(realintfixup)+(nrimpfixups+EXTRA_FIXUPS)*sizeof(realnamefixup));
1188 currealrec = frealrec;
1189 j = 0;
1190 k = 0;
1191 for(i=0;i<nrpages;i++) {
1192 fixuptable[i] = (int)currealrec - (int)frealrec;
1193 if(i == 0) {//add kernel32:registerresourceinfo import
1194 realordfixup *kerord = (realordfixup *)currealrec;
1195 kerord->nr_stype = 0x07; //32 bits offset
1196 kerord->nr_flags = 0x01 | 0x40; //import by ordinal + mod offset = 16 bits
1197 kerord->r32_soff = TIBOffKerImport;
1198 kerord->r32_objmod = kernel32Object + 1;
1199 if(IsEXE)
1200 kerord->ord = ORD_REGISTERRESOURCEINFO;
1201 else kerord->ord = ORD_REGISTERDLL;
1202
1203 currealrec = (realintfixup *)((int)currealrec + sizeof(realnamefixup));
1204 if(!IsEXE) {
1205 kerord = (realordfixup *)currealrec;
1206 kerord->nr_stype = 0x08; //32 bits self referencing offset
1207 kerord->nr_flags = 0x01 | 0x40; //import by ordinal + mod offset = 16 bits
1208 kerord->r32_soff = DLL_OFF_KERIMP2;
1209 kerord->r32_objmod = kernel32Object + 1;
1210 kerord->ord = ORD_KERNEL32DLLEXITLIST;
1211 currealrec = (realintfixup *)((int)currealrec + sizeof(realnamefixup));
1212 }
1213 }
1214 //SvL: 16-9-'97, for multiple import pages
1215 while(k < nrimpfixups && imprec->srcpage == i) {
1216 //sizeof(realordfixup) == sizeof(realnamefixup)
1217 memcpy(currealrec, imprec, sizeof(realnamefixup));
1218 currealrec = (realintfixup *)((int)currealrec + sizeof(realnamefixup));
1219 imprec++;
1220 k++;
1221 }
1222 while( j < nrintfixups && frec->srcpage == i) {
1223 memcpy(currealrec, frec, sizeof(realintfixup));
1224// cout << "src address " << frec->r32_soff << " srcpage " << frec->srcpage << " target " << frec->targetaddr << " frec " << (int)frec << endl;
1225 frec++;
1226 currealrec++;
1227 j++;
1228 }
1229 }
1230 fixuptable[nrpages] = (int)currealrec - (int)frealrec;
1231
1232 //Add extra kernel32 imports
1233 if(IsEXE)
1234 nrimpfixups++;
1235 else nrimpfixups += EXTRA_FIXUPS;
1236
1237 //Write fixup page table
1238 DosWrite(win32handle, fixuptable, (nrpages+1)*sizeof(int), &ulWrite);
1239 //Write fixup record table
1240 DosWrite(win32handle, frealrec, nrintfixups*sizeof(realintfixup)+nrimpfixups*sizeof(realnamefixup), &ulWrite);
1241 free(frealrec);
1242 free(fixuptable);
1243
1244 //fixup page + record + import name + module table size
1245 LXHdr.e32_fixupsize = (nrpages+1)*sizeof(int) + nrimpfixups*sizeof(realnamefixup) + nrintfixups*sizeof(realintfixup) + impmodulesize + impnamesize;
1246
1247 //size tables vanaf object table t/m impproc (eigenlijk pagesum ook..)
1248 LXHdr.e32_ldrsize += LXHdr.e32_fixupsize;
1249
1250 //offset naar module name array
1251 LXHdr.e32_impmod = LXHdr.e32_frectab + nrimpfixups*sizeof(realnamefixup) + nrintfixups*sizeof(realintfixup);
1252 //offset naar proc name array
1253 LXHdr.e32_impproc = LXHdr.e32_impmod + impmodulesize;
1254 //Write Import Module array
1255 DosWrite(win32handle, impmodules, impmodulesize, &ulWrite);
1256 //Write Import Procedure Name array
1257 if(impnamesize) {
1258 DosWrite(win32handle, impnames, impnamesize, &ulWrite);
1259 }
1260
1261 //pointer naar begin code/data
1262 LXHdr.e32_datapage = LXHdr.e32_impproc + impnamesize + LXHEADER_OFFSET; //vanaf begin ipv lxheader
1263
1264 fFirstCode = FALSE; //TIBfix only for first code object
1265 for(i=0;i<nrsections;i++) {
1266 //zero filled pages, niet nodig om op te slaan
1267 if(PESection[i].type != SECTION_UNINITDATA && PESection[i].rawdata) {
1268 //Put our special TIB fix to code section first! (SvL: 30-7-'97)
1269 if(PESection[i].type & SECTION_CODE && fFirstCode == FALSE) {
1270 DosWrite(win32handle, szTIBFix, TIBSize, &ulWrite);
1271 fFirstCode = TRUE;
1272 }
1273 DosWrite(win32handle, PESection[i].rawdata, PESection[i].rawsize, &ulWrite);
1274 }
1275 }
1276 if(nrresources)
1277 DosWrite(win32handle, ResSection.rawdata, ResSection.rawsize, &ulWrite);
1278
1279 DosSetFilePtr(win32handle, LXHEADER_OFFSET, FILE_BEGIN, &ulLocal);
1280 //write final lx header
1281 DosWrite(win32handle, &LXHdr, sizeof(LXHdr), &ulWrite);
1282
1283 free(objpage);
1284 DosClose(win32handle); /* Close the file */
1285 return(TRUE);
1286}
1287//******************************************************************************
1288//Requires fixing the resource size (as done in savenewexe)
1289//******************************************************************************
1290int LXHeader::GetNrPages()
1291{
1292 int i, nrpages = 0;
1293
1294 for(i=0;i<nrsections;i++) {
1295 if(PESection[i].fInvalid)
1296 continue;
1297 nrpages += PESection[i].nrpages + PESection[i].nrinvalidpages;
1298 }
1299//SvL: 13 aug 1998
1300#if 0
1301 if(IsEXE) {
1302 nrpages += StackSize >> PAGE_SHIFT;
1303 if(StackSize & 0xFFF) nrpages++;
1304 }
1305#endif
1306 if(nrresources) {
1307 nrpages += ResSection.virtualsize >> PAGE_SHIFT;
1308 if(ResSection.rawsize & 0xFFF) nrpages++;
1309 }
1310 return(nrpages);
1311}
1312//******************************************************************************
1313//******************************************************************************
1314void LXHeader::UpCase(char *mixedcase)
1315{
1316 int i;
1317
1318 for(i=0;i<strlen(mixedcase);i++) {
1319 if(mixedcase[i] >= 'a' && mixedcase[i] <= 'z') {
1320 mixedcase[i] += 'A' - 'a';
1321 }
1322 }
1323}
1324//******************************************************************************
1325//******************************************************************************
1326void LXHeader::SetModuleType(int type)
1327{
1328 LXHdr.e32_mflags |= E32PMAPI;
1329
1330 if(IsEXE) //don't set it for dlls (in case this flag is accidentally set in the header)
1331 fConsole = (type == SYSTEM_CHARACTER);
1332}
1333//******************************************************************************
1334//******************************************************************************
1335int LXHeader::GetAddressPage(int address)
1336{
1337 int i, page = 0;
1338
1339 for(i=0;i<nrsections;i++) {
1340 if(PESection[i].fInvalid)
1341 continue;
1342 if(address > PESection[i].endaddress) {
1343 page += PESection[i].nrpages + PESection[i].nrinvalidpages;
1344 }
1345 else {
1346 page += ((address - PESection[i].address) >> PAGE_SHIFT);
1347 break;
1348 }
1349 }
1350 return(page);
1351}
1352//******************************************************************************
1353//******************************************************************************
1354int LXHeader::GetSection(int type)
1355{
1356 int i;
1357
1358 for(i=0;i<nrsections;i++) {
1359 if(PESection[i].type & type) {
1360 return(i);
1361 }
1362 }
1363 return(-1);
1364}
1365//******************************************************************************
1366//SvL: Ignore combined data section, since we use the rawdata pointer
1367//******************************************************************************
1368int LXHeader::GetSectionByAddress(int address)
1369{
1370 int i;
1371
1372 for(i=0;i<nrsections;i++) {
1373 if(PESection[i].rawdata) {
1374 if(PESection[i].address <= address && PESection[i].endaddress > address ) {
1375 return(i);
1376 }
1377 }
1378 }
1379 return(-1);
1380}
1381//******************************************************************************
1382//SvL: Ignore sections combined into one data section
1383//******************************************************************************
1384int LXHeader::GetRealSectionByAddress(int address)
1385{
1386 int i;
1387
1388 for(i=0;i<nrsections;i++) {
1389 if(PESection[i].fInvalid) continue;
1390 if(PESection[i].rawdata || PESection[i].type == SECTION_COMBINEDDATA) {
1391 if(PESection[i].address <= address && PESection[i].endaddress > address ) {
1392 return(i);
1393 }
1394 }
1395 }
1396 return(-1);
1397}
1398//******************************************************************************
1399//******************************************************************************
1400int LXHeader::GetSectionLEAddress(int address)
1401{
1402 int i;
1403
1404 for(i=0;i<nrsections;i++) {
1405 if(PESection[i].fInvalid) continue;
1406 if(PESection[i].rawdata) {
1407 if(PESection[i].address > address) {
1408 return(i-1);
1409 }
1410 }
1411 }
1412 return(-1);
1413}
1414//******************************************************************************
1415//******************************************************************************
1416char *LXHeader::StripPath(char *path) //niets aan de string veranderen!!
1417{
1418 while(strchr(path, '\\') != NULL) {
1419 path++;
1420 }
1421 return(path);
1422}
1423/******************************************************************************/
1424/******************************************************************************/
1425char *LXHeader::StripExtension(char *fname)
1426{
1427 char *tmp = fname;
1428
1429 while(strchr(fname, '.') != NULL) {
1430 fname++;
1431 }
1432 fname--;
1433 *fname = 0;
1434 return(tmp);
1435}
1436/******************************************************************************/
1437/******************************************************************************/
1438int LXHeader::GetUniqueId()
1439{
1440 int i, j, id;
1441
1442 for(j=0;j<65536;j++) {
1443 for(i=0;i<nrids;i++) {
1444 if(uniqueId == resids[i]) {
1445 break;
1446 }
1447 }
1448 if(i == nrids) {
1449 id = uniqueId;
1450 resids[nrids] = id;
1451 nrids++;
1452 uniqueId = (uniqueId + 1) & 0xFFFF;
1453 return(id);
1454 }
1455 uniqueId = (uniqueId + 1) & 0xFFFF;
1456 }
1457 cout << "No ids left!!!!" << endl;
1458 assert(FALSE);
1459 return(0);
1460}
1461/******************************************************************************/
1462/******************************************************************************/
1463void LXHeader::SetNrResources(int cnt)
1464{
1465 cout << "Nr of resources: " << cnt << endl;
1466
1467 //+2 for resource name lookup table and original res lookup table
1468 nrresources = cnt+2;
1469 //reserve space for original win32 resources + strings
1470 os2resource = (rsrc32 *)malloc((nrresources*16)*sizeof(rsrc32));
1471 memset(os2resource, 0, nrresources*16*sizeof(rsrc32));
1472 cvtname = (NameId *)malloc(cnt*(sizeof(NameId)+256));
1473 curcvtname = (NameId *)((char *)cvtname+sizeof(USHORT)); //first USHORT = nr of converted names
1474 memset(cvtname, 0, cnt*(sizeof(NameId)+256));
1475
1476 //temporary storage for used resource ids (*16 since menus use getuniqueid too)
1477 resids = (int *)malloc(nrresources*16*sizeof(int));
1478 memset(resids, 0, nrresources*16*sizeof(int));
1479
1480 //table used in LockResource (kernel32) to return the original win32 resource
1481 //layout: 1st ULONG nr of entries
1482 // nth ULONG (n>1) 0xAAAABBBB, AAAA=org id, BBBB=OS/2 id
1483 orgrestable = (ULONG *)malloc((nrresources+1)*sizeof(ULONG));
1484 memset(orgrestable, 0, (nrresources+1)*sizeof(ULONG));
1485}
1486//******************************************************************************
1487//******************************************************************************
1488void LXHeader::StoreResourceId(int id)
1489{
1490 resids[nrids] = id;
1491 nrids++;
1492}
1493/******************************************************************************/
1494/******************************************************************************/
1495void LXHeader::StoreWin32Resource(int id, int type, int size, char *resourcedata)
1496{
1497 int newid = GetUniqueId();
1498
1499 //First entry used for nr of entries, so + 1
1500 orgrestable[nrorgres+1] = ((id & 0xFFFF) << 16) + (newid & 0xFFFF);
1501 nrorgres++;
1502
1503 //store them all as rcdata
1504 StoreResource(newid, RT_RCDATA, size, resourcedata);
1505}
1506/******************************************************************************/
1507/******************************************************************************/
1508void LXHeader::StoreResource(int id, int type, int size, char *resourcedata)
1509{
1510 static BOOL fFirstIcon = FALSE;
1511 char *tmpbuf;
1512 int i, newsize;
1513
1514 if(type == RT_POINTER && fFirstIcon == FALSE && curresource > 0) {
1515 //put this one in front of all resources so OS/2 recognizes
1516 //it as the program object icon
1517 tmpbuf = (char *)malloc(curresource*sizeof(rsrc32)+ResSection.curoff);
1518 memcpy(tmpbuf, (char *)os2resource, curresource*sizeof(rsrc32));
1519 memcpy((char *)&os2resource[1], tmpbuf, curresource*sizeof(rsrc32));
1520 memcpy(tmpbuf, ResSection.rawdata, ResSection.curoff);
1521 memcpy(ResSection.rawdata, resourcedata, size);
1522 //SvL: Align all resources on 4 byte boundary
1523 newsize = (size + 3) & ~3;
1524 for(i=0;i<newsize-size;i++) {
1525 ResSection.rawdata[size+i] = 0;
1526 }
1527 memcpy(ResSection.rawdata+newsize, tmpbuf, ResSection.curoff);
1528
1529 os2resource[0].type = (USHORT)type;
1530 os2resource[0].name = (USHORT)id;
1531 os2resource[0].cb = size;
1532 os2resource[0].offset = 0;
1533 //modify all offsets
1534 for(i=1;i<=curresource;i++) {
1535 os2resource[i].offset += newsize;
1536 }
1537 free(tmpbuf);
1538 }
1539 else {
1540 assert(ResSection.curoff + size < ResSection.rawsize);
1541 memcpy(ResSection.rawdata+ResSection.curoff, resourcedata, size);
1542 //SvL: Align all resources on 4 byte boundary
1543 newsize = (size + 3) & ~3;
1544 for(i=0;i<newsize-size;i++) {
1545 ResSection.rawdata[ResSection.curoff+size+i] = 0;
1546 }
1547 os2resource[curresource].type = (USHORT)type;
1548 os2resource[curresource].name = (USHORT)id;
1549 os2resource[curresource].cb = size;
1550 os2resource[curresource].offset = ResSection.curoff;
1551 }
1552
1553 ResSection.curoff += newsize;
1554 curresource++;
1555 return;
1556}
1557/******************************************************************************/
1558/******************************************************************************/
1559void LXHeader::SetResourceSize(int size)
1560{
1561 ResSection.virtualsize = ResSection.rawsize = size*4; //just to be sure
1562 ResSection.rawdata = (char *)malloc(ResSection.rawsize);
1563 memset(ResSection.rawdata, 0, ResSection.rawsize);
1564}
1565/******************************************************************************/
1566/******************************************************************************/
1567int LXHeader::ConvertNametoId(char *name)
1568{
1569 NameId *resname = (NameId *)((USHORT *)cvtname + 1);
1570 int id;
1571 int i;
1572
1573 for(i=0;i<nrcvtnames;i++) {//check if this name is already converted
1574 if(strcmpi(name, resname->name) == 0)
1575 return(resname->id);
1576 resname = (NameId *)((int)resname + sizeof(NameId) + strlen(resname->name));
1577 }
1578 //Not found, so create one
1579 id = GetUniqueId();
1580 curcvtname->id = id;
1581 strcpy(curcvtname->name, name);
1582 curcvtname = (NameId *)((int)curcvtname + sizeof(NameId) + strlen(name));
1583 nrcvtnames++;
1584 return(id);
1585}
1586/******************************************************************************/
1587/******************************************************************************/
1588void LXHeader::SaveConvertedNames()
1589{
1590 if(nrcvtnames) {
1591 //first USHORT = nr of converted names
1592 *(USHORT *)cvtname = nrcvtnames;
1593 cvtnametableid = GetUniqueId();
1594
1595 //fill in parameter for RegisterResourceInfo
1596 *(LONG *)&szTIBFix[TIBOffName] = cvtnametableid;
1597
1598 StoreResource(cvtnametableid, RT_RCDATA, (int)curcvtname - (int)cvtname, (char *)cvtname);
1599 }
1600 if(nrorgres) {
1601 //first ULONG = nr of original win32 resources stored in OS/2 exe/dll
1602 orgrestable[0] = nrorgres;
1603 orgrestableid = GetUniqueId();
1604
1605 //fill in parameter for RegisterResourceInfo
1606 *(LONG *)&szTIBFix[TIBOffName+5] = (fConsole << 24) | orgrestableid;
1607
1608 StoreResource(orgrestableid, RT_RCDATA, (nrorgres+1)*sizeof(ULONG), (char *)orgrestable);
1609 }
1610 else {
1611 *(LONG *)&szTIBFix[TIBOffName+5] = (fConsole << 24) | 0x888888;
1612 }
1613 //SvL: 18-7-'98: Store internal pe2lx version and version resource id
1614 *(LONG *)&szTIBFix[TIBOffPe2lxVer] = PE2LX_VERSION;
1615 *(LONG *)&szTIBFix[TIBOffVerResId] = VersionResourceId;
1616}
1617/******************************************************************************/
1618/******************************************************************************/
1619int LXHeader::uniqueId = RESID_CONVERTEDNAMES;
Note: See TracBrowser for help on using the repository browser.