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

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

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

File size: 52.8 KB
Line 
1/* $Id: lxsuper.cpp,v 1.1 1999-09-06 02:20:06 bird 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
15/*******************************************************************************
16* Header Files *
17*******************************************************************************/
18#include "pe2lx.h" //KSO Tue 2nd June 1998
19
20#include <versionos2.h>
21
22char *hex(ULONG num);
23
24
25/** Borrowed dos header from executables generated by Watcom */
26unsigned char achDosHeader[DOSHEADER_SIZE] = {
27 0x4D, 0x5A, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
28 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
31 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x74, 0x68,
32 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x6E, 0x20, 0x4F, 0x53, 0x2F, 0x32, 0x20, 0x33, 0x32,
33 0x2D, 0x62, 0x69, 0x74, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x0D,
34 0x0A, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
35
36
37/** Register module in kernel32 (resource managment) for EXEs:
38// push [esp+4] ;instance handle
39// push internal pe2lx version
40// push version resource id
41// push name_lookup_tableid
42// push orgres_lookup_tableid
43// mov ecx, KERNEL32:RegisterResourceInfo (stdcall)
44// call ecx
45//
46// call original_entrypoint
47// ret
48*/
49/** <br>Exe TIBFix code */
50unsigned char achEXETIBFix[EXETIBFIX_SIZE] = {
51//push [esp+4]
52 0xFF, 0x74, 0x24, 0x04,
53//SvL: 18-7-'98: push internal pe2lx version
54 0x68, 0x00, 0x00, 0x00, 0x00,
55//SvL: 18-7-'98: push version resource id (-1 = no version resource present)
56 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
57//push [table id1] (kernel32 proc depends on 0x77777777 & 0x88888888!!)
58//Svl: So does void LXHeaderSuper::SaveConvertedNames()!
59 0x68, 0x77, 0x77, 0x77, 0x77,
60//push [table id1]
61 0x68, 0x88, 0x88, 0x88, 0x88,
62//mov ecx, KERNEL32:RegisterResourceInfo (stdcall)
63 0xB9, 0x99, 0x99, 0x99, 0x99,
64//call ecx
65 0xFF, 0xD1,
66//call entrypoint
67 0xE8, 0x8C, 0xFF, 0xFF, 0xFF,
68//ret
69 0xC3
70};
71
72
73
74/** Register module in kernel32 (resource managment) for DLLs:
75// cmp [esp+8], 1
76// je detach
77// push [esp+4] ;instance handle
78// push internal pe2lx version
79// push version resource id
80// push name_lookup_tableid
81// push orgres_lookup_tableid
82// mov ecx, KERNEL32:RegisterDll (stdcall)
83// call ecx
84//
85// DLL entrypoint:
86// ;BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
87// push 0
88// mov ecx, [esp+12]
89// xor ecx, 1 //0 -> 1, 1 -> 0
90// push ecx //push entry type (1 = attach process, 0 = detach process)
91// push [esp+12] //push module handle
92// call testje
93// ret
94//
95// detach:
96// push [esp+4] //instance handle
97// call KERNEL32:DllExitList
98// ret
99*/
100/** <br>Dll TIBFix code
101 * WARNING: Kernel32.dll depends on this layout (offsets of dllexitlist &
102 * entry point call are hardcoded! (both calculated in RegisterDll)
103 */
104unsigned char achDLLTIBFix[DLLTIBFIX_SIZE] = {
105//cmp [esp+8], 1
106// 0xCC, 0x80, 0x7C, 0x24, 0x08, 0x01,
107 0x80, 0x7C, 0x24, 0x08, 0x01,
108//je detach
109 0x74, 0x33,
110//push [esp+4]
111 0xFF, 0x74, 0x24, 0x04,
112//SvL: 18-7-'98: push internal pe2lx version
113 0x68, 0x00, 0x00, 0x00, 0x00,
114//SvL: 18-7-'98: push version resource id (-1 = no version resource present)
115 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
116//push [table id1] (kernel32 proc depends on 0x77777777 & 0x88888888!!)
117//Svl: So does void LXHeaderSuper::SaveConvertedNames()!
118 0x68, 0x77, 0x77, 0x77, 0x77,
119//push [table id1]
120 0x68, 0x88, 0x88, 0x88, 0x88,
121//mov ecx, KERNEL32:RegisterDll (stdcall)
122 0xB9, 0x99, 0x99, 0x99, 0x99,
123//call ecx
124 0xFF, 0xD1,
125//push 0
126 0x6A, 0x00,
127 0x8B, 0x4C, 0x24, 0x0C,
128 0x83, 0xF1, 0x01,
129 0x51, 0xFF, 0x74, 0x24, 0x0C,
130//call entrypoint
131 0xE8, 0x80, 0xFF, 0xFF, 0xFF,
132//ret
133 0xC3,
134//detach:
135//push [esp+4]
136 0xFF, 0x74, 0x24, 0x04,
137//call KERNEL32:DllExitList (stdcall)
138 0xE8, 0x00, 0x00, 0x00, 0x00,
139//ret
140 0xC3
141};
142
143
144
145/**
146 * Constructor
147 * @remark Exetype is not fully initialized - always use SetExeType(...)!
148 */
149LXHeaderSuper::LXHeaderSuper() : fFlags(0), EntryAddress(0), IsEXE(TRUE),
150 impmodules(NULL), impnames(NULL), impfixuprec(NULL),
151 nrimpfixups(0), nrofimpfixups(0), StackSize(0), nrsections(0),
152 nrintfixups(0), nrofintfixups(0), intfixuprec(NULL),
153 os2resource(NULL), nrids(0),nrofids(0),
154 nrresources(0), curresource(0), exports(NULL),exportsize(0), resids(NULL),
155 nrexports(0), curexport(0), expbundle(NULL), curexpb(NULL),
156 cvtname(NULL), curcvtname(0), nrcvtnames(0), datapage(NULL),
157 cvtnametableid(0), orgrestableid(0), orgrestable(NULL), nrorgres(0),
158 kernel32Object(-1), TIBOffKerImport(0), fConsole(FALSE), impnamesize(0),
159 impmodulesize(0),VersionResourceId(-1)
160{
161 ZERO(LXHdr);
162
163 LXHdr.e32_magic[0] = E32MAGIC1;
164 LXHdr.e32_magic[1] = E32MAGIC2;
165 LXHdr.e32_border = E32LEBO;
166 LXHdr.e32_worder = E32LEWO;
167 LXHdr.e32_level = E32LEVEL;
168 LXHdr.e32_cpu = E32CPU386;
169 LXHdr.e32_os = 0x01; //OS/2
170 LXHdr.e32_ver = 0; //who cares which version...
171 LXHdr.e32_pagesize = 4096; //default
172 LXHdr.e32_pageshift= 0; //default (doet watcom zo)
173 LXHdr.e32_fixupsum = 0; //no checksum supported
174 LXHdr.e32_ldrsum = 0; //no checksum supported
175 LXHdr.e32_mflags = 0;
176 LXHdr.e32_startobj = 1; //code
177 LXHdr.e32_objcnt = 0;
178 LXHdr.e32_objtab = sizeof(LXHdr); //begin hiermee vlak na exe hdr
179
180 //KSO Aug 15 1998 5:07pm: PESection is now dynamic!
181 PESection = NULL;
182 cPESections = 0;
183 ZERO(ResSection);
184}
185
186
187
188/**
189 * Destructor
190 * @remark Pointers that are freed anywhere else *must* be set to NULL else we'll go INT 3
191 */
192LXHeaderSuper::~LXHeaderSuper()
193{
194 if (impnames) free(impnames);
195 if (impfixuprec) free(impfixuprec);
196 if (impmodules) free(impmodules);
197 if (os2resource) free(os2resource);
198 if (resids) free(resids);
199 if (cvtname) free(cvtname);
200 if (orgrestable) free(orgrestable);
201 if (exports) free(exports);
202 if (expbundle) free(expbundle);
203 if (datapage) free(datapage);
204 if (ResSection.rawdata) free((void*)ResSection.rawdata);
205 if (PESection) free(PESection);
206}
207
208
209
210/**
211 * Set flag for no fixups.
212 * @result LXHdr.e32_mflags have the E32NOINTFIX flag set.
213 */
214void LXHeaderSuper::SetNoFixups()
215{
216 LXHdr.e32_mflags |= E32NOINTFIX;// | 0x00100000; //testing MTEADDRALLOCED
217}
218
219
220
221/**
222 * Sets executable type to either EXE or DLL.
223 * @param IsEXE TRUE: EXE; FALSE: DLL
224 * @result LXHdr.e32_mflags have flags set EXE: E32MODEXE; DLL:E32LIBINIT, E32LIBTERM and E32MODDLL
225 * All TIBFIX stuff is set.
226 */
227void LXHeaderSuper::SetExeType(BOOL IsEXE)
228{
229 this->IsEXE = IsEXE;
230 if (IsEXE)
231 {
232 szTIBFix = &achEXETIBFix[0];
233 TIBSize = EXE_TIBSIZE;
234 TIBOffEntry = EXE_OFF_ENTRYFIX;
235 TIBOffCall = EXE_OFF_TIBCALL;
236 TIBOffName = EXE_OFF_NAMETABLE;
237 TIBOffKerImport = EXE_OFF_KERIMP;
238 //SvL: 18-7-'98: Internal pe2lx version and version resource id offsets
239 TIBOffPe2lxVer = EXE_OFF_PE2LXVER;
240 TIBOffVerResId = EXE_OFF_VERRESID;
241 LXHdr.e32_mflags &= ~(E32LIBINIT | E32LIBTERM | E32MODDLL); //mask off some dll flags
242 LXHdr.e32_mflags |= E32MODEXE;
243 }
244 else
245 {//Assuming per process initialization/termination...
246 szTIBFix = &achDLLTIBFix[0];
247 TIBSize = DLL_TIBSIZE;
248 TIBOffEntry = DLL_OFF_ENTRYFIX;
249 TIBOffCall = DLL_OFF_TIBCALL;
250 TIBOffName = DLL_OFF_NAMETABLE;
251 TIBOffKerImport = DLL_OFF_KERIMP;
252 //SvL: 18-7-'98: Internal pe2lx version and version resource id offsets
253 TIBOffPe2lxVer = DLL_OFF_PE2LXVER;
254 TIBOffVerResId = DLL_OFF_VERRESID;
255 LXHdr.e32_mflags &= ~E32MODEXE; //mask off exe flag.
256 LXHdr.e32_mflags |= E32LIBINIT | E32LIBTERM | E32MODDLL;
257 }
258}
259
260
261
262/**
263 * Set entry point.
264 * @param vaEntryPoint Virtualaddress of the entrypoint.
265 * @remark KSO Aug 15 1998: Rewritten
266 */
267BOOL LXHeaderSuper::SetEntryAddress(int vaEntryPoint)
268{
269 int i;
270 i = GetSectionIdxByVA(vaEntryPoint);
271 ltassert(i != -1);
272 LXHdr.e32_startobj = GetObjectNoByVA(vaEntryPoint);
273 ltassert(LXHdr.e32_startobj != -1);
274 LXHdr.e32_eip = vaEntryPoint - PESection[i].address;
275
276 return TRUE;
277}
278
279
280
281/**
282 * Sets Stacksize for thread 1.
283 * @param size (Suggested) stacksize in bytes.
284 */
285void LXHeaderSuper::SetStackSize(int size)
286{
287 if (IsEXE)
288 {
289 //Open32 requires a stack size of at least 64k
290 if (size < 128*1024)
291 StackSize = 128*1024;
292 else
293 StackSize = size;
294 LXHdr.e32_stacksize = StackSize;
295 }
296
297}
298
299
300
301/**
302 * Sets Module Name
303 * @remark This functions now stores the modulename in its right format.
304 */
305void LXHeaderSuper::SetModuleName(char *filename)
306{
307 //KSO: modulename is now stored in the right format (chLen, sName, wOrd)
308 char fname[CCHMAXPATH];
309 memset(modulename, 0, sizeof(modulename));
310 strcpy((char*)SSToDS(fname), filename);
311 strcpy(&modulename[1], StripExtension(StripPath((char*)SSToDS(fname))));
312 UpCase(&modulename[1]);
313 modulename[0] = (char)strlen(&modulename[1]);
314}
315
316
317
318/**
319 * Stores an PE Section in the PESection[] array sorted by (virtual)address.
320 * @param rawdata If ring0: offset of rawdata from an PE sectionheader,
321 * else: pointer to data in memory.
322 * If this pointer is NULL, there is no rawdata for it.
323 * @param rawsize SizeOfRawdata from an PE sectionheader.
324 * @param virtualsize Misc.VirtualSize from an PE sectionheader.
325 * @param address VirtualAddress from an PE sectionheader.
326 * @param type Section type - defined in lx.h - SECTION_*
327 * @remark Be aware of that you can't add more sections then you have allocated space for. (SetNrSections)
328 */
329void LXHeaderSuper::StoreSection(RAWDATA rawdata, int rawsize, int virtualsize, int address, int type)
330{
331 int i;
332 int j;
333
334 //Several exes have sections with virtual size 0
335 if (virtualsize == 0) virtualsize = rawsize;
336
337 /*find place in section table (sort on address)*/
338 i = 0;
339 while (i < nrsections/*idx?*/ && PESection[i].address < address )
340 i++;
341
342 if ( i != nrsections )
343 {
344 /* move sections from this one entry back */
345 j = nrsections;
346 while (j > i)
347 {
348 memcpy(&PESection[j], &PESection[j-1], sizeof(PESection[j-1]));
349 j--;
350 }
351 }
352
353 PESection[i].type = type;
354#ifndef RING0
355 /** NB! for PE2LX no raw data is represented with 0 */
356 PESection[i].rawdata = rawdata;
357#else
358 /** and for RING0 represented with ~0 */
359 PESection[i].rawdata = rawdata ? (rawdata) : ~0;
360#endif
361 PESection[i].address = address;
362 PESection[i].rawsize = min(rawsize,virtualsize);
363 PESection[i].virtualsize = max(virtualsize,rawsize);
364 PESection[i].nrpages = ((virtualsize + 0xFFF) & ~0xFFF) >> PAGE_SHIFT;
365 PESection[i].endaddress = address + PESection[i].nrpages*PAGE_SIZE - 1;
366
367 /* Inc number of sections */
368 nrsections++;
369}
370
371
372
373/**
374 * Aligns Section in executables with no fixups. If section alignment is not a multiple
375 * of 64kb all sections are put into one big section.
376 * @return TRUE : success<br>
377 * FALSE: failure - fatal - dead object!
378 * @precond <b>ASSUMPTIONS</b>:<br>
379 * -Code section comes first<br>
380 * -Sections that aren't adjacent are aligned at 64kb boundary<br>
381 * I could fix the second assumption, but I'm too lazy right now.
382 * @sketch SvL: Align code section at 64 kb boundary<br>
383 * SvL: Put adjacent data section in one big section and align it to a 64 kb boundary <br>
384 */
385BOOL LXHeaderSuper::AlignSections(PIMAGE_OPTIONAL_HEADER pOH)
386{
387 int iFirst;
388 int i;
389 int j;
390 int rawsize;
391 int idx;
392 Section CombinedData;
393
394 //KSO Aug 15 1998: TIBFixObject - code removed
395
396 /* More to do? */
397 if (!(LXHdr.e32_mflags & E32NOINTFIX))
398 return TRUE; //rest not needed if there are internal fixups
399
400 //KSO Aug 16 1998: Ignore TIBFixSection.
401 iFirst = GetTIBSectionIdx() == 0;
402
403 PESection[iFirst].nrinvalidpages = (PESection[iFirst].address & 0xFFFF) >> PAGE_SHIFT;
404 PESection[iFirst].address &= 0xFFFF0000;
405
406 //SvL: Concatenate code & data sections into one LX object
407 memcpy(SSToDS(&CombinedData), &PESection[iFirst], sizeof(Section));
408
409 //Insert invalid pages to align section at 64 kb boundary
410 CombinedData.type = SECTION_COMBINEDDATA;
411 CombinedData.rawdata = NULL; //not used here (just use the originals)
412
413 //too much, but just to be sure (in case we need to add extra invalid pages)
414 //TODO: This should be done safer in the future
415 //datapage = (DataPage*)malloc((GetNrPages()+256)*sizeof(DataPage));
416 //KSO : done - use IMAGESIZE... let's try!
417 datapage = (DataPage*)malloc(((pOH->SizeOfImage >> PAGE_SHIFT) + 10)*sizeof(DataPage));
418 ltassert(datapage != NULL);
419
420 //process pages of first section (code)
421 ltassert(PESection[iFirst].type & SECTION_CODE);
422 rawsize = CombinedData.rawsize; //?
423
424 //KSO Aug 15 1998: TIBFixObject - code removed
425
426 j = idx = 0;
427
428 for (j; j<CombinedData.nrpages; j++)
429 {
430 if (rawsize < PAGE_SIZE)
431 {
432 datapage[idx].size = rawsize;
433 rawsize = 0;
434 }
435 else
436 {
437 datapage[idx].size = PAGE_SIZE;
438 rawsize -= PAGE_SIZE;
439 }
440 datapage[idx].flags= 0;
441 idx++;
442 }
443
444 /* The rest of the section */
445 for ( i = iFirst + 1; i < nrsections; i++)
446 {
447 //Ignore TIBFixSection
448 if (i == GetTIBSectionIdx())
449 {
450 cout << "Debuginfo 3: " << i <<endl;;
451 ltassert(i+1 == nrsections); //TIBFixSection should be the last one
452 continue;
453 }
454
455 if (PESection[i].address != CombinedData.endaddress + 1)
456 {
457 if ((PESection[i].address & 0xFFFF) == 0) //Watcom generated exe
458 return TRUE; //all sections are already properly aligned
459 cout << "Section not aligned at 64 kb boundary!!!" << endl;
460 //Damn, more work to do.
461 int insertpages;
462
463 insertpages = (PESection[i].address - CombinedData.endaddress-1) >> PAGE_SHIFT;
464 for (j=0;j<insertpages;j++)
465 {
466 datapage[idx].size = 0;
467 datapage[idx].flags = ZEROED;
468 idx++;
469 }
470 CombinedData.nrpages += insertpages;
471 }
472
473 CombinedData.nrpages += PESection[i].nrpages;
474 CombinedData.rawsize += PESection[i].rawsize;
475 CombinedData.virtualsize += PESection[i].virtualsize;
476 CombinedData.endaddress = PESection[i].endaddress;
477
478 rawsize = PESection[i].rawsize;
479 for (j=0;j<PESection[i].nrpages;j++)
480 {
481 if (PESection[i].type == SECTION_UNINITDATA || rawsize == 0)
482 {
483 datapage[idx].size = 0;
484 datapage[idx].flags = ZEROED;
485 }
486 else
487 {
488 if (rawsize < PAGE_SIZE)
489 {
490 datapage[idx].size = rawsize;
491 rawsize = 0;
492 }
493 else
494 {
495 datapage[idx].size = PAGE_SIZE;
496 rawsize -= PAGE_SIZE;
497 }
498 datapage[idx].flags= 0;
499 }
500 idx++;
501 }
502 PESection[i].fInvalid = TRUE;
503 }
504
505 //KSO Aug 16 1998: Dynamic PESection and TIBFixSection
506 Section *pTmp;
507 pTmp = (Section*)realloc(PESection,(nrsections+1)*sizeof(Section));
508 ltassert(pTmp != NULL);
509 PESection = pTmp;
510 PESection[iFirst].fInvalid = TRUE;
511
512 memcpy(&PESection[nrsections++], SSToDS(&CombinedData), sizeof(Section));
513
514 return TRUE;
515}
516
517
518
519/**
520 * Get number of objects in the virtual LX-file.
521 * @return Number of Ojbects in the virtual LX-file.
522 * @remark Does <b>NOT</b> count the resource section.
523 */
524int LXHeaderSuper::GetNrObjects()
525{
526 int i;
527 int nrobjs = 0;
528
529 for ( i = 0; i < nrsections; i++)
530 {
531 if (!PESection[i].fInvalid)
532 nrobjs++;
533 }
534
535 return (nrobjs);
536}
537
538
539
540/**
541 * Get number of objects in the virtual LX-file.
542 * @return Number of Ojbects in the virtual LX-file.
543 * @remark <b>Does</b> count the resource section.
544 */
545int LXHeaderSuper::GetNrObjects2()
546{
547 int i;
548 int nrobjs = 0;
549
550 for ( i = 0; i < nrsections; i++)
551 {
552 if (!PESection[i].fInvalid)
553 nrobjs++;
554 }
555
556 nrobjs += nrresources != 0;
557 return (nrobjs);
558}
559
560
561
562/**
563 * Adds a name export
564 * @param address Entrypoint address.
565 * @param name Pointer to the namezerostring.
566 * @param ordinal Ordinalvalue of export.
567 * @return TRUE : on success<br>
568 * FALSE: on failure
569 */
570BOOL LXHeaderSuper::AddNameExport(int address, char *name, int ordinal)
571{
572 int len = strlen(name);
573
574 ltassert(exportsize > (ULONG)(curexport-exports) + min(len,127)+1+2);
575
576 if (len > (127-3))
577 {
578 name[126] = 0; //OS/2 maximum
579 len = 127;
580 cout << "LXHeaderSuper::AddNameExport: WARNING - Had to truncate export name." << endl;
581 }
582
583 *curexport = (BYTE)len;
584 curexport++;
585 strcpy(curexport, name);
586 curexport += len;
587 *(USHORT *)curexport = (USHORT)(ordinal);
588 curexport += sizeof(USHORT);
589
590 return TRUE;
591}
592
593
594/**
595 * Adds ordinal export.
596 * @param address Entrypoint address of export.
597 * @param ordinal Ordinal value of export.
598 * @return TRUE : on success<br>
599 * FALSE: on failure
600 */
601BOOL LXHeaderSuper::AddOrdExport(int address, int ordinal)
602{
603 /* static int lastord = 0; KOS: statics should be data members to work in RING0 */
604 int i;
605
606 if (ordinal > lastord+1)
607 {//add empty record(s)
608 int diff = ordinal - lastord - 1;
609 while (diff)
610 {
611 curexpb->b32_cnt = min(diff, 255);
612 diff -= curexpb->b32_cnt;
613 curexpb->b32_type = EMPTY;
614 curexpb = (exportbundle *)((int)curexpb + 2*sizeof(char));
615 }
616 }
617
618 curexpb->b32_cnt = 1;
619 curexpb->b32_type = ENTRY32;
620 i = GetObjectNoByVA(address);
621 ltassert(i != -1);
622 curexpb->b32_obj = (USHORT)i;
623
624 curexpb->e32_flags = E32EXPORT | E32SHARED;
625 i = GetSectionIdxByVA(address);
626 ltassert(i != -1);
627 curexpb->e32_offset = address - PESection[i].address;
628 lastord = ordinal;
629 curexpb++;
630
631 return TRUE;
632}
633
634
635
636/**
637 * Sets number of exports. (?? External Fixups ??)
638 * @param nr Number of exports.
639 * @return TRUE : on success<br>
640 * FALSE: on failure
641 */
642BOOL LXHeaderSuper::SetNrExtFixups(int nr)
643{
644 exportsize = 64+nr*(127+1+2);
645 exports = (char *)malloc(exportsize); //length byte, name (max 127) + ordinal (USHORT)
646 ltassert(exports != NULL);
647
648 memset(exports, 0, exportsize);
649 if (nr > 0)
650 {
651 expbundle = (exportbundle *)malloc(nr*max(sizeof(exportbundle), sizeof(forwardbundle)));
652 ltassert(expbundle != NULL); //KSO: fatal error - exports will be freed in the destructor
653 memset(expbundle, 0, nr*max(sizeof(exportbundle), sizeof(forwardbundle)));
654 }
655 curexpb = expbundle;
656 curexport = exports;
657
658 //First entry in resident name table is module name
659 //KSO: module name now have the right format! - Jun 16 1998 4:12pm
660 memcpy(exports, modulename, modulename[0]+1);
661 curexport += *curexport + 1;
662
663 *(USHORT *)curexport = 0;
664 curexport += sizeof(USHORT);
665#if 0
666 //first entry in export table is unused
667 curexpb->b32_cnt = 1;
668 curexpb->b32_type = EMPTY;
669 curexpb = (exportbundle *)&curexpb->b32_obj;
670#endif
671
672 return TRUE;
673}
674
675
676
677/**
678 * Adds forwarder.
679 * @param name Pointer to the exportname (zerostring).
680 * @param ordinal Ordinal number of export.
681 * @param forward Pointer to the forwardinfo (zerostring).
682 * @return TRUE : on success<br>
683 * FALSE: on failure
684 * @sketch forward gives the DLL name and name of the export (i.e. MYDLL.expfunc or MYDLL.#27)
685 * @remark <b>TODO:</b> finish this <br>
686 */
687BOOL LXHeaderSuper::AddForwarder(char *name, int ordinal, char *forward)
688{
689#if 0
690 int len = strlen(name);
691
692 ltassert(curexport + len - exports >= exportsize)
693
694 *curexport = len;
695 curexport++;
696 strncpy(curexport, name, 127);
697 curexport += len;
698 *(USHORT *)curexport = (USHORT)ordinal;
699 curexport += sizeof(USHORT);
700
701 nrexports++;
702 return TRUE;
703#else
704 return FALSE;
705#endif
706
707}
708
709
710
711/**
712 * Sets number of internal offset fixups.
713 * @param nr number of internal offset fixups.
714 * @return TRUE : on success<br>
715 * FALSE: on failure
716 * @remark iets te veel, but who cares (KSO: Sander could you translate)<br>
717 * IMPORTANT: Do not Add more Off32Fixups than you have Set!
718 */
719BOOL LXHeaderSuper::SetNrOff32Fixups(int nr)
720{
721 nrofintfixups = nr;
722 intfixuprec = (intfixup *)malloc(nr*sizeof(intfixup));
723
724 ltassert(intfixuprec != NULL || nr == 0);
725 memset(intfixuprec, 0, nr*sizeof(intfixup));
726
727 return TRUE;
728}
729
730
731
732/**
733 * Adds internal 32-bit offsetfixup
734 * @param address Address of fixup. (Virtual)
735 * @remark This function is not used in RING0 (LXFile)
736 */
737void LXHeaderSuper::AddOff32Fixup(int address)
738{
739 static intfixup crossedpage;
740 static BOOL fCrossed = FALSE;
741 static int crossedpageaddress = 0;
742 intfixup *frec;
743 int i;
744 int no;
745 int targetaddr;
746
747 frec = &intfixuprec[nrintfixups];
748
749 //Check if we need to insert a crossed page fixup
750 if (fCrossed == TRUE && address > crossedpageaddress)
751 {
752 memcpy((char *)frec, (char *)&crossedpage, sizeof(crossedpage));
753 fCrossed = FALSE;
754 crossedpageaddress = 0;
755 nrintfixups++;
756 frec++;
757 cout << "CrossPageFixup: Finished." << endl;
758 }
759 frec->nr_stype = 0x07; //32 bits offset fixup
760 frec->nr_flags = 0x00 | 0x10 | 0x40; //internal fixup + 32 bits offset + 16 bits object nr
761 frec->r32_soff = (SHORT)(address & 0xFFF);
762
763 i = GetOriginalSectionIdxByVA(address); //KSO: Combineddata sections don't have rawdata.
764 no = GetObjectNoByVA(address);
765 if (no == -1 || i == -1)
766 {
767 cout << "Oops, fixup error 1...." << endl;
768 return;
769 }
770 frec->srcpage = (USHORT)GetPageNoByVA(address);
771 frec->srcobj = (USHORT)no;
772
773 //SvL: address could be aligned at 64 kb boundary, so correct address calculation
774 //KSO Aug 16 1998: TIBFixSection - removed code - don't worry about TIB anymore
775 targetaddr = *(int *)(PESection[i].rawdata + (address - (PESection[i].address + PESection[i].nrinvalidpages*PAGE_SIZE)));
776 cout << " targetaddr: " << hex(targetaddr);
777 cout << endl;
778 cout << " address: " << hex(address) << endl;
779
780 //SvL: The target object might be the combined data section, so don't use
781 // GetSectionByAddress
782 i = GetSectionIdxByVA(targetaddr); //KSO: not original!
783 no = GetObjectNoByVA(targetaddr);
784 if (no == -1 || i == -1)
785 {
786 cout << "Oops, fixup error 2...." << endl;
787 return;
788 }
789 frec->targetaddr = targetaddr - PESection[i].address; //relative
790 frec->targetobj = (USHORT)no;
791
792 // cout << "src address " << frec->r32_soff << " srcpage " << frec->srcpage << " target " << frec->targetaddr << " frec " << (int)frec << endl;
793
794 //SvL: Check for fixups that cross page boundaries
795 // If I read the lx doc right, you need to add two fixups in
796 // this case, one for original page and one for original page + 1
797 //TODO: Doesn't work if the last page contains such a fixup!
798 if (frec->r32_soff + 4 > PAGE_SIZE)
799 {
800 memcpy((char *)&crossedpage, (char *)frec, sizeof(crossedpage));
801 //crossed page boundary -> negative offset in next page
802 crossedpage.r32_soff = (SHORT)((frec->r32_soff & 0xFFF) - PAGE_SIZE);
803 crossedpage.srcpage = frec->srcpage+1;
804 crossedpageaddress = (address + PAGE_SIZE) & ~0xFFF;
805 fCrossed = TRUE;
806 }
807
808 nrintfixups++;
809}
810
811
812/**
813 * Store and sort import fixups.
814 * @param newfrec Pointer to namefixup to add.
815 * @return TRUE : on success<br>
816 * FALSE: on failure
817 * @precond SvL: 30-10-'97, assumption about sorting of fixups is incorrect, so:<br>
818 * ASSUMPTION: namefixup & ordfixup of same size
819 */
820BOOL LXHeaderSuper::StoreAndSortImport(namefixup *newfrec)
821{
822 namefixup *frec;
823 namefixup *tmp;
824 int i;
825
826
827 /*KSO: Out of nrimpfixups? Try to alloc some more */
828 if (nrimpfixups >= nrofimpfixups)
829 {
830 namefixup *pTmp;
831 pTmp = (namefixup*)realloc(impfixuprec, nrofimpfixups+0x20);
832 if (pTmp != NULL)
833 {
834 impfixuprec = pTmp;
835 nrofimpfixups += 0x20;
836 }
837 else
838 {
839 cout << "LXHeaderSuper::StoreAndSortImport: Can't realloc more impfixuprec. Sorry" << endl;
840 return (FALSE);
841 }
842 }
843
844
845
846 if (nrimpfixups != 0)
847 {
848 frec = &impfixuprec[nrimpfixups - 1];
849
850 if (newfrec->srcpage >= frec->srcpage)
851 {
852 memcpy(&impfixuprec[nrimpfixups], newfrec, sizeof(namefixup));
853 nrimpfixups++;
854 return TRUE;
855 }
856 }
857 else
858 {
859 memcpy(&impfixuprec[0], newfrec, sizeof(namefixup));
860 nrimpfixups++;
861 return TRUE;
862 }
863
864 frec = &impfixuprec[0];
865 for (i = 0; i < nrimpfixups; i++)
866 {
867 if (newfrec->srcpage < frec->srcpage)
868 {
869#ifndef _asmutils_h_
870 tmp = (namefixup *)malloc(nrimpfixups*sizeof(namefixup));
871 ltassert(tmp != NULL);
872 memcpy(tmp, frec, (nrimpfixups-i)*sizeof(namefixup));
873 memcpy(frec, newfrec, sizeof(namefixup));
874 memcpy(frec+1, tmp, (nrimpfixups-i)*sizeof(namefixup));
875 free(tmp);
876#else
877 memmov(frec, sizeof(frec), (nrimpfixups-i)*sizeof(namefixup));
878 memcpy(frec, newfrec, sizeof(namefixup));
879#endif
880 break;
881
882 }
883 frec++;
884 }
885 ltassert(i != nrimpfixups);
886 nrimpfixups++;
887 return TRUE;
888}
889
890
891
892/**
893 * Store name import.
894 * @param modname Pointer to a the name(sz) of the module(DLL) from which the function is imported.
895 * @param idxmod Index of the module (DLL) from which the function is imported.
896 * @param name Pointer to the name of the imported function (zerostring).
897 * @param offset Offset(address) of fixup. (Virtual)
898 * @return TRUE : on success<br>
899 * FALSE: on failure
900 */
901BOOL LXHeaderSuper::StoreImportByName(char *modname, int idxmod, char *name, int offset)
902{
903 namefixup frec;
904
905 if (impfixuprec == NULL)
906 {
907 nrofimpfixups = MAX_IMPORT;
908 impfixuprec = (namefixup *)malloc(nrofimpfixups*sizeof(namefixup));
909 ltassert(impfixuprec != NULL);
910 memset(impfixuprec, 0, MAX_IMPORT*sizeof(namefixup));
911 }
912 if (impnames == NULL)
913 {
914 impnames = (char *)malloc(64*1024); //moet genoeg zijn
915 ltassert(impnames != NULL);
916 memset(impnames, 0, 64*1024);
917 impnameoff = impnames + 1; //SvL: Bugfix: base 1
918 impnamesize = 1; //include ending 0
919 }
920
921 /*KSO: if there is to few impfixups we will try to alloc some more */
922 if (nrimpfixups >= nrofimpfixups)
923 {
924 namefixup *pTmp;
925 pTmp = (namefixup*)realloc(impfixuprec, nrofimpfixups+0x20);
926 if (pTmp != NULL)
927 {
928 impfixuprec = pTmp;
929 nrofimpfixups += 0x20;
930 }
931 else
932 {
933 cout << "LXHeaderSuper::StoreImportByName: Can't realloc more impfixuprec. Sorry" << endl;
934 return (FALSE);
935 }
936 }
937
938 frec.nr_stype = 0x07; //32 bits offset
939 frec.nr_flags = 0x02 | 0x40; //import by name + mod offset = 16 bits
940 frec.r32_soff = (SHORT)(offset & 0xFFF); //offset within specific page
941 frec.r32_objmod = (USHORT)(idxmod+1); //vanaf 1!!!!!
942
943 impnameoff[0] = (char)strlen(name);
944 strcpy(&impnameoff[1], name);
945 frec.proc = (USHORT)((int)impnameoff-(int)impnames); //32 bits target flag not set!
946 frec.srcpage = (USHORT)GetPageNoByVA(offset);
947
948 impnamesize += impnameoff[0]+1;
949 impnameoff += impnameoff[0]+1;
950
951 return StoreAndSortImport((namefixup *)SSToDS(&frec));
952}
953
954
955
956/**
957 * Store (add) ordinal import.
958 * @param idxmod Index of the module (DLL) from which the function is imported.
959 * @param ordinal Ordinal number of the function to be imported.
960 * @param offset Offset(address) of fixup. (Virtual)
961 * @return TRUE : on success<br>
962 * FALSE: on failure
963 */
964BOOL LXHeaderSuper::StoreImportByOrd(int idxmod, int ordinal, int offset)
965{
966 ordfixup frec;
967
968 if (impfixuprec == NULL)
969 {
970 nrofimpfixups = MAX_IMPORT;
971 impfixuprec = (namefixup *)malloc(nrofimpfixups*sizeof(namefixup)); //this'll have to be more accurate - later
972 ltassert(impfixuprec != NULL);
973 memset(impfixuprec, 0, MAX_IMPORT*sizeof(namefixup));
974 }
975
976 /*KSO: if there is to few impfixups we will try to alloc some more */
977 if (nrimpfixups >= nrofimpfixups)
978 {
979 namefixup *pTmp;
980 pTmp = (namefixup*)realloc(impfixuprec, nrofimpfixups+0x20);
981 if (pTmp != NULL)
982 {
983 impfixuprec = pTmp;
984 nrofimpfixups += 0x20;
985 }
986 else
987 {
988 cout << "LXHeaderSuper::StoreImportByName: Can't realloc more impfixuprec. Sorry" << endl;
989 return (FALSE);
990 }
991 }
992
993 frec.nr_stype = 0x07; //32 bits offset
994 frec.nr_flags = 0x01 | 0x40; //import by ordinal + mod offset = 16 bits
995 frec.r32_soff = (SHORT)(offset & 0xFFF); //offset within specific page
996 frec.r32_objmod = (USHORT)(idxmod+1); //vanaf 1!!!!!
997 frec.ord = (USHORT)ordinal;
998 frec.srcpage = (USHORT)GetPageNoByVA(offset);
999
1000 return StoreAndSortImport((namefixup *)SSToDS(&frec));
1001}
1002
1003
1004
1005/**
1006 * Store importmodules.
1007 * @param moduels Pointer to array of modulenames (zerostrings).
1008 * @param nrmod Number of modules in array.
1009 * @return TRUE : on success<br>
1010 * FALSE: on failure
1011 */
1012BOOL LXHeaderSuper::StoreImportModules(char *modules, int nrmod)
1013{
1014 int size, i;
1015 char *src, *dest;
1016
1017 //KSO:determin size first
1018 int msize;
1019
1020 size = 0;
1021 msize = _msize(modules);
1022 src = modules;
1023 i = nrmod;
1024 kernel32Object = 0;
1025 while ( i > 0 )
1026 {
1027 ltassert((src-modules) < msize);
1028 int len = strlen(src)+1;
1029 if (!kernel32Object)
1030 kernel32Object = stricmp(src, "KERNEL32.DLL") == 0 ? 1 : 0;
1031 size += len - 4 + 1; //-".dll" + lenght-char
1032 src += len;
1033 i--;
1034 }
1035 size += !kernel32Object ? 10 : 1;
1036 kernel32Object = -1;
1037 //KSO - end
1038
1039 impmodules = (char *)malloc(size);
1040 ltassert(impmodules != NULL);
1041 impmodulesize = 0;
1042
1043 src = modules;
1044 dest = impmodules;
1045 for (i = 0; i < nrmod; i++)
1046 {
1047 size = min(strlen(src), 12);
1048 dest[0] = (char)(size-4);
1049 dest++;
1050 strncpy(dest, src, size-4);
1051 dest[size-4] = 0; // !!!
1052 UpCase(dest);
1053 if (strcmp(dest, "NETAPI32") == 0)
1054 {//SvL: Name conflict with MUGLIB\DLL\NETAPI32.DLL
1055 strcpy(dest, "WNETAP32");
1056 dest += size-4;
1057 }
1058 else
1059 {
1060 if (strcmp(dest, "KERNEL32") == 0)
1061 kernel32Object = i;
1062 dest += size-4;
1063 }
1064 src += strlen(src) + 1; //+ null byte
1065 }
1066
1067 if (kernel32Object == -1)
1068 {//add kernel32
1069 kernel32Object = nrmod;
1070 dest[0] = 8;
1071 strcpy(&dest[1], "KERNEL32");
1072 dest += 9;
1073 nrmod++;
1074 }
1075
1076 LXHdr.e32_impmodcnt = nrmod;
1077 dest[0] = 0; //end of array
1078 impmodulesize = (int)dest - (int)impmodules;
1079
1080 return TRUE;
1081}
1082
1083
1084/**
1085 * Systemmodules.
1086 */
1087char *sysmodules[] = {"KERNEL32",
1088 "USER32",
1089 "GDI32",
1090 "WINMM",
1091 "DSOUND",
1092 "DDRAW",
1093 "WNETAP32",
1094 "MPR",
1095 "OLE32",
1096 "ADVAPI32",
1097 "COMMDLG",
1098 "NTDLL",
1099 "WINSPOOL",
1100 "SHELL32",
1101 "TAPI32",
1102 "CAPI32",
1103 "VERSION",
1104 "WSOCK32"};
1105
1106
1107
1108/**
1109 * Determins where a module is a (win32os2-) systemmodule.
1110 * @param mod Pointer to modulename (string)
1111 * @param size Size of modulename
1112 * @return TRUE : on systemmodule<br>
1113 * FALSE:
1114 */
1115BOOL LXHeaderSuper::IsSystemModule(char *mod, int size)
1116{
1117 int i;
1118
1119 ltasserthp(mod);
1120
1121 for (i=0;i<sizeof(sysmodules)/sizeof(char *);i++)
1122 {
1123 if (!strncmp(mod, sysmodules[i], size))
1124 return (TRUE);
1125 }
1126 return (FALSE);
1127}
1128
1129
1130
1131/**
1132 * Find a name given by index in an array of Pascal strings.
1133 * @param table Pointer to a an array of Pascal strings.
1134 * @param index Index of
1135 * @return Offset into the table of the name requested by index.
1136 * @remark Not currently used.
1137 */
1138int LXHeaderSuper::FindName(char *table, int index)
1139{
1140 int i, offset = 0;
1141
1142 for (i=0;i<index-1;i++)
1143 {
1144 offset += table[0] + 1;
1145 table = table + table[0] + 1;
1146 }
1147 return (offset);
1148}
1149
1150
1151
1152/**
1153 * Get the number of pagemap entries in the virtual LX-file.
1154 * @return Number of pagemap entries.
1155 * @remark Requires fixing the resource size (as done in savenewexe)
1156 */
1157int LXHeaderSuper::GetNrPages()
1158{
1159 int i;
1160 int nrpages = 0;
1161
1162 for (i = 0; i < nrsections; i++)
1163 {
1164 if (!PESection[i].fInvalid)
1165 nrpages += PESection[i].nrpages + PESection[i].nrinvalidpages;
1166 }
1167//SvL: 13 aug 1998
1168#if 0
1169 if (IsEXE)
1170 {
1171 nrpages += StackSize >> PAGE_SHIFT;
1172 if (StackSize & 0xFFF)
1173 nrpages++;
1174 }
1175#endif
1176
1177 if (nrresources)
1178 {
1179 nrpages += ResSection.virtualsize >> PAGE_SHIFT;
1180 if (ResSection.rawsize & 0xFFF)
1181 nrpages++;
1182 }
1183 return (nrpages);
1184}
1185
1186
1187
1188/**
1189 * ASCII(us) uppercase.
1190 * @param mixedcase Pointer to the string to capitalize.
1191 * @result The mixedcase string is in uppercase.
1192 * @remark Mixedcase should of course not be in a readonly page/object (RING3).
1193 */
1194void LXHeaderSuper::UpCase(char *mixedcase)
1195{
1196 int i;
1197
1198 for (i=0;i<strlen(mixedcase);i++)
1199 {
1200 if (mixedcase[i] >= 'a' && mixedcase[i] <= 'z')
1201 {
1202 mixedcase[i] += 'A' - 'a';
1203 }
1204 }
1205}
1206
1207
1208
1209/**
1210 * Sets module type. GUI/text-mode.
1211 * @param type Moduletype - see SYSTEM_* defines in lx.h
1212 */
1213void LXHeaderSuper::SetModuleType(int type)
1214{
1215 LXHdr.e32_mflags |= E32PMAPI;
1216
1217 if (IsEXE) //don't set it for dlls (in case this flag is accidentally set in the header)
1218 fConsole = (type == SYSTEM_CHARACTER);
1219}
1220
1221
1222
1223/**
1224 * Get the page number which address points to. (Of course in the Virtual LX-file.)
1225 * @param vaAddress A virtual address in the page.
1226 * @return Page number.
1227 * @remark WAS: GetAddressPage(int address)
1228 */
1229int LXHeaderSuper::GetPageNoByVA(int vaAddress)
1230{
1231 int i, page = 0;
1232
1233 for (i = 0; i < nrsections; i++)
1234 {
1235 if (PESection[i].fInvalid)
1236 continue;
1237
1238 if (vaAddress > PESection[i].endaddress)
1239 {
1240 page += PESection[i].nrpages + PESection[i].nrinvalidpages;
1241 }
1242 else
1243 {
1244 ltassert(vaAddress >= PESection[i].address) //KSO Aug 15 1998 3:36pm
1245 page += ((vaAddress - PESection[i].address) >> PAGE_SHIFT);
1246 break;
1247 }
1248 }
1249
1250 return (page);
1251}
1252
1253
1254
1255/**
1256 * Gets section number by type.
1257 * @param type Section type. See SECTION_* in lx.h
1258 * @return Section number on success<br>
1259 * -1 on failure
1260 */
1261int LXHeaderSuper::GetSection(int type)
1262{
1263 int i;
1264
1265 for (i=0;i<nrsections;i++)
1266 {
1267 if (PESection[i].type & type)
1268 {
1269 return (i);
1270 }
1271 }
1272 return (-1);
1273}
1274
1275
1276
1277/**
1278 * Get index, into PESection, of the "original" section which vaAddress points into.
1279 * "original" - all sections but COMBINEDDATA ignoring invalid sections.
1280 * @param vaAddress Virtual address.
1281 * @return Section index (into PESection) on success.<br>
1282 * -1 on failure.
1283 * @remark WAS: GetSectionByAddress(int address) was used.<br>
1284 * KSO: Now uses type instead of rawdata to find Combined data section.
1285 */
1286int LXHeaderSuper::GetOriginalSectionIdxByVA(int vaAddress)
1287{
1288 int i;
1289
1290 for (i = 0; i < nrsections; i++)
1291 {
1292 if (!(PESection[i].type & SECTION_COMBINEDDATA))
1293 {
1294 if (PESection[i].address <= vaAddress && PESection[i].endaddress > vaAddress)
1295 return i;
1296 }
1297 }
1298 return -1;
1299}
1300
1301
1302
1303/**
1304 * Get index, into PESection, of the section which vaAddress points into.
1305 * @param vaAddress Virtual address.
1306 * @return Section index (into PESection) on success.<br>
1307 * -1 on failure.
1308 * @remark WAS: GetSectionByAddress(int address) was used<br>
1309 * KSO: Now uses type instead of rawdata to find Combined data section.
1310 */
1311int LXHeaderSuper::GetSectionIdxByVA(int vaAddress)
1312{
1313 int i;
1314
1315 for (i = 0; i < nrsections; i++)
1316 {
1317 if (!(PESection[i].fInvalid))
1318 {
1319 if (PESection[i].address <= vaAddress && PESection[i].endaddress > vaAddress)
1320 return i;
1321 }
1322 }
1323 return -1;
1324}
1325
1326
1327
1328/**
1329 * Get the object number (1 based), in the virtual LX-File, of the section
1330 * which vaAddress points into.
1331 * @param vaAddress Virtual address.
1332 * @return Object number (1 based) on success.<br>
1333 * -1 on failure.
1334 * @remark SvL: Ignore sections combined into one data section<br>
1335 * KSO: Do not count Invalid section! and 1 based<br>
1336 * @remark RENAMED : was GetRealSectionByAddress(int address)<br>
1337 * QUESTION: why do you check rawdata != 0 ?
1338 */
1339int LXHeaderSuper::GetObjectNoByVA(int vaAddress)
1340{
1341 int i, ObjNo;
1342
1343 for (i = ObjNo = 0; i < nrsections; i++)
1344 {
1345 if (!PESection[i].fInvalid)
1346 {
1347 ObjNo++;
1348 #if 0
1349 if (PESection[i].rawdata || PESection[i].type == SECTION_COMBINEDDATA)
1350 {
1351 if (PESection[i].address <= vaAddress && PESection[i].endaddress > vaAddress )
1352 return (ObjNo);
1353 }
1354 #else
1355
1356 if (PESection[i].address <= vaAddress && PESection[i].endaddress > vaAddress )
1357 return (ObjNo);
1358
1359 #endif
1360 }
1361 }
1362
1363 return -1;
1364}
1365
1366
1367
1368/**
1369 * Gets section index by address (index into PESection).
1370 * @return Section index on success.<br>
1371 * -1 on failure.
1372 * @remark Ignores invalid sections.<br>
1373 * @remark Unused!
1374 */
1375int LXHeaderSuper::GetSectionLEAddress(int address)
1376{
1377 int i;
1378
1379 for (i=0;i<nrsections;i++)
1380 {
1381 if (PESection[i].fInvalid) continue;
1382 if (PESection[i].rawdata)
1383 {
1384 if (PESection[i].address > address)
1385 {
1386 return (i-1);
1387 }
1388 }
1389 }
1390 return (-1);
1391}
1392
1393
1394
1395/**
1396 * Strip off path.
1397 * @param path Pointer to a filename or directoryname with path. (sz)
1398 * @return Pointer (into the path string) to the end of the path (beginning of filename).
1399 * @remark Does not change anything in the string
1400 */
1401char *LXHeaderSuper::StripPath(char *path) //niets aan de string veranderen!!
1402{
1403 char *pszRet = path;
1404
1405 while (*path != '\0')
1406 {
1407 if (*path == '\\' || *path == '/' || *path == ':')
1408 pszRet = path + 1;
1409
1410 path++;
1411 }
1412
1413 return pszRet;
1414}
1415
1416
1417
1418/**
1419 * Strip off extention (if any)
1420 * @param fname Pointer to a filename (without path) (sz)
1421 * @return fname without extension
1422 * @remark This function changes the fname string. (Must be writable - RING3)
1423 */
1424char *LXHeaderSuper::StripExtension(char *fname)
1425{
1426 int i = 0;
1427 int j = -1;
1428
1429 while (fname[i] != '\0')
1430 {
1431 if (fname[i] == '.')
1432 j = i;
1433 i++;
1434 }
1435 if (j >= 0)
1436 fname[j] = '\0';
1437 return fname;
1438}
1439
1440
1441
1442/**
1443 * Gets a unique resource id.
1444 * @return Unique resource id.
1445 */
1446int LXHeaderSuper::GetUniqueId()
1447{
1448 int i, j, id;
1449
1450 for (j=0;j<65536;j++)
1451 {
1452 for (i=0;i<nrids;i++)
1453 {
1454 if (uniqueId == resids[i])
1455 {
1456 break;
1457 }
1458 }
1459 if (i == nrids)
1460 {
1461 id = uniqueId;
1462 resids[nrids] = id;
1463 nrids++;
1464 if (nrids <= nrofids)
1465 {
1466 int *pTmp;
1467 pTmp = (int*)realloc(resids, nrofids + 0x20);
1468 if (pTmp != NULL)
1469 {
1470 resids = pTmp;
1471 nrofids += 0x20;
1472 }
1473 else
1474 ltassert(FALSE && "NO ids left");
1475 }
1476 uniqueId = (uniqueId + 1) & 0xFFFF;
1477 return (id);
1478 }
1479 uniqueId = (uniqueId + 1) & 0xFFFF;
1480 }
1481 cout << "No ids left!!!!" << endl;
1482 ltassert(FALSE && "NO ids left");
1483 return (0);
1484}
1485
1486
1487
1488/**
1489 * Set number of resources.
1490 * @param cnt Count of resources.
1491 * @return TRUE : on success<br>
1492 * FALSE: on failure
1493 */
1494BOOL LXHeaderSuper::SetNrResources(int cnt)
1495{
1496 cout << "Nr of resources: " << cnt << endl;
1497
1498 //+2 for resource name lookup table and original res lookup table
1499 nrresources = cnt+2;
1500
1501 //reserve space for original win32 resources + strings
1502 os2resource = (rsrc32 *)malloc((nrresources*16)*sizeof(rsrc32));
1503 ltassert(os2resource != NULL);
1504
1505 memset(os2resource, 0, nrresources*16*sizeof(rsrc32));
1506 cvtname = (NameId *)malloc(cnt*(sizeof(NameId)+256));
1507 ltassert2(cvtname != NULL, free(os2resource);os2resource = NULL);
1508 curcvtname = (NameId *)((char *)cvtname+sizeof(USHORT)); //first USHORT = nr of converted names
1509 ltasserthp2(curcvtname, free(os2resource);os2resource = NULL);
1510 memset(cvtname, 0, cnt*(sizeof(NameId)+256));
1511
1512 //temporary storage for used resource ids (*16 since menus use getuniqueid too)
1513 nrofids = nrresources*16;
1514 resids = (int *)malloc(nrofids * sizeof(int));
1515 ltassert2(resids != NULL, free(cvtname);cvtname = NULL;free(os2resource);os2resource = NULL);
1516 memset(resids, 0, nrresources*16*sizeof(int));
1517
1518 //table used in LockResource (kernel32) to return the original win32 resource
1519 //layout: 1st ULONG nr of entries
1520 // nth ULONG (n>1) 0xAAAABBBB, AAAA=org id, BBBB=OS/2 id
1521 orgrestable = (ULONG *)malloc((nrresources+1)*sizeof(ULONG));
1522 ltassert2(orgrestable != NULL, free(cvtname);cvtname = NULL; free(os2resource);os2resource = NULL;free(resids);resids = NULL);
1523 memset(orgrestable, 0, (nrresources+1)*sizeof(ULONG));
1524
1525 return TRUE;
1526}
1527
1528
1529
1530/**
1531 * Store a resource id.
1532 * @param id Resource id.
1533 * @return TRUE : on success<br>
1534 * FALSE: on failure
1535 * @remark All ids should be stored before we ask for any unique resource id.
1536 */
1537BOOL LXHeaderSuper::StoreResourceId(int id)
1538{
1539 resids[nrids] = id;
1540 nrids++;
1541 if (nrids >= nrofids)
1542 {
1543 int *pTmp;
1544 pTmp = (int*)realloc(resids, sizeof(int)*(nrofids + 0x20));
1545 if (pTmp != NULL)
1546 {
1547 resids = resids;
1548 nrofids += 0x20;
1549 }
1550 else
1551 ltassert(FALSE && "NO ids left");
1552 }
1553
1554 return TRUE;
1555}
1556
1557
1558
1559/**
1560 * Stores a win32 resource.
1561 * @param id Resource id.
1562 * @param type (OS/2) Resource type. (ignored)
1563 * @param size Size of resourcedata (bytes).
1564 * @param resourcedata Pointer to resource data.
1565 * @return TRUE : on success<br>
1566 * FALSE: on failure
1567 * @remark The following resources are currently stored in Win32 format:<br>
1568 * Accelerators<br>
1569 * Dialogs<br>
1570 * Menus<br>
1571 */
1572BOOL LXHeaderSuper::StoreWin32Resource(int id, int type, int size, char *resourcedata)
1573{
1574 int newid = GetUniqueId();
1575 ltassert(newid != 0);
1576 ltassert(nrorgres+1 <= nrresources); //(resourcedata is asserted in StoreResource)
1577
1578 //First entry used for nr of entries, so + 1
1579 orgrestable[++nrorgres] = ((id & 0xFFFF) << 16) + (newid & 0xFFFF);
1580
1581 //store them all as rcdata
1582 return StoreResource(newid, RT_RCDATA, size, resourcedata);
1583}
1584
1585
1586
1587/**
1588 * Stores a resource.
1589 * @param id Resource id.
1590 * @param type OS/2 resource type.
1591 * @param size Size of resourcedata (bytes).
1592 * @param resourcedata Pointer to resource data.
1593 * @return TRUE : on success<br>
1594 * FALSE: on failure
1595 */
1596BOOL LXHeaderSuper::StoreResource(int id, int type, int size, char *resourcedata)
1597{
1598 //static BOOL fFirstIcon = FALSE; //KSO: data member in class
1599 int i, newsize;
1600
1601 //Calc aligned size (4 bytes align)
1602 newsize = (size + 3) & ~3;
1603 if (ResSection.curoff + newsize > ResSection.rawsize)
1604 {
1605 char *pTmp;
1606 pTmp = (char*)realloc((char*)ResSection.rawdata, ResSection.rawsize + max(size,0x2000));
1607 if (pTmp != NULL)
1608 {
1609#ifndef RING0
1610 ResSection.rawdata = pTmp;
1611#else
1612 ResSection.rawdata = (ULONG)pTmp;
1613#endif
1614 ResSection.rawsize = ResSection.virtualsize = ResSection.rawsize + max(size,0x2000);
1615 }
1616 else
1617 {
1618 kprintf(("LXHeaderSuper::StoreResource: failed to realloc - rawsize(=%d) + size(=%d) ",ResSection.rawsize,max(size,0x2000)));
1619 return FALSE;
1620 }
1621 }
1622 ltassert((ULONG)resourcedata > MINPTR && (ULONG)resourcedata < MAXPTR)
1623
1624 if (type == RT_POINTER && fFirstIcon == FALSE && curresource > 0)
1625 {
1626 //put this one in front of all resources so OS/2 recognizes
1627 //it as the program object icon
1628#ifndef _asmutils_h_
1629 char *tmpbuf = (char *)malloc(curresource*sizeof(rsrc32)+ResSection.curoff);
1630 ltassert(tmpbuf != NULL);
1631 memcpy(tmpbuf, (char *)os2resource, curresource*sizeof(rsrc32));
1632 memcpy((char *)&os2resource[1], tmpbuf, curresource*sizeof(rsrc32));
1633 memcpy(tmpbuf, (char*)ResSection.rawdata, ResSection.curoff);
1634 memcpy((char*)ResSection.rawdata, resourcedata, size);
1635 memcpy((char*)ResSection.rawdata+newsize, tmpbuf, ResSection.curoff);
1636 free(tmpbuf);
1637#else
1638 //memmov - found in asmutils
1639 memmov((void*)os2resource, sizeof(rsrc32), curresource*sizeof(rsrc32));
1640 memmov((char*)ResSection.rawdata, newsize, ResSection.curoff);
1641 memcpy((char*)ResSection.rawdata, resourcedata, size);
1642#endif
1643
1644 //Padd alignment
1645 for (i=0;i<newsize-size;i++)
1646 {
1647 ((char*) ResSection.rawdata)[size+i] = 0;
1648 }
1649
1650 os2resource[0].type = (USHORT)type;
1651 os2resource[0].name = (USHORT)id;
1652 os2resource[0].cb = size;
1653 os2resource[0].offset = 0;
1654
1655 //modify all offsets
1656 for (i=1;i<=curresource;i++)
1657 os2resource[i].offset += newsize;
1658 }
1659 else
1660 {
1661 memcpy((char*)ResSection.rawdata+ResSection.curoff, resourcedata, size);
1662
1663 //Padd alignment
1664 for (i=0;i<newsize-size;i++)
1665 ((char*)ResSection.rawdata)[ResSection.curoff+size+i] = 0;
1666
1667 os2resource[curresource].type = (USHORT)type;
1668 os2resource[curresource].name = (USHORT)id;
1669 os2resource[curresource].cb = size;
1670 os2resource[curresource].offset = ResSection.curoff;
1671 }
1672
1673 ResSection.curoff += newsize;
1674 curresource++;
1675
1676 return TRUE;
1677}
1678
1679
1680
1681/**
1682 * Sets size and allocate heap for resource section.
1683 * @param size Size in bytes.
1684 * @return TRUE : on success<br>
1685 * FALSE: on failure
1686 * @remark KSO: TODO - size*3 is not good enough, it wastes to much heap!
1687 */
1688BOOL LXHeaderSuper::SetResourceSize(int size)
1689{
1690 ResSection.virtualsize = ResSection.rawsize = size*3; //just to be sure (KSO:must not be too sure... *3)
1691#ifndef RING0
1692 ResSection.rawdata = (char *)malloc(ResSection.rawsize);
1693#else
1694 ResSection.rawdata = (ULONG)malloc(ResSection.rawsize);
1695#endif
1696 ltassert((char*)ResSection.rawdata != NULL);
1697 memset((char*)ResSection.rawdata, 0, ResSection.rawsize);
1698
1699 return TRUE;
1700}
1701
1702
1703
1704/**
1705 * Convert Win32 resource name to a resource id.
1706 * @param name Pointer to name (sz).
1707 * @return New resource id.
1708 */
1709int LXHeaderSuper::ConvertNametoId(char *name)
1710{
1711 NameId *resname = (NameId *)((USHORT *)cvtname + 1);
1712 int id;
1713 int i;
1714
1715 for (i=0;i<nrcvtnames;i++)
1716 {//check if this name is already converted
1717 if (stricmp(name, resname->name) == 0)
1718 return (resname->id);
1719 resname = (NameId *)((int)resname + sizeof(NameId) + strlen(resname->name));
1720 }
1721 //Not found, so create one
1722 id = GetUniqueId();
1723 curcvtname->id = id;
1724 strcpy(curcvtname->name, name);
1725 curcvtname = (NameId *)((int)curcvtname + sizeof(NameId) + strlen(name));
1726 nrcvtnames++;
1727 return (id);
1728}
1729
1730
1731
1732/**
1733 * Saves the resource which contains the converted names.
1734 * @return TRUE : on success<br>
1735 * FALSE: on failure
1736 * @remark Should allways be called after resources are processed.<br>
1737 * It also addjusts the TIB.
1738 */
1739BOOL LXHeaderSuper::SaveConvertedNames()
1740{
1741 BOOL rc = TRUE;
1742 if (nrcvtnames)
1743 {
1744 //first USHORT = nr of converted names
1745 *(USHORT *)cvtname = nrcvtnames;
1746 cvtnametableid = GetUniqueId();
1747 ltassert(cvtnametableid != 0);
1748 //fill in parameter for RegisterResourceInfo
1749 *(LONG *)&szTIBFix[TIBOffName] = cvtnametableid;
1750
1751 rc = StoreResource(cvtnametableid, RT_RCDATA, (int)curcvtname - (int)cvtname, (char *)cvtname);
1752 }
1753
1754 if (nrorgres && rc)
1755 {
1756 //first ULONG = nr of original win32 resources stored in OS/2 exe/dll
1757 orgrestable[0] = nrorgres;
1758 orgrestableid = GetUniqueId();
1759 ltassert(orgrestableid != 0);
1760
1761 //fill in parameter for RegisterResourceInfo
1762 *(LONG *)&szTIBFix[TIBOffName+5] = (fConsole << 24) | orgrestableid;
1763
1764 rc = StoreResource(orgrestableid, RT_RCDATA, (nrorgres+1)*sizeof(ULONG), (char *)orgrestable);
1765 }
1766 else
1767 *(LONG *)&szTIBFix[TIBOffName+5] = (fConsole << 24) | 0x888888;
1768
1769 //SvL: 18-7-'98: Store internal pe2lx version and version resource id
1770 *(LONG *)&szTIBFix[TIBOffPe2lxVer] = PE2LX_VERSION;
1771 *(LONG *)&szTIBFix[TIBOffVerResId] = VersionResourceId;
1772
1773 return rc;
1774}
1775
1776
1777/**
1778 * Set number of section in PESection array. Alloc heap for them and zero it out.
1779 * @param cSections Count of section.
1780 * @return TRUE : On success.
1781 * FALSE: On failure - fatal - object unusable
1782 */
1783BOOL LXHeaderSuper::SetNrSections(int cSections)
1784{
1785 //cPESections = cSections + (options.TIBFixObject && !(options.noExeTIBFix && IsEXE));
1786 cPESections = cSections + 1; //KSO Aug 16 1998: TIBFixSection;
1787 PESection = (Section*)malloc(cPESections*sizeof(Section));
1788 ltassert(PESection != NULL);
1789 memset(PESection, 0, cPESections*sizeof(Section));
1790
1791 return TRUE;
1792}
1793
1794
1795
1796/**
1797 * Creates the TIBFix Section
1798 * @param pOH Pointer to optionalheader from the PE file.
1799 * @return TRUE : On success.
1800 * FALSE: On failure - fatal - object unusable
1801 */
1802BOOL LXHeaderSuper::CreateTIBSection(PIMAGE_OPTIONAL_HEADER pOH)
1803{
1804 ULONG base;
1805
1806 /** @sketch
1807 * Where to place the TIBSection
1808 * if EXE then <br>
1809 * begin<br>
1810 * if imagebase is not 0x10000 then<br>
1811 * base = 0x10000<br>
1812 * else<br>
1813 * base = imagebase + imagesize (pageboundrary)<br>
1814 * end<br>
1815 *
1816 * if DLL then
1817 * base = imagebase + imagesize (pageboundrary)<br>
1818 * We could easily change this.
1819 */
1820 if (IsEXE && pOH->ImageBase >= 0x10000)
1821 base = 0x10000;
1822 else
1823 base = pOH->ImageBase + pOH->SizeOfImage;
1824
1825 StoreSection(
1826 (RAWDATA)szTIBFix,
1827 TIBSize,
1828 TIBSize,
1829 base,
1830 SECTION_CODE | SECTION_TIBFIX
1831 );
1832
1833 return TRUE;
1834}
1835
1836
1837
1838/**
1839 * Get Sectionindex of the TIBSection in the PESection array.
1840 * @return Index into PESection array on success<br>
1841 * -1 on failure
1842 */
1843int LXHeaderSuper::GetTIBSectionIdx()
1844{
1845 int i;
1846
1847 if (IsEXE && options.noExeTIBFix)
1848 return -1;
1849 for (i = 0; i < nrsections; i++)
1850 {
1851 if (!PESection[i].fInvalid && PESection[i].type & SECTION_TIBFIX)
1852 return i;
1853 }
1854
1855 return -1;
1856}
1857
1858
1859
1860/**
1861 * Get Object number of the TIBSection (in the Virtual LX-file).
1862 * @return Object number on success<br>
1863 * -1 on failure
1864 */
1865int LXHeaderSuper::GetTIBObjectNo()
1866{
1867 int i,j;
1868
1869 if (IsEXE && options.noExeTIBFix)
1870 return -1;
1871
1872 for (j = i = 0; i < nrsections; i++)
1873 {
1874 if (!PESection[i].fInvalid)
1875 {
1876 j++;
1877 if (PESection[i].type & SECTION_TIBFIX)
1878 return j;
1879 }
1880 }
1881
1882 return -1;
1883}
1884
1885
1886
1887/** KSO: Why is this uniqueId static ??? */
1888int LXHeaderSuper::uniqueId = RESID_CONVERTEDNAMES;
1889
1890
1891
1892
1893
1894
1895
1896
1897
Note: See TracBrowser for help on using the repository browser.