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

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

Major changes in PE2LX/KERNEL32 for TLS support. DLL VERSION INCREASED TO 3 AS THIS CHANGE MAKES IT INCOMPATIBLE WITH APPS CONVERTED WITH PREVIOUS VERSION OF PE2LX (OR WIN32K)

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