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

Last change on this file since 4 was 4, checked in by ktk, 26 years ago

Import

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