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

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

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

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