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

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

Fixes and enhancements.

File size: 10.6 KB
Line 
1/* $Id: kFileLX.cpp,v 1.2 2000-08-31 03:00:13 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 "kFileLX.h"
50
51/*******************************************************************************
52* Structures and Typedefs *
53*******************************************************************************/
54typedef struct _export_state
55{
56 struct b32_bundle * pb32; /* Pointer to current bundle. */
57 int iOrdinalBundle; /* The ordinal the bundle starts at. */
58 struct e32_entry * pe32; /* Pointer to the current bundle entry. */
59 int iOrdinal; /* The current ordinal. */
60} EXPSTATE, *PEXPSTATE;
61
62
63
64BOOL kFileLX::queryExportName(int iOrdinal, char *pszBuffer)
65{
66 PUSHORT pus;
67 PUCHAR puch;
68
69 /* resident name table */
70 if (pe32->e32_restab)
71 {
72 puch = (PUCHAR)pvBase + offLXHdr + pe32->e32_restab;
73 while (*puch != 0)
74 {
75 pus = (PUSHORT)(puch + 1 + *puch);
76 if (*pus == iOrdinal)
77 {
78 memcpy(pszBuffer, puch + 1, *puch);
79 pszBuffer[*puch] = '\0';
80 return TRUE;
81 }
82 puch += *puch + 1 + 2;
83 }
84 }
85
86 /* not found, check the non-resident name table too */
87 if (pe32->e32_nrestab)
88 {
89 puch = (PUCHAR)pvBase + pe32->e32_nrestab;
90 while (*puch != 0)
91 {
92 pus = (PUSHORT)(puch + 1 + *puch);
93 if (*pus == iOrdinal)
94 {
95 memcpy(pszBuffer, puch + 1, *puch);
96 pszBuffer[*puch] = '\0';
97 return TRUE;
98 }
99 puch += *puch + 1 + 2;
100 }
101 }
102
103 return FALSE;
104}
105
106
107
108/**
109 * Create an LX file object from an LX executable image.
110 * @param pszFilename LX executable image name.
111 */
112kFileLX::kFileLX(const char *pszFilename)
113: pvBase(NULL)
114{
115 struct exe_hdr * pehdr;
116
117 /* create filemapping */
118 pvBase = kFileFormatBase::readfile(pszFilename);
119 if (pvBase == NULL)
120 throw(1);
121
122 pehdr = (struct exe_hdr*)pvBase;
123 if (pehdr->e_magic == EMAGIC)
124 offLXHdr = pehdr->e_lfanew;
125 else
126 offLXHdr = 0;
127
128 pe32 = (struct e32_exe*)((char*)pvBase + offLXHdr);
129 if (*(PUSHORT)pe32 == E32MAGIC)
130 {
131 paObject = (struct o32_obj*)((char*)pvBase + pe32->e32_objtab + offLXHdr);
132 }
133 else
134 {
135 free(pvBase);
136 pvBase = NULL;
137 throw(2);
138 }
139}
140
141
142
143/**
144 * Destructor.
145 */
146kFileLX::~kFileLX()
147{
148 if (pvBase != NULL)
149 free(pvBase);
150 pvBase = NULL;
151}
152
153
154
155BOOL kFileLX::queryModuleName(char *pszBuffer)
156{
157 /* The module name is the 0 ordinal entry in resident name table */
158 return queryExportName(0, pszBuffer);
159}
160
161
162
163BOOL kFileLX::findFirstExport(PEXPORTENTRY pExport)
164{
165 struct b32_bundle * pBundle = (struct b32_bundle*)((char*)pvBase + pe32->e32_enttab + offLXHdr);
166 struct e32_entry * pEntry;
167 int iOrdinal = 1;
168
169 if (pe32->e32_enttab)
170 {
171 while (pBundle->b32_cnt != 0)
172 {
173 /* skip empty bundles */
174 while (pBundle->b32_cnt != 0 && pBundle->b32_type == EMPTY)
175 {
176 iOrdinal += pBundle->b32_cnt;
177 pBundle = (struct b32_bundle*)((char*)pBundle + 2);
178 }
179
180 /* FIXME forwarders are not implemented so we'll skip them too. */
181 while (pBundle->b32_cnt != 0 && (pBundle->b32_type & ~TYPEINFO) == ENTRYFWD)
182 {
183 iOrdinal += pBundle->b32_cnt;
184 pBundle = (struct b32_bundle*)((char*)(pBundle + 1) + pBundle->b32_cnt * 7);
185 }
186
187 /* we'll ignore any flags for the moment - TODO */
188 if (pBundle->b32_cnt != 0)
189 {
190 pExport->ulOrdinal = iOrdinal;
191 pExport->iObject = pBundle->b32_obj;
192
193 /* look for name */
194 pExport->achIntName[0] = '\0';
195 if (!queryExportName(iOrdinal, pExport->achName))
196 pExport->achName[0] = '\0';
197
198 pEntry = (struct e32_entry*)(pBundle+1);
199 switch (pBundle->b32_type & ~TYPEINFO)
200 {
201 case ENTRY16:
202 pExport->offset = pEntry->e32_variant.e32_offset.offset16;
203 break;
204
205 case ENTRY32:
206 pExport->offset = pEntry->e32_variant.e32_offset.offset32;
207 break;
208
209 case GATE16:
210 pExport->offset = pEntry->e32_variant.e32_callgate.offset;
211 break;
212 default:
213 assert(!"ARG!!!! invalid bundle type!");
214 }
215
216 /* store status - current export entry */
217 PEXPSTATE pExpState = (PEXPSTATE)malloc(sizeof(EXPSTATE));
218 pExport->pv = pExpState;
219 pExpState->pb32 = pBundle;
220 pExpState->iOrdinalBundle = iOrdinal;
221 pExpState->pe32 = pEntry;
222 pExpState->iOrdinal = iOrdinal;
223 return TRUE;
224 }
225 }
226
227 }
228
229 return FALSE;
230}
231
232
233
234BOOL kFileLX::findNextExport(PEXPORTENTRY pExport)
235{
236 static int acbEntry[] =
237 {
238 0, /* EMPTY */
239 3, /* ENTRY16 */
240 5, /* GATE16 */
241 5, /* ENTRY32 */
242 7 /* ENTRYFWD */
243 };
244
245 PEXPSTATE pExpState = (PEXPSTATE)pExport->pv;
246
247 /*
248 * Get more ordinals from the current bundle if any left.
249 */
250 if (pExpState->pb32->b32_cnt > (pExpState->iOrdinal - pExpState->iOrdinalBundle + 1))
251 {
252 /* skip to the next entry */
253 pExpState->iOrdinal++;
254 pExpState->pe32 = (struct e32_entry*)((char*)pExpState->pe32
255 + acbEntry[pExpState->pb32->b32_type & ~TYPEINFO]);
256
257 /* fill output struct */
258 pExport->ulOrdinal = pExpState->iOrdinal;
259 pExport->iObject = pExpState->pb32->b32_obj;
260
261 /* look for name */
262 pExport->achIntName[0] = '\0';
263 if (!queryExportName(pExpState->iOrdinal, pExport->achName))
264 pExport->achName[0] = '\0';
265
266 /* offset */
267 switch (pExpState->pb32->b32_type & ~TYPEINFO)
268 {
269 case ENTRY16:
270 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset16;
271 break;
272
273 case ENTRY32:
274 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset32;
275 break;
276
277 case GATE16:
278 pExport->offset = pExpState->pe32->e32_variant.e32_callgate.offset;
279 break;
280 }
281
282 return TRUE;
283 }
284
285 /*
286 * next bundle.
287 */
288 pExpState->pb32 = (struct b32_bundle*)((char*)(pExpState->pb32 + 1) +
289 pExpState->pb32->b32_cnt * acbEntry[pExpState->pb32->b32_type & ~TYPEINFO]);
290 while (pExpState->pb32->b32_cnt != 0)
291 {
292 /* skip empty bundles */
293 while (pExpState->pb32->b32_cnt != 0 && pExpState->pb32->b32_type == EMPTY)
294 {
295 pExpState->iOrdinal += pExpState->pb32->b32_cnt;
296 pExpState->pb32 = (struct b32_bundle*)((char*)pExpState->pb32 + 2);
297 }
298
299 /* FIXME forwarders are not implemented so we'll skip them too. */
300 while (pExpState->pb32->b32_cnt != 0 && (pExpState->pb32->b32_type & ~TYPEINFO) == ENTRYFWD)
301 {
302 pExpState->iOrdinal += pExpState->pb32->b32_cnt;
303 pExpState->pb32 = (struct b32_bundle*)((char*)(pExpState->pb32 + 1) + pExpState->pb32->b32_cnt * 7);
304 }
305
306 /* we'll ignore any flags for the moment - TODO */
307 if (pExpState->pb32->b32_cnt != 0)
308 {
309 pExpState->iOrdinalBundle = pExpState->iOrdinal;
310
311 pExport->ulOrdinal = pExpState->iOrdinal;
312 pExport->iObject = pExpState->pb32->b32_obj;
313
314 /* look for name */
315 pExport->achIntName[0] = '\0';
316 if (!queryExportName(pExpState->iOrdinal, pExport->achName))
317 pExport->achName[0] = '\0';
318
319 pExpState->pe32 = (struct e32_entry*)(pExpState->pb32+1);
320 switch (pExpState->pb32->b32_type & ~TYPEINFO)
321 {
322 case ENTRY16:
323 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset16;
324 break;
325
326 case ENTRY32:
327 pExport->offset = pExpState->pe32->e32_variant.e32_offset.offset32;
328 break;
329
330 case GATE16:
331 pExport->offset = pExpState->pe32->e32_variant.e32_callgate.offset;
332 break;
333 default:
334 assert(!"ARG!!!! invalid bundle type!");
335 }
336
337 return TRUE;
338 }
339 }
340
341
342 /*
343 * No more exports - clean up
344 */
345 free(pExport->pv);
346 pExport->pv = NULL;
347 return FALSE;
348}
349
350
351/**
352 * Gets a specific LX object.
353 * @returns Pointer to object. NULL on error / invalid index.
354 * @param iObject object number (0-based)
355 */
356struct o32_obj * kFileLX::getObject(int iObject)
357{
358
359 if (iObject < pe32->e32_objcnt)
360 return &paObject[iObject];
361 return NULL;
362}
363
364
365/**
366 * Gets the count of LX objects.
367 * @returns Count of LX objects.
368 */
369int kFileLX::getObjectCount()
370{
371 return (int)pe32->e32_objcnt;
372}
373
Note: See TracBrowser for help on using the repository browser.