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

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

Tempfix which makes the resource section writeable and commits the 64KB
preceding the resource section commited and readable.

File size: 26.2 KB
Line 
1/* $Id: winimagepe2lx.cpp,v 1.12 2000-08-19 17:22:52 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
263 /*
264 * Temporary fix.
265 * Make resource section writable.
266 * Make 64 KB before the resource section present.
267 */
268 int iSection;
269 if (pResRootDir != NULL && (iSection = getSectionIndexFromRVA(ulRVAResourceSection)) != -1)
270 {
271 ULONG ulAddr = paSections[iSection].ulAddress;
272 rc = DosSetMem((PVOID)ulAddr, paSections[iSection].cbVirtual, PAG_WRITE | PAG_READ);
273 ulAddr -= 0x10000;
274 while (ulAddr < paSections[iSection].ulAddress)
275 {
276 ULONG fl = ~0UL;
277 ULONG cb = ~0UL;
278 if ((rc = DosQueryMem((PVOID)ulAddr, &cb, &fl)) == NO_ERROR)
279 {
280 if ((fl & PAG_COMMIT) == 0)
281 {
282 fl &= PAG_WRITE & PAG_READ & PAG_GUARD;
283 if ((fl & PAG_READ) == 0)
284 fl |= PAG_READ;
285 rc = DosSetMem((PVOID)ulAddr, cb, fl | PAG_COMMIT);
286 }
287
288 ulAddr += cb;
289 }
290 }
291 rc = NO_ERROR;
292 }
293 }
294
295 /* TLS - Thread Local Storage */
296 if (pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0UL
297 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size != 0UL)
298 {
299 PIMAGE_TLS_DIRECTORY pTLSDir;
300 pTLSDir = (PIMAGE_TLS_DIRECTORY)getPointerFromRVA(pNtHdrs->OptionalHeader.
301 DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].
302 VirtualAddress);
303
304 if (pTLSDir != NULL)
305 {
306 PVOID pv;
307 ULONG ulBorlandRVAFix = 0UL;
308
309 pv = getPointerFromRVA(pTLSDir->StartAddressOfRawData);
310 /*
311 * Borland seems to have problems getting things right...
312 * Needs to subtract image base to make the TLSDir "RVA"s real
313 * RVAs before converting them to pointers.
314 */
315 if ((pv == NULL || pTLSDir->StartAddressOfRawData == 0UL)
316 && pTLSDir->StartAddressOfRawData > this->pNtHdrs->OptionalHeader.ImageBase)
317 {
318 ulBorlandRVAFix = this->pNtHdrs->OptionalHeader.ImageBase;
319 pv = getPointerFromRVA(pTLSDir->StartAddressOfRawData - ulBorlandRVAFix);
320 }
321 if (pv == NULL || pTLSDir->StartAddressOfRawData == 0UL)
322 {
323 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS StartAddressOfRawData - %#8x.\n",
324 pTLSDir->StartAddressOfRawData));
325 return FALSE;
326 }
327 setTLSAddress(pv);
328 setTLSInitSize(pTLSDir->EndAddressOfRawData - pTLSDir->StartAddressOfRawData);
329 setTLSTotalSize(pTLSDir->EndAddressOfRawData - pTLSDir->StartAddressOfRawData + pTLSDir->SizeOfZeroFill);
330 pv = getPointerFromRVA((ULONG)pTLSDir->AddressOfIndex - ulBorlandRVAFix);
331 if (pv == NULL)
332 {
333 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS AddressOffIndex - %#8x.\n",
334 pTLSDir->AddressOfIndex));
335 return FALSE;
336 }
337 setTLSIndexAddr((LPDWORD)pv);
338 pv = getPointerFromRVA((ULONG)pTLSDir->AddressOfCallBacks - ulBorlandRVAFix);
339 if (pv == NULL)
340 {
341 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS AddressOffIndex - %#8x.\n",
342 pTLSDir->AddressOfIndex));
343 return FALSE;
344 }
345 setTLSCallBackAddr((PIMAGE_TLS_CALLBACK*)pv);
346 }
347 else
348 {
349 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS Dir - %#8x. (getPointerFromRVA failed)\n",
350 pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress));
351 return FALSE;
352 }
353 }
354 return TRUE;
355}
356
357
358
359/**
360 * Gets the object layout for this module. Creates the paSections array.
361 * @returns OS2 errorcode. (NO_ERROR == success)
362 * @sketch Allocate output buffer.
363 * Call DosQuerySysState.
364 * IF buffer overflow THEN retry calling it with larger buffers, until buffer size is 1MB.
365 * IF success THEN
366 * BEGIN
367 * Find record for this module.
368 * IF record found THEN allocate memory for object table and copy it. (paSections, cSections)
369 * END
370 * @status Completely implemented.
371 * @author knut st. osmundsen
372 */
373ULONG Win32Pe2LxImage::getSections()
374{
375 APIRET rc = NO_ERROR;
376 qsPtrRec_t * pPtrRec;
377 ULONG cbBuf = 65536;
378
379 pPtrRec = (qsPtrRec_t *)malloc(cbBuf);
380 if (pPtrRec != NULL)
381 {
382 rc = DosQuerySysState(QS_MTE, QS_MTE, getpid(), 0L, pPtrRec, cbBuf);
383 while (cbBuf < 1024*1024 && rc == ERROR_BUFFER_OVERFLOW)
384 {
385 PVOID pv = pPtrRec;
386 cbBuf += 65536;
387 pPtrRec = (qsPtrRec_t *)realloc(pv, cbBuf);
388 if (pPtrRec != NULL)
389 rc = DosQuerySysState(QS_MTE, QS_MTE, getpid(), 0L, pPtrRec, cbBuf);
390 else
391 {
392 rc = ERROR_NOT_ENOUGH_MEMORY;
393 free(pv);
394 }
395 }
396
397 if (rc == NO_ERROR)
398 {
399 qsLrec_t * pLrec = pPtrRec->pLibRec;
400 while (pLrec != NULL)
401 {
402 /*
403 * Bug detected in OS/2 FP13. Probably a problem which occurs
404 * in _LDRSysMteInfo when qsCheckCache is calle before writing
405 * object info. The result is that the cache flushed and the
406 * attempt of updating the qsLrec_t next and object pointer is
407 * not done. This used to work earlier and on Aurora AFAIK.
408 *
409 * The fix for this problem is to check if the pObjInfo is NULL
410 * while the number of objects isn't 0 and correct this. pNextRec
411 * will also be NULL at this time. This will be have to corrected
412 * before we exit the loop or moves to the next record.
413 * There is also a nasty alignment of the object info... Hope
414 * I got it right. (This aligment seems new to FP13.)
415 */
416 if (pLrec->pObjInfo == NULL /*&& pLrec->pNextRec == NULL*/ && pLrec->ctObj > 0)
417 {
418 pLrec->pObjInfo = (qsLObjrec_t*)(
419 (char*)pLrec
420 + ((sizeof(qsLrec_t) /* size of the lib record */
421 + pLrec->ctImpMod * sizeof(short) /* size of the array of imported modules */
422 + strlen((char*)pLrec->pName) + 1 /* size of the filename */
423 + 3) & ~3)); /* the size is align on 4 bytes boundrary */
424 pLrec->pNextRec = (qsLrec_t*)((char*)pLrec->pObjInfo
425 + sizeof(qsLObjrec_t) * pLrec->ctObj);
426 }
427 if (pLrec->hmte == hinstance)
428 break;
429
430 /*
431 * Next record
432 */
433 pLrec = (qsLrec_t*)pLrec->pNextRec;
434 }
435
436
437 if (pLrec)
438 {
439 if (pLrec->pObjInfo != NULL)
440 {
441 /* Allocate memory for paSections */
442 paSections = (PSECTION)malloc(pLrec->ctObj*sizeof(SECTION));
443 if (paSections != NULL)
444 {
445 /* objects -> section array */
446 for (int i = 0; i < pLrec->ctObj; i++)
447 {
448 paSections[i].ulRVA = ~0UL;
449 paSections[i].cbVirtual = pLrec->pObjInfo[i].osize;
450 paSections[i].ulAddress = pLrec->pObjInfo[i].oaddr;
451 }
452 cSections = pLrec->ctObj;
453 }
454 else
455 rc = ERROR_NOT_ENOUGH_MEMORY;
456 }
457 else
458 {
459 rc = ERROR_BAD_EXE_FORMAT;
460 dprintf(("Win32Pe2LxImage::getSections: Error - no object table!\n"));
461 }
462 }
463 else
464 rc = ERROR_MOD_NOT_FOUND;
465 }
466 else
467 dprintf(("DosQuerySysState - failed with rc=%d (cbBuf=%d)\n", rc, cbBuf));
468
469 if (pPtrRec != NULL)
470 free(pPtrRec);
471 }
472 else
473 rc = ERROR_NOT_ENOUGH_MEMORY;
474
475 return rc;
476}
477
478
479/**
480 * Sets the ulRVA according to the original PE section table.
481 * @returns OS/2 errorcode. (NO_ERROR == success)
482 * @sketch DEBUG: Validate pNtHdrs
483 * Make pointer to start of PE section table.
484 * Set RVA for the header section.
485 * IF not all in one object exe? THEN
486 * Loop thru the sections in the PE section table.
487 * Note: due to the header section: PE section no. + 1 == LX object no.
488 * ELSE
489 * BEGIN
490 * (try) Reallocate paSections to NumberOfSections + 3.
491 * Loop thru the PE sections and make paSections from them.
492 * Add final Stack or TIBFix+Stack section if necessary.
493 * Resize header section.
494 * END
495 * @status completely implemented.
496 * @author knut st. osmundsen
497 * @remark Must not be called before pNtHdrs is set.
498 */
499ULONG Win32Pe2LxImage::setSectionRVAs()
500{
501 #if DEBUG
502 if (pNtHdrs == NULL)
503 {
504 DebugInt3();
505 return ERROR_INVALID_PARAMETER;
506 }
507 #endif
508
509 PIMAGE_SECTION_HEADER paPESections = (PIMAGE_SECTION_HEADER)
510 ((unsigned)pNtHdrs + sizeof(*pNtHdrs) +
511 (pNtHdrs->OptionalHeader.NumberOfRvaAndSizes - IMAGE_NUMBEROF_DIRECTORY_ENTRIES) * sizeof(IMAGE_DATA_DIRECTORY)
512 );
513
514 /* set RVA for the header section to 0UL. */
515 paSections[0].ulRVA = 0UL;
516
517 /* All in one object exe? */
518 if (pNtHdrs->FileHeader.NumberOfSections < cSections)
519 {
520 /* loop thru the other sections */
521 for (int i = 0; i < pNtHdrs->FileHeader.NumberOfSections; i++)
522 paSections[i+1].ulRVA = paPESections[i].VirtualAddress;
523 }
524 else
525 { /* all in one object */
526 /* (try) Reallocate paSections to NumberOfSections + 3. */
527 PVOID pv = realloc(paSections, sizeof(paSections[0]) * (pNtHdrs->FileHeader.NumberOfSections + 3));
528 if (pv != NULL)
529 {
530 paSections = (PSECTION)pv;
531
532 /* loop thru the PE sections */
533 for (int i = 0; i < pNtHdrs->FileHeader.NumberOfSections; i++)
534 {
535 if (paSections[0].cbVirtual < paPESections[i].VirtualAddress)
536 {
537 dprintf(("Win32Pe2LxImage::setSectionRVAs: mismatch between section table and all-in-one-object"
538 "paSections[0].cbVirtual %#x paPESections[i].VirtualAddress %#x\n",
539 paSections[0].cbVirtual, paPESections[i].VirtualAddress
540 ));
541 return ERROR_BAD_EXE_FORMAT;
542 }
543 paSections[i+1].ulRVA = paPESections[i].VirtualAddress;
544 paSections[i+1].cbVirtual = max(paPESections[i].Misc.VirtualSize, paPESections[i].SizeOfRawData);
545 paSections[i+1].ulAddress = paSections[0].ulAddress + paPESections[i].VirtualAddress;
546 }
547 cSections = pNtHdrs->FileHeader.NumberOfSections + 1;
548
549 /* add final Stack or TIBFix+Stack section if necessary */
550 if (paSections[0].cbVirtual > paSections[i].ulRVA + ALIGN(paSections[i].cbVirtual, 0x1000))
551 {
552 paSections[i+1].ulRVA = ~0UL;
553 paSections[i+1].cbVirtual = paSections[0].cbVirtual - paSections[i].ulRVA + ALIGN(paSections[i].cbVirtual, 0x1000);
554 paSections[i+1].ulAddress = paSections[i].ulAddress + ALIGN(paSections[i].cbVirtual, 0x1000);
555 i++;
556 cSections++;
557 }
558
559 /* resize header section */
560 paSections[0].cbVirtual = paSections[1].ulRVA; /*....*/
561 }
562 else
563 return ERROR_NOT_ENOUGH_MEMORY;
564 }
565
566 return NO_ERROR;
567}
568
569
570/**
571 * Frees memory used by this object.
572 * When an exception is to be thrown, this function is called first to clean up
573 * the object. Base class(es) are automatically clean up by theire destructor(s).
574 * @status completely implemented.
575 * @author knut st. osmundsen
576 */
577VOID Win32Pe2LxImage::cleanup()
578{
579 if (paSections != NULL)
580 {
581 free(paSections);
582 paSections = NULL;
583 cSections = 0;
584 }
585}
586
587
588/**
589 * Converts a RVA to an pointer.
590 * @returns Pointer matching the given RVA, NULL on error.
591 * @param ulRVA An address relative to the imagebase of the original PE image.
592 * If this is 0UL NULL is returned.
593 * @sketch DEBUG: validate state, paSections != NULL
594 * IF ulRVA is 0 THEN return NULL
595 * LOOP while more section left and ulRVA is not within section
596 * next section
597 * IF section matching ulRVA is not found THEN fail.
598 * return pointer matching RVA.
599 * @status completely implemented.
600 * @author knut st. osmundsen
601 * @remark Should not be called until getSections has returned successfully.
602 * RVA == 0 is ignored.
603 */
604PVOID Win32Pe2LxImage::getPointerFromRVA(ULONG ulRVA)
605{
606 int i;
607 #ifdef DEBUG
608 if (paSections == NULL)
609 return NULL;
610 #endif
611
612 if (ulRVA == 0UL)
613 return NULL;
614
615 i = 0;
616 while (i < cSections &&
617 !(paSections[i].ulRVA <= ulRVA && paSections[i].ulRVA + paSections[i].cbVirtual > ulRVA)) /* ALIGN on page too? */
618 i++;
619
620 if (i >= cSections)
621 return NULL;
622
623 return (PVOID)(ulRVA - paSections[i].ulRVA + paSections[i].ulAddress);
624}
625
626
627/**
628 * Gets the (0-based) index into paSection of the section holding the
629 * given ulRVA.
630 * @returns Section index (0 based).
631 * -1 on error.
632 * @param ulRVA Relative Virtual Address.
633 * @sketch DEBUG: validate state, paSections != NULL
634 * IF ulRVA is 0 THEN return NULL
635 * LOOP while more section left and ulRVA is not within section
636 * next section
637 * IF section matching ulRVA is not found THEN fail.
638 * The index.
639 * @status
640 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
641 * @remark
642 */
643LONG Win32Pe2LxImage::getSectionIndexFromRVA(ULONG ulRVA)
644{
645 int i;
646 #ifdef DEBUG
647 if (paSections == NULL)
648 return NULL;
649 #endif
650
651 if (ulRVA == 0UL)
652 return NULL;
653
654 i = 0;
655 while (i < cSections &&
656 !(paSections[i].ulRVA <= ulRVA && paSections[i].ulRVA + paSections[i].cbVirtual > ulRVA)) /* ALIGN on page too? */
657 i++;
658
659 if (i >= cSections)
660 return -1;
661
662 return i;
663}
664
665
666/**
667 * Gets pointer to an exported procedure by procedure name.
668 * @returns Address of exported procedure. 0UL if not found.
669 * @param name Exported procedure name.
670 * @status completely implemented.
671 * @author Sander van Leeuwen
672 * @remark
673 */
674ULONG Win32Pe2LxImage::getApi(char *name)
675{
676 APIRET rc;
677 ULONG ulApiAddr;
678
679 rc = DosQueryProcAddr(hinstance, 0, name, (PFN *)&ulApiAddr);
680 return rc == NO_ERROR ? ulApiAddr : 0;
681}
682
683
684/**
685 * Gets pointer to an exported procedure by ordinal.
686 * @returns Pointer to an exported procedure. 0UL if not found.
687 * @param ordinal Export ordinal number.
688 * @status completely implemented.
689 * @author Sander van Leeuwen
690 * @remark FIXME:
691 * This function should be implemented for both Exe and Dll images!
692 * It could be done similar in both peldr image and pe2lx images by
693 * accessing PE structures.
694 */
695ULONG Win32Pe2LxImage::getApi(int ordinal)
696{
697 APIRET rc;
698 ULONG ulApiAddr;
699
700 rc = DosQueryProcAddr(hinstance, ordinal, NULL, (PFN *)&ulApiAddr);
701
702 return rc == NO_ERROR ? ulApiAddr : 0;
703}
Note: See TracBrowser for help on using the repository browser.