source: trunk/src/win32k/pe2lx/lxhdr.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: 20.1 KB
Line 
1/* $Id: lxhdr.cpp,v 1.1 1999-09-06 02:20:05 bird Exp $
2 *
3 * PE2LX PE image interpreter
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1998-1999 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13/*
14 * NOTE: NOT RING0 RING3 only!
15 */
16
17/*******************************************************************************
18* Defined Constants And Macros *
19*******************************************************************************/
20#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \
21 ((PIMAGE_DOS_HEADER)a)->e_lfanew + \
22 SIZE_OF_NT_SIGNATURE + \
23 sizeof(IMAGE_FILE_HEADER)))
24
25
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include "pe2lx.h" //KSO Tue 2nd June 1998
31
32
33/**
34 * Global LXHeader Object
35 */
36LXHeader OS2Exe;
37
38
39
40/**
41 * Constructor
42 */
43LXHeader::LXHeader() : LXHeaderSuper()
44{
45
46}
47
48
49/**
50 * Destructor
51 */
52LXHeader::~LXHeader()
53{
54 //LXHeaderSuper::~LXHeaderSuper();
55}
56
57
58
59/**
60 * Saves the LX-File.
61 * @param filename The name of the LX-file to be created.
62 */
63BOOL LXHeader::SaveNewExeFile(char *filename)
64{
65 PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(pBaseFile);
66 HFILE win32handle;
67 ULONG ulAction = 0; /* Action taken by DosOpen */
68 ULONG ulLocal = 0; /* File pointer position after DosSetFilePtr */
69 ULONG ulWrite;
70 APIRET rc;
71 struct o32_obj objtable;
72 struct o32_map *objpage;
73 int pagetblidx, i, j, k, idx, rawsize, objectsize;
74 int nrpages, pagedataoffset;
75 //BOOL fFirstCode = FALSE; //KSO Aug 16 1998: no TIB to think so much about any longer
76 int *fixuptable;
77 char modname[128+5];//KSO Aug 16 1998: +5 just to be sure
78 intfixup *frec;
79 namefixup *imprec;
80 realintfixup *frealrec, *currealrec;
81
82 rc = DosOpen(filename, /* File path name */
83 &win32handle, /* File handle */
84 &ulAction, /* Action taken */
85 0L, /* File primary allocation */
86 0L, /* File attribute */
87 OPEN_ACTION_CREATE_IF_NEW |
88 OPEN_ACTION_REPLACE_IF_EXISTS, /* Open function type */
89 OPEN_FLAGS_NOINHERIT |
90 OPEN_SHARE_DENYNONE |
91 OPEN_ACCESS_READWRITE, /* Open mode of the file */
92 0L); /* No extended attribute */
93
94 if (rc != NO_ERROR)
95 {
96 cout << "DosOpen returned " << rc << endl;
97 return (FALSE);
98 }
99 /* Move the file pointer back to the beginning of the file */
100 DosSetFilePtr(win32handle, 0L, FILE_BEGIN, &ulLocal);
101
102 rc = DosWrite(win32handle, achDosHeader, sizeof(achDosHeader), &ulWrite);
103 if (rc != NO_ERROR)
104 {
105 cout << "DosWrite returned " << rc << endl;
106 DosClose(win32handle); /* Close the file */
107 return (FALSE);
108 }
109 //write preliminary lx header
110 DosWrite(win32handle, &LXHdr, sizeof(LXHdr), &ulWrite);
111
112 //First take care of the resources (if present), see GetNrPages()
113 //works correctly
114 if (nrresources)
115 {
116 ResSection.virtualsize = ResSection.curoff;
117 ResSection.rawsize = ResSection.curoff;
118 } //done with resources
119
120 pagetblidx = 1; //start met 1
121 objtable.o32_reserved = 0;
122 pagedataoffset = 0;
123 nrpages = GetNrPages();
124 //SvL: 13 aug 1998
125 //objpage = (struct o32_map *)malloc((nrpages-(StackSize+0xFFF>>PAGE_SHIFT))*sizeof(o32_map));
126 objpage = (struct o32_map *)malloc(nrpages*sizeof(o32_map));
127
128 LXHdr.e32_objcnt = GetNrObjects2();
129 LXHdr.e32_mpages = 0;
130 idx = -1;
131 int objcnt = 1;
132
133 for (i=0;i<nrsections;i++)
134 {
135 objtable.o32_pagemap = pagetblidx;
136 if (PESection[i].fInvalid) continue;
137
138 switch (PESection[i].type)
139 {
140 case (SECTION_CODE | SECTION_TIBFIX): //KSO Aug 15 1998: TIBFixObject
141 case (SECTION_CODE | SECTION_IMPORT):
142 case SECTION_CODE:
143 objtable.o32_flags = OBJREAD | NSEXRD | OBJBIGDEF;
144 //if (fFirstCode == FALSE) //KSO Aug 16 1998: Entrypoint fixup
145 // LXHdr.e32_startobj = i+1;
146 break;
147 case SECTION_IMPORT:
148 objtable.o32_flags = OBJREAD | OBJBIGDEF;
149 break;
150 case SECTION_INITDATA:
151 objtable.o32_flags = OBJREAD | OBJWRITE | OBJBIGDEF;
152 break;
153 case SECTION_COMBINEDDATA:
154 objtable.o32_flags = OBJREAD | OBJWRITE | OBJBIGDEF;
155 //LXHdr.e32_startobj = 1;
156 break;
157 case SECTION_RESOURCE_ORG:
158 case SECTION_UNINITDATA:
159 //SvL: Zero filled flag maps on Permanent flag, so ditch it
160 objtable.o32_flags = OBJREAD | OBJWRITE | OBJBIGDEF; //read/write/big
161 break;
162 case SECTION_READONLYDATA:
163 objtable.o32_flags = OBJREAD | OBJBIGDEF;
164 break;
165 }
166 //OS/2 doesn't seem to mind if the sizes of all the pages in an object
167 //exceeds the object size....
168 if (PESection[i].type == SECTION_UNINITDATA)
169 objectsize = PESection[i].virtualsize; //rawsize == 0
170 else objectsize = PESection[i].rawsize;
171
172 objtable.o32_mapsize = PESection[i].nrpages;
173
174 objtable.o32_mapsize += PESection[i].nrinvalidpages;
175 objtable.o32_base = PESection[i].address;
176 objtable.o32_size = objtable.o32_mapsize*PAGE_SIZE;
177
178 rawsize = PESection[i].rawsize;
179 for (j=0;j<objtable.o32_mapsize;j++)
180 {
181 idx = pagetblidx+j-1;
182 objpage[idx].o32_pagedataoffset = pagedataoffset;
183
184 if (j < PESection[i].nrinvalidpages)
185 {
186 objpage[idx].o32_pagesize = 0;
187 //SvL: Invalid pages are not properly handled by the OS/2 loader -> make 'em zeroed
188 objpage[idx].o32_pageflags = ZEROED;
189 }
190 else
191 {
192 if (PESection[i].type == SECTION_COMBINEDDATA)
193 {
194 //KSO Aug 16 1998: There is no longer a TIBFix in COMBINEDDATA - code removed
195 int didx = j - PESection[i].nrinvalidpages;
196 objpage[idx].o32_pagesize = datapage[didx].size;
197 objpage[idx].o32_pageflags = datapage[didx].flags;
198 pagedataoffset += objpage[idx].o32_pagesize;
199 if (objpage[idx].o32_pageflags == 0)
200 LXHdr.e32_mpages++;
201
202 }
203 else
204 if (PESection[i].type == SECTION_UNINITDATA || rawsize == 0)
205 {
206 objpage[idx].o32_pagesize = 0;
207 objpage[idx].o32_pagedataoffset = pagedataoffset;
208 objpage[idx].o32_pageflags = ZEROED;
209 }
210 else
211 { //KSO Aug 16 1998: TIBFixObject - TIBFix code removed
212 if (rawsize > PAGE_SIZE)
213 objpage[idx].o32_pagesize = PAGE_SIZE;
214 else
215 objpage[idx].o32_pagesize = rawsize;
216 rawsize -= objpage[idx].o32_pagesize;
217 objpage[idx].o32_pageflags = 0;
218 LXHdr.e32_mpages++;
219 pagedataoffset += objpage[idx].o32_pagesize;
220 }
221 }
222 }
223
224 if (IsEXE && i == nrsections - 1)
225 {//SvL: 25-7-'97 Add stack pages to last data object
226 LXHdr.e32_stackobj = objcnt;
227 LXHdr.e32_autodata = LXHdr.e32_stackobj;
228 objtable.o32_flags |= OBJWRITE;
229 objtable.o32_size += StackSize;
230 LXHdr.e32_esp = objtable.o32_size; //highest address in object
231 }
232
233 //Write object table entry to file
234 DosWrite(win32handle, &objtable, sizeof(objtable), &ulWrite);
235
236 pagetblidx += objtable.o32_mapsize;
237 objcnt++;
238 }
239
240
241 /* KSO Aug 15 1998: EntryPoint - TIBFixObject */
242 // Sets entrypoint to TIBFixSection and changes the TIBFix call
243 int iPESection = GetTIBSectionIdx();
244 LXHdr.e32_eip = 0;
245 LXHdr.e32_startobj = GetTIBObjectNo();
246 ltassert(LXHdr.e32_startobj != -1 && iPESection != -1);
247 *(PULONG)&szTIBFix[TIBOffEntry] = pOptionalHeader->AddressOfEntryPoint //RVA
248 + pOptionalHeader->ImageBase
249 - (PESection[iPESection].address + TIBOffCall + SIZE_TIBCALL);
250
251
252
253 if (nrresources)
254 {
255 //Correct count in case there are string tables which aren't completely filled
256 nrresources = curresource;
257 //KSO: already done by GetNrObjects2 //LXHdr.e32_objcnt++;
258 objtable.o32_pagemap = pagetblidx;
259 objtable.o32_flags = NSSHARED | OBJREAD | OBJRSRC | OBJBIGDEF;
260 objtable.o32_mapsize = ResSection.rawsize >> PAGE_SHIFT;
261
262 objtable.o32_base = 0; //SvL: Set to 0 in PM exes (plf)
263 objtable.o32_size = ResSection.rawsize;
264
265 for (j=0;j<objtable.o32_mapsize;j++)
266 {
267 idx = pagetblidx+j-1;
268 objpage[idx].o32_pagedataoffset = pagedataoffset;
269 objpage[idx].o32_pagesize = PAGE_SIZE;
270 objpage[idx].o32_pageflags = 0;
271 LXHdr.e32_mpages++;
272 pagedataoffset += PAGE_SIZE;
273 }
274 if ((objtable.o32_size & 0xFFF) != 0)
275 {
276 objtable.o32_mapsize++;
277 LXHdr.e32_mpages++;
278 idx++;
279 objpage[idx].o32_pagedataoffset = pagedataoffset;
280 objpage[idx].o32_pagesize = (USHORT)(objtable.o32_size & 0xFFF);
281 objpage[idx].o32_pageflags = 0;
282 pagedataoffset += objpage[idx].o32_pagesize;
283 }
284
285 //Write resource object table to file
286 DosWrite(win32handle, &objtable, sizeof(objtable), &ulWrite);
287 pagetblidx += objtable.o32_mapsize;
288
289 //fill in object nr's in resource table entries
290 for (i=0;i<nrresources;i++)
291 {
292 os2resource[i].obj = LXHdr.e32_objcnt;
293 }
294 }
295
296 //Write object page table entries to file
297 //DosWrite(win32handle, objpage, sizeof(*objpage)*(nrpages-(StackSize+0xFFF>>PAGE_SHIFT)), &ulWrite);
298 DosWrite(win32handle, objpage, sizeof(*objpage)*nrpages, &ulWrite);
299
300 //object page records offset:
301 LXHdr.e32_objmap = LXHdr.e32_objtab + LXHdr.e32_objcnt*sizeof(objtable);
302 //size tables vanaf object table t/m impproc (eigenlijk pagesum ook..)
303 //LXHdr.e32_ldrsize = LXHdr.e32_objcnt*sizeof(objtable) + (nrpages-(StackSize+0xFFF>>PAGE_SHIFT))*sizeof(o32_map);
304 LXHdr.e32_ldrsize = LXHdr.e32_objcnt*sizeof(objtable) + nrpages*sizeof(o32_map);
305
306 //resource table:
307 LXHdr.e32_rsrctab = LXHdr.e32_ldrsize + LXHdr.e32_objtab;
308 LXHdr.e32_rsrccnt = nrresources;
309 if (nrresources)
310 {
311 DosWrite(win32handle, (char *)os2resource, nrresources*sizeof(rsrc32), &ulWrite);
312 }
313 LXHdr.e32_ldrsize += nrresources*sizeof(rsrc32);
314
315 //resident name table + entry table:
316 LXHdr.e32_restab = LXHdr.e32_rsrctab + nrresources*sizeof(rsrc32);
317
318
319#if 1 //KSO Aug 16 1998: exports from exes and dll without exports: TODO cleanup!
320 //write DLL/EXE export information
321 if (exports)
322 {
323 int len = 0;
324
325 //save resident name table
326 if (exports)
327 {
328 len = curexport - exports + 1; // + 0 byte to signal end of table
329 rc = DosWrite(win32handle, exports, len, &ulWrite);
330 LXHdr.e32_ldrsize += len;
331 }
332
333 //save entry table
334 LXHdr.e32_enttab = LXHdr.e32_restab + len;
335 //TODO: Forwarders!
336 len = (int)curexpb - (int)expbundle + 1; // + 0 byte to signal end of table
337 if (len > 1)
338 {
339 rc = DosWrite(win32handle, expbundle, len, &ulWrite);
340 LXHdr.e32_ldrsize += len;
341 }
342 }
343 else
344 {
345 int modlen;
346 //save resident name table
347 memset(modname, 0, sizeof(modname));
348 strcpy(modname, modulename);
349 modlen = strlen(&modname[1]);
350 modlen += 1 + 2 + 1; //len byte + ord word + 0 byte
351 DosWrite(win32handle, modname, modlen, &ulWrite);
352
353 //save entry table
354 LXHdr.e32_enttab = LXHdr.e32_restab + modlen; //points to 0 byte
355 DosWrite(win32handle, "", 1, &ulWrite);
356 LXHdr.e32_ldrsize += 1 + modlen;
357 }
358
359#else
360
361 if (IsEXE == TRUE)
362 {
363 int modlen;
364 //save resident name table
365 //KSO: modname has right format - Jun 16 1998 4:27pm
366 memset(modname, 0, sizeof(modname));
367 strcpy(modname, modulename);
368 //strcpy(&modname[1], modulename);
369 //UpCase(&modname[1]); // this is already done!
370 modlen = strlen(&modname[1]);
371 //modname[0] = (char)modlen;
372 modlen += 1 + 2 + 1; //len byte + ord word + 0 byte
373 DosWrite(win32handle, modname, modlen, &ulWrite);
374
375 //save entry table
376 LXHdr.e32_enttab = LXHdr.e32_restab + modlen; //points to 0 byte
377 modname[0] = 0;
378 DosWrite(win32handle, modname, 1, &ulWrite);
379 LXHdr.e32_ldrsize += 1 + modlen;
380 }
381 else
382 {//write DLL export information
383 int len = 0;
384
385 //save resident name table
386 if (exports)
387 {
388 len = curexport - exports + 1; // + 0 byte to signal end of table
389 rc = DosWrite(win32handle, exports, len, &ulWrite);
390 LXHdr.e32_ldrsize += len;
391 }
392
393 //save entry table
394 LXHdr.e32_enttab = LXHdr.e32_restab + len;
395 //TODO: Forwarders!
396 len = (int)curexpb - (int)expbundle + 1; // + 0 byte to signal end of table
397 if (len > 1)
398 {
399 rc = DosWrite(win32handle, expbundle, len, &ulWrite);
400 LXHdr.e32_ldrsize += len;
401 }
402 }
403#endif
404
405 /* FIXUPS */
406 //#pages * offset naar import fixups + 1 eind offset
407 LXHdr.e32_fpagetab = LXHdr.e32_ldrsize + LXHdr.e32_objtab;
408 LXHdr.e32_frectab = LXHdr.e32_fpagetab + (nrpages+1)*sizeof(int);
409 fixuptable = (int *)malloc((nrpages+1)*sizeof(int));
410 for (i=0;i<nrpages+1;i++) fixuptable[i] = 0;
411
412 //dump alle fixup records in 1 memory block en bepaal offsets in fixup page table
413 frec = &intfixuprec[0];
414 imprec = &impfixuprec[0];
415 //KSO Aug 15 1998: TIBFixObject - "+ 1" (internal entrypoint fixup)
416 frealrec = (realintfixup *)malloc(
417 (nrintfixups + 1) * sizeof(realintfixup)
418 + (nrimpfixups + EXTRA_FIXUPS) * sizeof(realnamefixup)
419 );
420 /* KSO Aug 16 1998: we need the pageno of the TIBSection */
421 int TIBPageNo = GetTIBSectionIdx();
422 ltassert(TIBPageNo != 1);
423 TIBPageNo = GetPageNoByVA(PESection[TIBPageNo].address);
424
425 currealrec = frealrec;
426 j = 0;
427 k = 0;
428 for (i=0;i<nrpages;i++)
429 {
430 fixuptable[i] = (int)currealrec - (int)frealrec;
431 if (i == TIBPageNo)
432 {//add kernel32:registerresourceinfo import
433 realordfixup *kerord = (realordfixup *)currealrec;
434 kerord->nr_stype = 0x07; //32 bits offset
435 kerord->nr_flags = 0x01 | 0x40; //import by ordinal + mod offset = 16 bits
436 kerord->r32_soff = TIBOffKerImport;
437 kerord->r32_objmod = kernel32Object + 1;
438 if (IsEXE)
439 kerord->ord = ORD_REGISTERRESOURCEINFO;
440 else
441 kerord->ord = ORD_REGISTERDLL;
442
443 currealrec = (realintfixup *)((int)currealrec + sizeof(realnamefixup));
444 if (!IsEXE)
445 {
446 kerord = (realordfixup *)currealrec;
447 kerord->nr_stype = 0x08; //32 bits self referencing offset
448 kerord->nr_flags = 0x01 | 0x40; //import by ordinal + mod offset = 16 bits
449 kerord->r32_soff = DLL_OFF_KERIMP2;
450 kerord->r32_objmod = kernel32Object + 1;
451 kerord->ord = ORD_KERNEL32DLLEXITLIST;
452 currealrec = (realintfixup *)((int)currealrec + sizeof(realnamefixup));
453 }
454
455 /* add entrypoint internal fixup */
456 realintfixup *pEntInt = currealrec;
457 int SectNo;
458 pEntInt->nr_stype = 0x08; //self referencing
459 pEntInt->nr_flags = 0x00 | 0x10 | 0x40;
460 pEntInt->r32_soff = TIBOffEntry;
461 pEntInt->targetaddr = pOptionalHeader->ImageBase + pOptionalHeader->AddressOfEntryPoint;
462 pEntInt->targetobj = GetObjectNoByVA(pEntInt->targetaddr);
463 ltassert(pEntInt->targetobj != 0);
464 SectNo = GetSectionIdxByVA(pEntInt->targetaddr);
465 ltassert(SectNo != -1);
466 pEntInt->targetaddr -= PESection[SectNo].address;
467 currealrec++;
468 }
469
470 //SvL: 16-9-'97, for multiple import pages
471 while (k < nrimpfixups && imprec->srcpage == i)
472 {
473 //sizeof(realordfixup) == sizeof(realnamefixup)
474 memcpy(currealrec, imprec, sizeof(realnamefixup));
475 currealrec = (realintfixup *)((int)currealrec + sizeof(realnamefixup));
476 imprec++;
477 k++;
478 }
479 while (j < nrintfixups && frec->srcpage == i)
480 {
481 memcpy(currealrec, frec, sizeof(realintfixup));
482 //cout << "src address " << frec->r32_soff << " srcpage " << frec->srcpage << " target " << frec->targetaddr << " frec " << (int)frec << endl;
483 frec++;
484 currealrec++;
485 j++;
486 }
487 }
488 fixuptable[nrpages] = (int)currealrec - (int)frealrec;
489
490 //Add extra kernel32 imports
491 if (IsEXE)
492 nrimpfixups++;
493 else nrimpfixups += EXTRA_FIXUPS;
494
495 nrintfixups += 1; //KSO Aug 15 1998: TIBFixObject internal entrypoint fixup
496
497 //Write fixup page table
498 DosWrite(win32handle, fixuptable, (nrpages+1)*sizeof(int), &ulWrite);
499 //Write fixup record table
500 DosWrite(win32handle, frealrec, (int)currealrec - (int)frealrec, &ulWrite); //KSO Aug 15 1998: calc of fixupsize.
501
502 //fixup page + record + import name + module table size
503 LXHdr.e32_fixupsize = (nrpages+1)*sizeof(int) + (int)currealrec - (int)frealrec + impmodulesize + impnamesize; //KSO Aug 15 1998: calc of fixupsize.
504
505 //size tables vanaf object table t/m impproc (eigenlijk pagesum ook..)
506 LXHdr.e32_ldrsize += LXHdr.e32_fixupsize;
507
508 //offset naar module name array
509 LXHdr.e32_impmod = LXHdr.e32_frectab + (int)currealrec - (int)frealrec; //KSO Aug 15 1998: calc of fixupsize.
510 //offset naar proc name array
511 LXHdr.e32_impproc = LXHdr.e32_impmod + impmodulesize;
512 //Write Import Module array
513 DosWrite(win32handle, impmodules, impmodulesize, &ulWrite);
514 //Write Import Procedure Name array
515 DosWrite(win32handle, impnames, impnamesize, &ulWrite);
516
517 //pointer naar begin code/data
518 LXHdr.e32_datapage = LXHdr.e32_impproc + impnamesize + LXHEADER_OFFSET; //vanaf begin ipv lxheader
519
520 free(frealrec);
521 free(fixuptable);
522
523
524 for (i=0;i<nrsections;i++)
525 {
526 //zero filled pages, niet nodig om op te slaan
527 if (PESection[i].type != SECTION_UNINITDATA && PESection[i].rawdata)
528 DosWrite(win32handle, PESection[i].rawdata, PESection[i].rawsize, &ulWrite);
529 //KSO Aug 16 1998: Removed some TIB-code
530 }
531 if (nrresources)
532 DosWrite(win32handle, ResSection.rawdata, ResSection.rawsize, &ulWrite);
533
534 DosSetFilePtr(win32handle, LXHEADER_OFFSET, FILE_BEGIN, &ulLocal);
535 //write final lx header
536 DosWrite(win32handle, &LXHdr, sizeof(LXHdr), &ulWrite);
537
538 free(objpage);
539 DosClose(win32handle); /* Close the file */
540
541 return (TRUE);
542}
543
Note: See TracBrowser for help on using the repository browser.