source: trunk/src/kernel32/winimagepe2lx.cpp@ 4097

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

Temporary Resource section fix.
Added getSectionIndexFromRVA.

File size: 26.8 KB
Line 
1/* $Id: winimagepe2lx.cpp,v 1.13 2000-08-27 03:20:37 bird Exp $ */
2
3/*
4 * Win32 PE2LX Image base class
5 *
6 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1998-1999 knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13/*******************************************************************************
14* Defined Constants And Macros *
15*******************************************************************************/
16#define INCL_DOSERRORS /* DOS Error values */
17#define INCL_DOSPROFILE /* DosQuerySysState (Toolkit 4.5) */
18#define INCL_DOSMODULEMGR /* DOS Module management */
19
20#define ALIGN(a, alignment) (((a) + (alignment - 1UL)) & ~(alignment - 1UL))
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#include <os2wrap.h> //Odin32 OS/2 api wrappers
27
28#include <malloc.h>
29#include <process.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include <win32type.h>
34#include <misc.h>
35#include <winimagebase.h>
36#include <winimagepe2lx.h>
37
38#define DBG_LOCALLOG DBG_winimagepe2lx
39#include "dbglocal.h"
40
41/*******************************************************************************
42* Structures and Typedefs *
43*******************************************************************************/
44#ifndef QS_MTE
45 /* From OS/2 Toolkit v4.5 (BSEDOS.H) */
46
47 /* Global Record structure
48 * Holds all global system information. Placed first in user buffer
49 */
50 typedef struct qsGrec_s { /* qsGrec */
51 ULONG cThrds;
52 ULONG c32SSem;
53 ULONG cMFTNodes;
54 }qsGrec_t;
55
56 /*
57 * System wide MTE information
58 * ________________________________
59 * | pNextRec |----|
60 * |-------------------------------| |
61 * | hmte | |
62 * |-------------------------------| |
63 * | ctImpMod | |
64 * |-------------------------------| |
65 * | ctObj | |
66 * |-------------------------------| |
67 * | pObjInfo |----|----------|
68 * |-------------------------------| | |
69 * | pName |----|----| |
70 * |-------------------------------| | | |
71 * | imported module handles | | | |
72 * | . | | | |
73 * | . | | | |
74 * | . | | | |
75 * |-------------------------------| <--|----| |
76 * | "pathname" | | |
77 * |-------------------------------| <--|----------|
78 * | Object records | |
79 * | (if requested) | |
80 * |_______________________________| |
81 * <-----
82 * NOTE that if the level bit is set to QS_MTE, the base Lib record will be followed
83 * by a series of object records (qsLObj_t); one for each object of the
84 * module.
85 */
86
87 typedef struct qsLObjrec_s { /* qsLOrec */
88 ULONG oaddr; /* object address */
89 ULONG osize; /* object size */
90 ULONG oflags; /* object flags */
91 } qsLObjrec_t;
92
93 typedef struct qsLrec_s { /* qsLrec */
94 void FAR *pNextRec; /* pointer to next record in buffer */
95 USHORT hmte; /* handle for this mte */
96 USHORT fFlat; /* true if 32 bit module */
97 ULONG ctImpMod; /* # of imported modules in table */
98 ULONG ctObj; /* # of objects in module (mte_objcnt)*/
99 qsLObjrec_t FAR *pObjInfo; /* pointer to per object info if any */
100 UCHAR FAR *pName; /* -> name string following struc */
101 } qsLrec_t;
102
103
104
105 /* Pointer Record Structure
106 * This structure is the first in the user buffer.
107 * It contains pointers to heads of record types that are loaded
108 * into the buffer.
109 */
110
111 typedef struct qsPtrRec_s { /* qsPRec */
112 qsGrec_t *pGlobalRec;
113 void *pProcRec; /* ptr to head of process records */
114 void *p16SemRec; /* ptr to head of 16 bit sem recds */
115 void *p32SemRec; /* ptr to head of 32 bit sem recds */
116 void *pMemRec; /* ptr to head of shared mem recs */
117 qsLrec_t *pLibRec; /* ptr to head of mte records */
118 void *pShrMemRec; /* ptr to head of shared mem records */
119 void *pFSRec; /* ptr to head of file sys records */
120 } qsPtrRec_t;
121
122#endif
123
124
125/*******************************************************************************
126* External Functions *
127*******************************************************************************/
128#ifndef QS_MTE
129 /* from OS/2 Toolkit v4.5 */
130
131 APIRET APIENTRY DosQuerySysState(ULONG EntityList, ULONG EntityLevel, PID pid,
132 TID tid, PVOID pDataBuf, ULONG cbBuf);
133 #define QS_MTE 0x0004
134#endif
135
136
137
138/**
139 * Constructor - creates an pe2lx image object from a module handle to a pe2lx module.
140 * @param hinstance OS/2 module handle.
141 * @param fWin32k TRUE: Win32k module.
142 * FALSE: Pe2Lx module.
143 * @status partially implemented.
144 * @author knut st. osmundsen, Sander van Leeuwen
145 */
146Win32Pe2LxImage::Win32Pe2LxImage(HINSTANCE hinstance, BOOL fWin32k)
147 : Win32ImageBase(hinstance),
148 paSections(NULL), cSections(0), pNtHdrs(NULL), fWin32k(fWin32k)
149{
150 setFullPath(szFileName);
151}
152
153
154/**
155 * Free memory associated with this object.
156 * @status completely implemented.
157 * @author knut st. osmundsen, Sander van Leeuwen
158 */
159Win32Pe2LxImage::~Win32Pe2LxImage()
160{
161 cleanup();
162}
163
164
165/**
166 * Initiates the object.
167 * Must be called immediately after the object construction.
168 * @returns Success indicator, TRUE == success; FALSE = failure.
169 * @sketch Get section placement and sizes for this module. (paSections, cSections)
170 * Verify that there is at least one section - the header section.
171 * Locate the NT headers.
172 * Set pNtHdrs pointer.
173 * Validate the NT headers.
174 * Read the PE section table the set the RVAs in paSections.
175 * Locate and set the entrypoint.
176 * Locate the resource directory (if any). (pResRootDir, ulRVAResourceSection)
177 * TLS - FIXME!
178 * @status completely implemented.
179 * @author knut st. osmundsen
180 * @remark Object must be destroyed if failure!
181 */
182BOOL Win32Pe2LxImage::init()
183{
184 APIRET rc;
185
186 /* Get section placement and sizes for this module. (paSections, cSections) */
187 rc = getSections();
188 if (rc != NO_ERROR)
189 {
190 dprintf(("Win32Pe2LxImage::Win32Pe2LxImage: error - getSection failed with rc=%d\n",
191 rc));
192 return FALSE;
193 }
194
195 /* Verify that there is at least one section - the header section. */
196 if (cSections < 1)
197 {
198 dprintf(("Win32Pe2LxImage::Win32Pe2LxImage: no header section, cSections is 0\n"));
199 return FALSE;
200 }
201
202 /* Locate the NT headers. */
203 PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)paSections[0].ulAddress;
204 if ((pDosHdr->e_magic != IMAGE_DOS_SIGNATURE
205 || pDosHdr->e_lfanew < sizeof(IMAGE_DOS_HEADER) /* Larger than 64 bytes */
206 || pDosHdr->e_lfanew > 0x04000000UL /* or less that 64MB. */
207 )
208 && !*(PDWORD)paSections[0].ulAddress == IMAGE_NT_SIGNATURE
209 )
210 {
211 dprintf(("Win32Pe2LxImage::Win32Pe2LxImage: Not a pe2lx image!(?)\n"));
212 return FALSE;
213 }
214
215 /* Set pNtHdrs pointer. */
216 if (pDosHdr->e_magic == IMAGE_DOS_SIGNATURE)
217 pNtHdrs = (PIMAGE_NT_HEADERS)(paSections[0].ulAddress + pDosHdr->e_lfanew);
218 else
219 pNtHdrs = (PIMAGE_NT_HEADERS)paSections[0].ulAddress;
220
221 /* Validate the NT headers. */
222 if (pNtHdrs->Signature != IMAGE_NT_SIGNATURE
223 || pNtHdrs->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC
224 || pNtHdrs->FileHeader.Machine != IMAGE_FILE_MACHINE_I386
225 || (cSections != 1 /* all in one object */
226 && pNtHdrs->FileHeader.NumberOfSections
227 > cSections - 1 - (pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL ? 0 : 1) /* hdr section and stack */
228 )
229 /* TODO: add more tests? */
230 )
231 {
232 dprintf(("Win32Pe2LxImage::Win32Pe2LxImage: Not a pe2lx image!(?)\n"));
233 return FALSE;
234 }
235
236 /* set RVAs */
237 rc = setSectionRVAs();
238 if (rc != NO_ERROR)
239 {
240 dprintf(("Win32Pe2LxImage::Win32Pe2LxImage: setSectionRVAs failed with rc=%d\n", rc));
241 return FALSE;
242 }
243
244 /* Locate and set the entrypoint. */
245 setEntryPoint((ULONG)getPointerFromRVA(pNtHdrs->OptionalHeader.AddressOfEntryPoint));
246 if (entryPoint == 0UL &&
247 (pNtHdrs->OptionalHeader.AddressOfEntryPoint != NULL /* getPointerFromRVA failed... */
248 || !(pNtHdrs->FileHeader.Characteristics & IMAGE_FILE_DLL)) /* EXEs must have and entry point! */
249 )
250 {
251 dprintf(("Win32Pe2LxImage::Win32Pe2LxImage: entrypoint is incorrect, AddrOfEP=0x%08x, entryPoint=0x%08x\n",
252 pNtHdrs->OptionalHeader.AddressOfEntryPoint, entryPoint));
253 return FALSE;
254 }
255
256 /* Locate the resource directory (if any) */
257 if (pNtHdrs->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE
258 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress > 0UL)
259 {
260 ulRVAResourceSection = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
261 pResRootDir = (PIMAGE_RESOURCE_DIRECTORY)getPointerFromRVA(ulRVAResourceSection);
262 /* _temporary_ fix:
263 * We'll have to make the resource section writable.
264 * And we'll have to make the pages before it readable.
265 */
266 ULONG iSection = getSectionIndexFromRVA(ulRVAResourceSection);
267 if (iSection >= 0)
268 {
269 rc = DosSetMem((PVOID)paSections[iSection].ulAddress, paSections[iSection].cbVirtual, PAG_WRITE | PAG_READ);
270
271 ULONG ulAddr = paSections[iSection].ulAddress - 0x10000; //64KB
272 while (ulAddr < paSections[iSection].ulAddress)
273 {
274 ULONG fl = ~0UL;
275 ULONG cb = ~0UL;
276 rc = DosQueryMem((PVOID)ulAddr, &cb, &fl);
277 if (rc == NO_ERROR)
278 {
279 if (fl & PAG_GUARD)
280 rc = -1;
281 else if (fl & PAG_COMMIT)
282 fl &= ~(PAG_COMMIT);
283 else
284 fl |= PAG_COMMIT;
285 cb = (cb + 0xfffUL) & ~0xfffUL;
286 }
287 else
288 {
289 fl = PAG_COMMIT;
290 cb = 0x1000;
291 }
292 fl &= PAG_READ | PAG_COMMIT | PAG_WRITE | PAG_GUARD;
293 fl |= PAG_READ;
294 if (cb > paSections[iSection].ulAddress - ulAddr)
295 cb = paSections[iSection].ulAddress - ulAddr;
296 if (rc == NO_ERROR)
297 rc = DosSetMem((PVOID)ulAddr, cb, fl);
298
299 ulAddr += cb;
300 }
301 }
302 }
303
304 /* TLS - Thread Local Storage */
305 if (pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0UL
306 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size != 0UL)
307 {
308 PIMAGE_TLS_DIRECTORY pTLSDir;
309 pTLSDir = (PIMAGE_TLS_DIRECTORY)getPointerFromRVA(pNtHdrs->OptionalHeader.
310 DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].
311 VirtualAddress);
312
313 if (pTLSDir != NULL)
314 {
315 PVOID pv;
316 ULONG ulBorlandRVAFix = 0UL;
317
318 pv = getPointerFromRVA(pTLSDir->StartAddressOfRawData);
319 /*
320 * Borland seems to have problems getting things right...
321 * Needs to subtract image base to make the TLSDir "RVA"s real
322 * RVAs before converting them to pointers.
323 */
324 if ((pv == NULL || pTLSDir->StartAddressOfRawData == 0UL)
325 && pTLSDir->StartAddressOfRawData > this->pNtHdrs->OptionalHeader.ImageBase)
326 {
327 ulBorlandRVAFix = this->pNtHdrs->OptionalHeader.ImageBase;
328 pv = getPointerFromRVA(pTLSDir->StartAddressOfRawData - ulBorlandRVAFix);
329 }
330 if (pv == NULL || pTLSDir->StartAddressOfRawData == 0UL)
331 {
332 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS StartAddressOfRawData - %#8x.\n",
333 pTLSDir->StartAddressOfRawData));
334 return FALSE;
335 }
336 setTLSAddress(pv);
337 setTLSInitSize(pTLSDir->EndAddressOfRawData - pTLSDir->StartAddressOfRawData);
338 setTLSTotalSize(pTLSDir->EndAddressOfRawData - pTLSDir->StartAddressOfRawData + pTLSDir->SizeOfZeroFill);
339 pv = getPointerFromRVA((ULONG)pTLSDir->AddressOfIndex - ulBorlandRVAFix);
340 if (pv == NULL)
341 {
342 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS AddressOffIndex - %#8x.\n",
343 pTLSDir->AddressOfIndex));
344 return FALSE;
345 }
346 setTLSIndexAddr((LPDWORD)pv);
347 if (pTLSDir->AddressOfCallBacks != 0)
348 {
349 pv = getPointerFromRVA((ULONG)pTLSDir->AddressOfCallBacks - ulBorlandRVAFix);
350 if (pv == NULL)
351 {
352 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS AddressOffIndex - %#8x.\n",
353 pTLSDir->AddressOfIndex));
354 return FALSE;
355 }
356 setTLSCallBackAddr((PIMAGE_TLS_CALLBACK*)pv);
357 }
358 }
359 else
360 {
361 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS Dir - %#8x. (getPointerFromRVA failed)\n",
362 pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress));
363 return FALSE;
364 }
365 }
366 return TRUE;
367}
368
369
370
371/**
372 * Gets the object layout for this module. Creates the paSections array.
373 * @returns OS2 errorcode. (NO_ERROR == success)
374 * @sketch Allocate output buffer.
375 * Call DosQuerySysState.
376 * IF buffer overflow THEN retry calling it with larger buffers, until buffer size is 1MB.
377 * IF success THEN
378 * BEGIN
379 * Find record for this module.
380 * IF record found THEN allocate memory for object table and copy it. (paSections, cSections)
381 * END
382 * @status Completely implemented.
383 * @author knut st. osmundsen
384 */
385ULONG Win32Pe2LxImage::getSections()
386{
387 APIRET rc = NO_ERROR;
388 qsPtrRec_t * pPtrRec;
389 ULONG cbBuf = 65536;
390
391 pPtrRec = (qsPtrRec_t *)malloc(cbBuf);
392 if (pPtrRec != NULL)
393 {
394 rc = DosQuerySysState(QS_MTE, QS_MTE, getpid(), 0L, pPtrRec, cbBuf);
395 while (cbBuf < 1024*1024 && rc == ERROR_BUFFER_OVERFLOW)
396 {
397 PVOID pv = pPtrRec;
398 cbBuf += 65536;
399 pPtrRec = (qsPtrRec_t *)realloc(pv, cbBuf);
400 if (pPtrRec != NULL)
401 rc = DosQuerySysState(QS_MTE, QS_MTE, getpid(), 0L, pPtrRec, cbBuf);
402 else
403 {
404 rc = ERROR_NOT_ENOUGH_MEMORY;
405 free(pv);
406 }
407 }
408
409 if (rc == NO_ERROR)
410 {
411 qsLrec_t * pLrec = pPtrRec->pLibRec;
412 while (pLrec != NULL)
413 {
414 /*
415 * Bug detected in OS/2 FP13. Probably a problem which occurs
416 * in _LDRSysMteInfo when qsCheckCache is calle before writing
417 * object info. The result is that the cache flushed and the
418 * attempt of updating the qsLrec_t next and object pointer is
419 * not done. This used to work earlier and on Aurora AFAIK.
420 *
421 * The fix for this problem is to check if the pObjInfo is NULL
422 * while the number of objects isn't 0 and correct this. pNextRec
423 * will also be NULL at this time. This will be have to corrected
424 * before we exit the loop or moves to the next record.
425 * There is also a nasty alignment of the object info... Hope
426 * I got it right. (This aligment seems new to FP13.)
427 */
428 if (pLrec->pObjInfo == NULL /*&& pLrec->pNextRec == NULL*/ && pLrec->ctObj > 0)
429 {
430 pLrec->pObjInfo = (qsLObjrec_t*)(
431 (char*)pLrec
432 + ((sizeof(qsLrec_t) /* size of the lib record */
433 + pLrec->ctImpMod * sizeof(short) /* size of the array of imported modules */
434 + strlen((char*)pLrec->pName) + 1 /* size of the filename */
435 + 3) & ~3)); /* the size is align on 4 bytes boundrary */
436 pLrec->pNextRec = (qsLrec_t*)((char*)pLrec->pObjInfo
437 + sizeof(qsLObjrec_t) * pLrec->ctObj);
438 }
439 if (pLrec->hmte == hinstance)
440 break;
441
442 /*
443 * Next record
444 */
445 pLrec = (qsLrec_t*)pLrec->pNextRec;
446 }
447
448
449 if (pLrec)
450 {
451 if (pLrec->pObjInfo != NULL)
452 {
453 /* Allocate memory for paSections */
454 paSections = (PSECTION)malloc(pLrec->ctObj*sizeof(SECTION));
455 if (paSections != NULL)
456 {
457 /* objects -> section array */
458 for (int i = 0; i < pLrec->ctObj; i++)
459 {
460 paSections[i].ulRVA = ~0UL;
461 paSections[i].cbVirtual = pLrec->pObjInfo[i].osize;
462 paSections[i].ulAddress = pLrec->pObjInfo[i].oaddr;
463 }
464 cSections = pLrec->ctObj;
465 }
466 else
467 rc = ERROR_NOT_ENOUGH_MEMORY;
468 }
469 else
470 {
471 rc = ERROR_BAD_EXE_FORMAT;
472 dprintf(("Win32Pe2LxImage::getSections: Error - no object table!\n"));
473 }
474 }
475 else
476 rc = ERROR_MOD_NOT_FOUND;
477 }
478 else
479 dprintf(("DosQuerySysState - failed with rc=%d (cbBuf=%d)\n", rc, cbBuf));
480
481 if (pPtrRec != NULL)
482 free(pPtrRec);
483 }
484 else
485 rc = ERROR_NOT_ENOUGH_MEMORY;
486
487 return rc;
488}
489
490
491/**
492 * Sets the ulRVA according to the original PE section table.
493 * @returns OS/2 errorcode. (NO_ERROR == success)
494 * @sketch DEBUG: Validate pNtHdrs
495 * Make pointer to start of PE section table.
496 * Set RVA for the header section.
497 * IF not all in one object exe? THEN
498 * Loop thru the sections in the PE section table.
499 * Note: due to the header section: PE section no. + 1 == LX object no.
500 * ELSE
501 * BEGIN
502 * (try) Reallocate paSections to NumberOfSections + 3.
503 * Loop thru the PE sections and make paSections from them.
504 * Add final Stack or TIBFix+Stack section if necessary.
505 * Resize header section.
506 * END
507 * @status completely implemented.
508 * @author knut st. osmundsen
509 * @remark Must not be called before pNtHdrs is set.
510 */
511ULONG Win32Pe2LxImage::setSectionRVAs()
512{
513 #if DEBUG
514 if (pNtHdrs == NULL)
515 {
516 DebugInt3();
517 return ERROR_INVALID_PARAMETER;
518 }
519 #endif
520
521 PIMAGE_SECTION_HEADER paPESections = (PIMAGE_SECTION_HEADER)
522 ((unsigned)pNtHdrs + sizeof(*pNtHdrs) +
523 (pNtHdrs->OptionalHeader.NumberOfRvaAndSizes - IMAGE_NUMBEROF_DIRECTORY_ENTRIES) * sizeof(IMAGE_DATA_DIRECTORY)
524 );
525
526 /* set RVA for the header section to 0UL. */
527 paSections[0].ulRVA = 0UL;
528
529 /* All in one object exe? */
530 if (pNtHdrs->FileHeader.NumberOfSections < cSections)
531 {
532 /* loop thru the other sections */
533 for (int i = 0; i < pNtHdrs->FileHeader.NumberOfSections; i++)
534 paSections[i+1].ulRVA = paPESections[i].VirtualAddress;
535 }
536 else
537 { /* all in one object */
538 /* (try) Reallocate paSections to NumberOfSections + 3. */
539 PVOID pv = realloc(paSections, sizeof(paSections[0]) * (pNtHdrs->FileHeader.NumberOfSections + 3));
540 if (pv != NULL)
541 {
542 paSections = (PSECTION)pv;
543
544 /* loop thru the PE sections */
545 for (int i = 0; i < pNtHdrs->FileHeader.NumberOfSections; i++)
546 {
547 if (paSections[0].cbVirtual < paPESections[i].VirtualAddress)
548 {
549 dprintf(("Win32Pe2LxImage::setSectionRVAs: mismatch between section table and all-in-one-object"
550 "paSections[0].cbVirtual %#x paPESections[i].VirtualAddress %#x\n",
551 paSections[0].cbVirtual, paPESections[i].VirtualAddress
552 ));
553 return ERROR_BAD_EXE_FORMAT;
554 }
555 paSections[i+1].ulRVA = paPESections[i].VirtualAddress;
556 paSections[i+1].cbVirtual = max(paPESections[i].Misc.VirtualSize, paPESections[i].SizeOfRawData);
557 paSections[i+1].ulAddress = paSections[0].ulAddress + paPESections[i].VirtualAddress;
558 }
559 cSections = pNtHdrs->FileHeader.NumberOfSections + 1;
560
561 /* add final Stack or TIBFix+Stack section if necessary */
562 if (paSections[0].cbVirtual > paSections[i].ulRVA + ALIGN(paSections[i].cbVirtual, 0x1000))
563 {
564 paSections[i+1].ulRVA = ~0UL;
565 paSections[i+1].cbVirtual = paSections[0].cbVirtual - paSections[i].ulRVA + ALIGN(paSections[i].cbVirtual, 0x1000);
566 paSections[i+1].ulAddress = paSections[i].ulAddress + ALIGN(paSections[i].cbVirtual, 0x1000);
567 i++;
568 cSections++;
569 }
570
571 /* resize header section */
572 paSections[0].cbVirtual = paSections[1].ulRVA; /*....*/
573 }
574 else
575 return ERROR_NOT_ENOUGH_MEMORY;
576 }
577
578 return NO_ERROR;
579}
580
581
582/**
583 * Frees memory used by this object.
584 * When an exception is to be thrown, this function is called first to clean up
585 * the object. Base class(es) are automatically clean up by theire destructor(s).
586 * @status completely implemented.
587 * @author knut st. osmundsen
588 */
589VOID Win32Pe2LxImage::cleanup()
590{
591 if (paSections != NULL)
592 {
593 free(paSections);
594 paSections = NULL;
595 cSections = 0;
596 }
597}
598
599
600/**
601 * Converts a RVA into a pointer.
602 * @returns Pointer matching the given RVA, NULL on error.
603 * @param ulRVA An address relative to the imagebase of the original PE image.
604 * If this is 0UL NULL is returned.
605 * @sketch DEBUG: validate state, paSections != NULL
606 * IF ulRVA is 0 THEN return NULL
607 * LOOP while more section left and ulRVA is not within section
608 * next section
609 * IF section matching ulRVA is not found THEN fail.
610 * return pointer matching RVA.
611 * @status completely implemented.
612 * @author knut st. osmundsen
613 * @remark Should not be called until getSections has returned successfully.
614 * RVA == 0 is ignored.
615 */
616PVOID Win32Pe2LxImage::getPointerFromRVA(ULONG ulRVA)
617{
618 int i;
619 #ifdef DEBUG
620 if (paSections == NULL)
621 return NULL;
622 #endif
623
624 if (ulRVA == 0UL)
625 return NULL;
626
627 i = 0;
628 while (i < cSections &&
629 !(paSections[i].ulRVA <= ulRVA && paSections[i].ulRVA + paSections[i].cbVirtual > ulRVA)) /* ALIGN on page too? */
630 i++;
631
632 if (i >= cSections)
633 return NULL;
634
635 return (PVOID)(ulRVA - paSections[i].ulRVA + paSections[i].ulAddress);
636}
637
638
639/**
640 * Converts a RVA into a paSections index.
641 * @returns Index into paSections for the section containing the RVA.
642 * -1 on error.
643 * @param ulRVA An address relative to the imagebase of the original PE image.
644 * If this is 0UL -1 is returned.
645 * @sketch DEBUG: validate state, paSections != NULL
646 * IF ulRVA is 0 THEN return -1
647 * LOOP while more section left and ulRVA is not within section
648 * next section
649 * IF section matching ulRVA is found THEN return index ELSE fail.
650 * @status completely implemented.
651 * @author knut st. osmundsen
652 * @remark Should not be called until getSections has returned successfully.
653 * RVA == 0 is ignored.
654 */
655ULONG Win32Pe2LxImage::getSectionIndexFromRVA(ULONG ulRVA)
656{
657 int i;
658 #ifdef DEBUG
659 if (paSections == NULL)
660 return -1;
661 #endif
662
663 if (ulRVA == 0UL)
664 return -1;
665
666 i = 0;
667 while (i < cSections &&
668 !(paSections[i].ulRVA <= ulRVA && paSections[i].ulRVA + paSections[i].cbVirtual > ulRVA)) /* ALIGN on page too? */
669 i++;
670
671 return i < cSections ? i : -1;
672}
673
674
675/**
676 * Gets pointer to an exported procedure by procedure name.
677 * @returns Address of exported procedure. 0UL if not found.
678 * @param name Exported procedure name.
679 * @status completely implemented.
680 * @author Sander van Leeuwen
681 * @remark
682 */
683ULONG Win32Pe2LxImage::getApi(char *name)
684{
685 APIRET rc;
686 ULONG ulApiAddr;
687
688 rc = DosQueryProcAddr(hinstance, 0, name, (PFN *)&ulApiAddr);
689 return rc == NO_ERROR ? ulApiAddr : 0;
690}
691
692
693/**
694 * Gets pointer to an exported procedure by ordinal.
695 * @returns Pointer to an exported procedure. 0UL if not found.
696 * @param ordinal Export ordinal number.
697 * @status completely implemented.
698 * @author Sander van Leeuwen
699 * @remark FIXME:
700 * This function should be implemented for both Exe and Dll images!
701 * It could be done similar in both peldr image and pe2lx images by
702 * accessing PE structures.
703 */
704ULONG Win32Pe2LxImage::getApi(int ordinal)
705{
706 APIRET rc;
707 ULONG ulApiAddr;
708
709 rc = DosQueryProcAddr(hinstance, ordinal, NULL, (PFN *)&ulApiAddr);
710
711 return rc == NO_ERROR ? ulApiAddr : 0;
712}
Note: See TracBrowser for help on using the repository browser.