source: trunk/tools/common/kFileLX.cpp@ 4804

Last change on this file since 4804 was 4750, checked in by bird, 25 years ago

Not completed implementation of kPageI.

File size: 17.7 KB
Line 
1/* $Id: kFileLX.cpp,v 1.3 2000-12-04 08:48:08 bird Exp $
2 *
3 *
4 *
5 * Copyright (c) 2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 */
10
11/*******************************************************************************
12* Defined Constants *
13*******************************************************************************/
14/* emx fixups */
15#ifdef __EMX__
16 #define __stdcall
17 #define max(a,b) (((a) > (b)) ? (a) : (b))
18 #define min(a,b) (((a) < (b)) ? (a) : (b))
19#endif
20#define INCL_DOSERRORS
21#define FOR_EXEHDR 1 /* exe386.h flag */
22#define DWORD ULONG /* Used by exe386.h / newexe.h */
23#define WORD USHORT /* Used by exe386.h / newexe.h */
24
25
26/******************************************************************************
27* Header Files *
28******************************************************************************/
29#ifdef __EMX__
30#define INT INT_
31#define PCHAR PCHAR_
32#endif
33#include <os2.h>
34#ifdef __EMX__
35#undef PCHAR
36#undef INT
37#endif
38#include <newexe.h>
39#include <exe386.h>
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <malloc.h>
45
46#include <assert.h>
47
48#include "kFileFormatBase.h"
49#include "kInterfaces.h"
50#include "kFileLX.h"
51
52
53/*******************************************************************************
54* Structures and Typedefs *
55*******************************************************************************/
56typedef struct _export_state
57{
58 struct b32_bundle * pb32; /* Pointer to current bundle. */
59 int iOrdinalBundle; /* The ordinal the bundle starts at. */
60 struct e32_entry * pe32; /* Pointer to the current bundle entry. */
61 int iOrdinal; /* The current ordinal. */
62} EXPSTATE, *PEXPSTATE;
63
64
65
66BOOL kFileLX::queryExportName(int iOrdinal, char *pszBuffer)
67{
68 PUSHORT pus;
69 PUCHAR puch;
70
71 /* resident name table */
72 if (pe32->e32_restab)
73 {
74 puch = (PUCHAR)pvBase + offLXHdr + pe32->e32_restab;
75 while (*puch != 0)
76 {
77 pus = (PUSHORT)(puch + 1 + *puch);
78 if (*pus == iOrdinal)
79 {
80 memcpy(pszBuffer, puch + 1, *puch);
81 pszBuffer[*puch] = '\0';
82 return TRUE;
83 }
84 puch += *puch + 1 + 2;
85 }
86 }
87
88 /* not found, check the non-resident name table too */
89 if (pe32->e32_nrestab)
90 {
91 puch = (PUCHAR)pvBase + pe32->e32_nrestab;
92 while (*puch != 0)
93 {
94 pus = (PUSHORT)(puch + 1 + *puch);
95 if (*pus == iOrdinal)
96 {
97 memcpy(pszBuffer, puch + 1, *puch);
98 pszBuffer[*puch] = '\0';
99 return TRUE;
100 }
101 puch += *puch + 1 + 2;
102 }
103 }
104
105 return FALSE;
106}
107
108
109
110/**
111 * Create an LX file object from an LX executable image.
112 * @param pszFilename LX executable image name.
113 */
114kFileLX::kFileLX(const char *pszFilename)
115: pvBase(NULL)
116{
117 struct exe_hdr * pehdr;
118
119 /* create filemapping */
120 pvBase = kFileFormatBase::readfile(pszFilename);
121 if (pvBase == NULL)
122 throw(1);
123
124 pehdr = (struct exe_hdr*)pvBase;
125 if (pehdr->e_magic == EMAGIC)
126 offLXHdr = pehdr->e_lfanew;
127 else
128 offLXHdr = 0;
129
130 pe32 = (struct e32_exe*)((char*)pvBase + offLXHdr);
131 if (*(PUSHORT)pe32 != E32MAGIC)
132 {
133 free(pvBase);
134 pvBase = NULL;
135 throw(2);
136 }
137
138 paObject = pe32->e32_objtab && pe32->e32_objcnt
139 ? (struct o32_obj*)((char*)pvBase + pe32->e32_objtab + offLXHdr) : NULL;
140 paMap = pe32->e32_objmap
141 ? (struct o32_map*)((char*)pvBase + pe32->e32_objmap + offLXHdr) : NULL;
142}
143
144
145
146/**
147 * Destructor.
148 */
149kFileLX::~kFileLX()
150{
151 if (pvBase != NULL)
152 free(pvBase);
153 pvBase = NULL;
154}
155
156
157
158BOOL kFileLX::queryModuleName(char *pszBuffer)
159{
160 /* The module name is the 0 ordinal entry in resident name table */
161 return queryExportName(0, pszBuffer);
162}
163
164
165
166BOOL kFileLX::findFirstExport(PEXPORTENTRY pExport)
167{
168 struct b32_bundle * pBundle = (struct b32_bundle*)((char*)pvBase + pe32->e32_enttab + offLXHdr);
169 struct e32_entry * pEntry;
170 int iOrdinal = 1;
171
172 if (pe32->e32_enttab)
173 {
174 while (pBundle->b32_cnt != 0)
175 {
176 /* skip empty bundles */
177 while (pBundle->b32_cnt != 0 && pBundle->b32_type == EMPTY)
178 {
179 iOrdinal += pBundle->b32_cnt;
180 pBundle = (struct b32_bundle*)((char*)pBundle + 2);
181 }
182
183 /* FIXME forwarders are not implemented so we'll skip them too. */
184 while (pBundle->b32_cnt != 0 && (pBundle->b32_type & ~TYPEINFO) == ENTRYFWD)
185 {
186 iOrdinal += pBundle->b32_cnt;
187 pBundle = (struct b32_bundle*)((char*)(pBundle + 1) + pBundle->b32_cnt * 7);
188 }
189
190 /* we'll ignore any flags for the moment - TODO */
191 if (pBundle->b32_cnt != 0)
192 {
193 pExport->ulOrdinal = iOrdinal;
194 pExport->iObject = pBundle->b32_obj;
195
196 /* look for name */
197 pExport->achIntName[0] = '\0';
198 if (!queryExportName(iOrdinal, pExport->achName))
199 pExport->achName[0] = '\0';
200
201 pEntry = (struct e32_entry*)(pBundle+1);
202 switch (pBundle->b32_type & ~TYPEINFO)
203 {
204 case ENTRY16:
205 pExport->offset = pEntry->e32_variant.e32_offset.offset16;
206 break;
207
208 case ENTRY32:
209 pExport->offset = pEntry->e32_variant.e32_offset.offset32;
210 break;
211
212 case GATE16:
213 pExport->offset = pEntry->e32_variant.e32_callgate.offset;
214 break;
215 default:
216 assert(!"ARG!!!! invalid bundle type!");
217 }
218
219 /* store status - current export entry */
220 PEXPSTATE pExpState = (PEXPSTATE)malloc(sizeof(EXPSTATE));
221 pExport->pv = pExpState;
222 pExpState->pb32 = pBundle;
223 pExpState->iOrdinalBundle = iOrdinal;
224 pExpState->pe32 = pEntry;
225 pExpState->iOrdinal = iOrdinal;
226 return TRUE;
227 }
228 }
229
230 }
231
232 return FALSE;
233}
234
235
236
237BOOL kFileLX::findNextExport(PEXPORTENTRY pExport)
238{
239 static int acbEntry[] =
240 {
241 0, /* EMPTY */
242 3, /* ENTRY16 */
243 5, /* GATE16 */
244 5, /* ENTRY32 */
245 7 /* ENTRYFWD */
246 };
247
248 PEXPSTATE pExpState = (PEXPSTATE)pExport->pv;
249
250 /*
251 * Get more ordinals from the current bundle if any left.
252 */
253 if (pExpState->pb32->b32_cnt > (pExpState->iOrdinal - pExpState->iOrdinalBundle + 1))
254 {
255 /* skip to the next entry */
256 pExpState->iOrdinal++;
257 pExpState->pe32 = (struct e32_entry*)((char*)pExpState->pe32
258 + acbEntry[pExpState->pb32->b32_type & ~TYPEINFO]);
259
260 /* fill output struct */
261 pExport->ulOrdinal = pExpState->iOrdinal;
262 pExport->iObject = pExpState->pb32->b32_obj;
263
264 /* look for name */
265 pExport->achIntName[0] = '\0';
266 if (!queryExportName(pExpState->iOrdinal, pExport->achName))
267 pExport->achName[0] = '\0';
268
269 /* offset */
270 switch (pExpState->pb32->b32_type & ~TYPEINFO)
271 {
272 case ENTRY16:
273 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset16;
274 break;
275
276 case ENTRY32:
277 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset32;
278 break;
279
280 case GATE16:
281 pExport->offset = pExpState->pe32->e32_variant.e32_callgate.offset;
282 break;
283 }
284
285 return TRUE;
286 }
287
288 /*
289 * next bundle.
290 */
291 pExpState->pb32 = (struct b32_bundle*)((char*)(pExpState->pb32 + 1) +
292 pExpState->pb32->b32_cnt * acbEntry[pExpState->pb32->b32_type & ~TYPEINFO]);
293 while (pExpState->pb32->b32_cnt != 0)
294 {
295 /* skip empty bundles */
296 while (pExpState->pb32->b32_cnt != 0 && pExpState->pb32->b32_type == EMPTY)
297 {
298 pExpState->iOrdinal += pExpState->pb32->b32_cnt;
299 pExpState->pb32 = (struct b32_bundle*)((char*)pExpState->pb32 + 2);
300 }
301
302 /* FIXME forwarders are not implemented so we'll skip them too. */
303 while (pExpState->pb32->b32_cnt != 0 && (pExpState->pb32->b32_type & ~TYPEINFO) == ENTRYFWD)
304 {
305 pExpState->iOrdinal += pExpState->pb32->b32_cnt;
306 pExpState->pb32 = (struct b32_bundle*)((char*)(pExpState->pb32 + 1) + pExpState->pb32->b32_cnt * 7);
307 }
308
309 /* we'll ignore any flags for the moment - TODO */
310 if (pExpState->pb32->b32_cnt != 0)
311 {
312 pExpState->iOrdinalBundle = pExpState->iOrdinal;
313
314 pExport->ulOrdinal = pExpState->iOrdinal;
315 pExport->iObject = pExpState->pb32->b32_obj;
316
317 /* look for name */
318 pExport->achIntName[0] = '\0';
319 if (!queryExportName(pExpState->iOrdinal, pExport->achName))
320 pExport->achName[0] = '\0';
321
322 pExpState->pe32 = (struct e32_entry*)(pExpState->pb32+1);
323 switch (pExpState->pb32->b32_type & ~TYPEINFO)
324 {
325 case ENTRY16:
326 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset16;
327 break;
328
329 case ENTRY32:
330 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset32;
331 break;
332
333 case GATE16:
334 pExport->offset = pExpState->pe32->e32_variant.e32_callgate.offset;
335 break;
336 default:
337 assert(!"ARG!!!! invalid bundle type!");
338 }
339
340 return TRUE;
341 }
342 }
343
344
345 /*
346 * No more exports - clean up
347 */
348 free(pExport->pv);
349 pExport->pv = NULL;
350 return FALSE;
351}
352
353
354/**
355 * Gets a specific LX object.
356 * @returns Pointer to object. NULL on error / invalid index.
357 * @param iObject object number (0-based)
358 */
359struct o32_obj * kFileLX::getObject(int iObject)
360{
361
362 if (iObject < pe32->e32_objcnt)
363 return &paObject[iObject];
364 return NULL;
365}
366
367
368/**
369 * Gets the count of LX objects.
370 * @returns Count of LX objects.
371 */
372int kFileLX::getObjectCount()
373{
374 return (int)pe32->e32_objcnt;
375}
376
377#if 0
378
379/** @cat Get and put page methods. (the first ones are generic) */
380BOOL kFileLX::getPage(char *pachPage, ULONG ulAddress)
381{
382 int iObj;
383
384 for (iObj = 0; iObj < pe32->e32_objcnt; iObj++)
385 if ( paObject[iObj].o32_base > ulAddress
386 && paObject[iObj].o32_base + paObject[iObj].o32_size > ulAddress
387 )
388 return getPage(pachPage, iObj, ulAddress - paObject[iObj].o32_base);
389
390 return FALSE;
391}
392
393BOOL kFileLX::getPage(char *pachPage, int iObject, int offObject)
394{
395 offObject &= ~(PAGESIZE - 1);
396 if ( iObject >= pe32->e32_objcnt
397 && offObject >= paObject[iObject].o32_size
398 )
399 return FALSE;
400
401 /*
402 * Is there a pagemap entry for the requested page?
403 */
404 if ((offObject >> PAGESHIFT) < paObject[iObject].o32_mapsize)
405 { /* yes */
406 int iPage = (offObject >> PAGESIZE) + paObject[iObject].o32_pagemap - 1;
407 char * pchPageData = (char*)((paMap[iPage].o32_pagedataoffset << pe32->e32_pageshift) + pe32->e32_datapage + (char*)pvBase);
408
409 if (pchPageData )
410 {
411 }
412
413 }
414 else
415 { /* no, so it's a zero page */
416 memset(pachPage, 0, PAGESIZE);
417 }
418
419 return FALSE;
420}
421
422BOOL kFileLX::putPage(const char *pachPage, ULONG ulAddress)
423{
424 return FALSE;
425}
426
427BOOL kFileLX::putPage(const char *pachPage, int iObject, int offObject)
428{
429 return FALSE;
430}
431
432BOOL kFileLX::getPageLX(char *pachPage, int iObject, int iPage)
433{
434 return FALSE;
435}
436
437BOOL kFileLX::getPageLX(char *pachPage, int iPage)
438{
439 return FALSE;
440}
441
442BOOL kFileLX::putPageLX(const char *pachPage, int iObject, int iPage)
443{
444 return FALSE;
445}
446
447BOOL kFileLX::putPageLX(const char *pachPage, int iPage)
448{
449 return FALSE;
450}
451
452
453/**
454 * Expands a page compressed with the old exepack method introduced with OS/2 2.0.
455 * (/EXEPACK or just /EXEPACK)
456 * @returns Successindicator.
457 * @param pachPage Pointer to output page. size: PAGESIZE
458 * Upon successful return this will contain the expanded page data.
459 * @param pachSrcPage Pointer to source data. size: cchSrcPage.
460 * This data should be compressed with EXEPACK:2!
461 * @sketch Have no good idea right now.
462 * @status Completely implemented.
463 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
464 * @remark
465 */
466BOOL kFileLX::expandPage1(char *pachPage, const char * pachSrcPage, int cchSrcPage)
467{
468 struct LX_Iter *pIter = (struct LX_Iter *)pachSrcPage;
469 char * pachDestPage = pachPage; /* Store the pointer for boundrary checking. */
470
471 /* Validate size of data. */
472 if (cchSrcPage >= PAGESIZE - 2)
473 return FALSE;
474
475 /*
476 * Expand the page.
477 */
478 while (pIter->LX_nIter)
479 {
480 /* Check if we're out of bound. */
481 if ( pachPage - pachDesPage + pIter->LX_nIter * pIter->LX_nBytes > PAGESIZE
482 || cchSrcPage <= 0)
483 return FALSE;
484
485 if (pIter->LX_nBytes == 1)
486 { /* one databyte */
487 memset(pachPage, &pIter->LX_Iterdata, pIter->LX_nIter);
488 pchPage += pIter->LX_nIter;
489 cchSrcPage -= pIter->LX_nIter + 4;
490 pIter++;
491 }
492 else
493 {
494 for (int i = 0; i < pIter->LX_nIter; i++, pachPage += pIter->LX_nBytes)
495 memcpy(pachPage, &pIter->LX_Iterdata, pIter->LX_nBytes);
496 cchSrcPage -= 4 + pIter->LX_nBytes;
497 pIter = (pIter)((char*)pIter 4 + pIter->LX_nBytes);
498 }
499 }
500 return TRUE;
501#if 0
502/* example code */
503 int off;
504 struct LX_Iter *pIter;
505 char * pch = pvPage; /* Current position on page */
506
507 off = pe32->e32_datapage + (pObjMap->o32_pagedataoffset << pe32->e32_pageshift);
508 if (pObjMap->o32_pagesize && (off + pObjMap->o32_pagesize - 1) >= cbFile)
509 {
510 fprintf(stderr, "Error: Page resides outside of the file.\n");
511 return 1;
512 }
513 pIter = (struct LX_Iter *)((char*)pvFile + off);
514
515 /* expand page */
516 while (pIter->LX_nIter > 0)
517 {
518 if (pch + (pIter->LX_nBytes * pIter->LX_nIter) > (char*)pvPage + OBJPAGELEN)
519 {
520 fprintf(stderr, "Error: Iterated page expands to more than a page!\n");
521 return 1;
522 }
523
524 if (pIter->LX_nBytes == 1)
525 {
526 memset(pch, pIter->LX_Iterdata, pIter->LX_nIter);
527 pch += pIter->LX_nIter;
528 pIter++;
529 }
530 else
531 {
532 int i;
533 for (i = 0; i < pIter->LX_nIter; i++, pch += pIter->LX_nBytes)
534 memcpy(pch, &pIter->LX_Iterdata, pIter->LX_nBytes);
535 #if 1 /* curious */
536 if (pIter->LX_nBytes > 2) fprintf(stdout, "pIter->LX_nBytes = %\n", pIter->LX_nBytes);
537 #endif
538
539 pIter = (struct LX_Iter*)((char*)pIter + 4 + pIter->LX_nBytes);
540 }
541 }
542
543 return FALSE;
544#endif
545}
546
547
548/**
549 * Expands a page compressed with the exepack method introduced with OS/2 Warp 3.0.
550 * (/EXEPACK:2)
551 * @returns Successindicator.
552 * @param pachPage Pointer to output page. size: PAGESIZE
553 * Upon successful return this will contain the expanded page data.
554 * @param pachSrcPage Pointer to source data. size: cchSrcPage.
555 * This data should be compressed with EXEPACK:2!
556 * @sketch Have no good idea right now.
557 * @status Stub.
558 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
559 * @remark
560 */
561BOOL kFileLX::expandPage2(char *pachPage, const char * pachSrcPage, int cchSrcPage)
562{
563 NOREF(pachPage);
564 NOREF(pachSrcPage);
565 NOREF(cchSrcPage);
566 return FALSE;
567}
568
569
570/**
571 * Compresses a page using the old exepack method introduced with OS/2 2.0.
572 * (/EXEPACK:1 or just /EXEPACK)
573 * @returns Size of the compressed page in the pachPage buffer.
574 * PAGESIZE if failed to compress the page.
575 * -1 on error.
576 * @param pachPage Pointer to output buffer. size: PAGESIZE.
577 * This will hold the compressed page data upon return.
578 * @param pachSrcPage Pointer to page to compress. size: PAGESIZE.
579 * @sketch
580 * @status stub.
581 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
582 * @remark Not implemented.
583 */
584int kFileLX::compressPage1(char *pachPage, const char * pachSrcPage)
585{
586 NOREF(pachPage);
587 NOREF(pachSrcPage);
588 return -1;
589}
590
591
592/**
593 * Compresses a page using the exepack method introduced with OS/2 Warp 3.0.
594 * (/EXEPACK:2)
595 * @returns Size of the compressed page in the pachPage buffer.
596 * PAGESIZE if failed to compress the page.
597 * -1 on error.
598 * @param pachPage Pointer to output buffer. size: PAGESIZE.
599 * This will hold the compressed page data upon return.
600 * @param pachSrcPage Pointer to page to compress. size: PAGESIZE.
601 * @sketch Have no idea!
602 * @status stub.
603 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
604 * @remark Not implemented.
605 */
606int kFileLX::compressPage2(char *pachPage, const char * pachSrcPage)
607{
608 NOREF(pachPage);
609 NOREF(pachSrcPage);
610 return -1;
611}
612
613#endif
Note: See TracBrowser for help on using the repository browser.