Changeset 10397 for trunk/src/kernel32/winimagepe2lx.cpp
- Timestamp:
- Jan 15, 2004, 11:39:15 AM (22 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/winimagepe2lx.cpp
r9537 r10397 1 /* $Id: winimagepe2lx.cpp,v 1.2 1 2002-12-20 11:39:42 sandervl Exp $ */1 /* $Id: winimagepe2lx.cpp,v 1.22 2004-01-15 10:39:12 sandervl Exp $ */ 2 2 3 3 /* … … 35 35 #include <misc.h> 36 36 #include "winimagebase.h" 37 #include "windllbase.h" 38 #include "winexebase.h" 37 39 #include "winimagepe2lx.h" 40 #include "winimagepeldr.h" 41 #include "windllpeldr.h" 42 #include "winimagelx.h" 43 #include "windlllx.h" 38 44 #include "Win32k.h" 39 45 … … 259 265 hinstance = (HINSTANCE)paSections[0].ulAddress; 260 266 267 /* Set poh & pExportDir (base class stuff) */ 268 poh = &pNtHdrs->OptionalHeader; 269 pExportDir = (PIMAGE_EXPORT_DIRECTORY)getPointerFromRVA(pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 270 261 271 /* Locate and set the entrypoint. */ 262 272 setEntryPoint((ULONG)getPointerFromRVA(pNtHdrs->OptionalHeader.AddressOfEntryPoint)); … … 272 282 273 283 /* Locate the resource directory (if any) */ 274 if (pNtHdrs->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE 275 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress > 0UL) 276 { 277 ulRVAResourceSection = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; 278 pResRootDir = (PIMAGE_RESOURCE_DIRECTORY)getPointerFromRVA(ulRVAResourceSection); 279 /* _temporary_ fix: 280 * We'll have to make the resource section writable. 281 * And we'll have to make the pages before it readable. 282 */ 283 LONG iSection = getSectionIndexFromRVA(ulRVAResourceSection); 284 if (iSection >= 0) 285 { 286 rc = DosSetMem((PVOID)paSections[iSection].ulAddress, paSections[iSection].cbVirtual, PAG_WRITE | PAG_READ); 287 288 ULONG ulAddr = paSections[iSection].ulAddress - 0x10000; //64KB 289 while (ulAddr < paSections[iSection].ulAddress) 290 { 291 ULONG fl = ~0UL; 292 ULONG cb = ~0UL; 293 rc = DosQueryMem((PVOID)ulAddr, &cb, &fl); 294 if (rc == NO_ERROR) 295 { 296 if (fl & PAG_GUARD) 297 rc = -1; 298 else if (fl & PAG_COMMIT) 299 fl &= ~(PAG_COMMIT); 300 else 301 fl |= PAG_COMMIT; 302 cb = (cb + 0xfffUL) & ~0xfffUL; 303 } 304 else 305 { 306 fl = PAG_COMMIT; 307 cb = 0x1000; 308 } 309 fl &= PAG_READ | PAG_COMMIT | PAG_WRITE | PAG_GUARD; 310 fl |= PAG_READ; 311 if (cb > paSections[iSection].ulAddress - ulAddr) 312 cb = paSections[iSection].ulAddress - ulAddr; 313 if (rc == NO_ERROR) 314 rc = DosSetMem((PVOID)ulAddr, cb, fl); 315 316 ulAddr += cb; 317 } 318 } 319 } 320 321 /* TLS - Thread Local Storage */ 322 if (pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0UL 323 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size != 0UL) 324 { 325 PIMAGE_TLS_DIRECTORY pTLSDir; 326 LONG iSection; 327 iSection = getSectionIndexFromRVA(pNtHdrs->OptionalHeader. 328 DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]. 329 VirtualAddress); 330 pTLSDir = (PIMAGE_TLS_DIRECTORY)getPointerFromRVA(pNtHdrs->OptionalHeader. 331 DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]. 332 VirtualAddress); 333 334 if (pTLSDir != NULL && iSection != -1) 335 { 336 PVOID pv; 337 338 /* 339 * According to the docs StartAddressOfRawData and EndAddressOfRawData is 340 * real pointers with a baserelocs. 341 * 342 * The docs says nothing about the two AddressOf pointers. So, we'll assume that 343 * these also are real pointers. But, we'll try compensate if they should not have 344 * base realocations. 345 */ 346 if (validateRealPointer((PVOID)pTLSDir->StartAddressOfRawData) 347 && 348 validateRealPointer((PVOID)pTLSDir->EndAddressOfRawData) 349 ) 350 { 351 setTLSAddress((PVOID)pTLSDir->StartAddressOfRawData); 352 setTLSInitSize(pTLSDir->EndAddressOfRawData - pTLSDir->StartAddressOfRawData); 353 setTLSTotalSize(pTLSDir->EndAddressOfRawData - pTLSDir->StartAddressOfRawData + pTLSDir->SizeOfZeroFill); 354 355 if (pTLSDir->AddressOfIndex) 356 { 357 if (validateRealPointer(pTLSDir->AddressOfIndex)) 358 /* assume baserelocations for thepointer; use it without any change. */ 359 setTLSIndexAddr((LPDWORD)(void*)pTLSDir->AddressOfIndex); 360 else 361 { /* assume no baserelocs for these pointers? Complain and debugint3 */ 362 eprintf(("Win32Pe2LxImage::init: TLS - AddressOfIndex(%#8x) is not a pointer with basereloc.\n", 363 pTLSDir->AddressOfIndex)); 364 pv = getPointerFromPointer(pTLSDir->AddressOfIndex); 365 if (pv == NULL) 366 { 367 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS AddressOfIndex - %#8x.\n", 368 pTLSDir->AddressOfIndex)); 369 return LDRERROR_INVALID_HEADER; 370 } 371 setTLSIndexAddr((LPDWORD)pv); 372 } 373 } 374 375 if (pTLSDir->AddressOfCallBacks) 376 { 377 if (validateRealPointer(pTLSDir->AddressOfCallBacks)) 378 /* assume baserelocations for thepointer; use it without any change. */ 379 setTLSCallBackAddr(pTLSDir->AddressOfCallBacks); 380 else 381 { /* assume no baserelocs for these pointers? Complain and debugint3 */ 382 eprintf(("Win32Pe2LxImage::init: Warning: TLS - AddressOfCallBacks(%#8x) is not a pointer with basereloc.\n", 383 pTLSDir->AddressOfCallBacks)); 384 pv = getPointerFromPointer(pTLSDir->AddressOfCallBacks); 385 if (pv == NULL) 386 { 387 eprintf(("Win32Pe2LxImage::init: invalid pointer to TLS AddressOfCallBacks - %#8x.\n", 388 pTLSDir->AddressOfIndex)); 389 return LDRERROR_INVALID_HEADER; 390 } 391 setTLSCallBackAddr((PIMAGE_TLS_CALLBACK*)pv); 392 } 393 } 394 } 395 } 396 else 397 { 398 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS Dir - %#8x. (getPointerFromRVA failed)\n", 399 pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress)); 400 return LDRERROR_INVALID_HEADER; 401 } 402 } 284 rc = doResources(); 285 if (rc) 286 return rc; 287 288 /* 289 * TLS - Thread Local Storage 290 */ 291 rc = doTLS(); 292 if (rc) 293 return rc; 294 295 296 /* 297 * Process imports. 298 */ 299 rc = doImports(); 300 if (rc) 301 return rc; 302 403 303 return LDRERROR_SUCCESS; 404 304 } 405 406 305 407 306 … … 688 587 689 588 /** 589 * Process resource section. 590 */ 591 ULONG Win32Pe2LxImage::doResources() 592 { 593 ULONG rc; 594 595 if (pNtHdrs->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_RESOURCE 596 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress > 0UL) 597 { 598 ulRVAResourceSection = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; 599 pResRootDir = (PIMAGE_RESOURCE_DIRECTORY)getPointerFromRVA(ulRVAResourceSection); 600 /* _temporary_ fix: 601 * We'll have to make the resource section writable. 602 * And we'll have to make the pages before it readable. 603 */ 604 LONG iSection = getSectionIndexFromRVA(ulRVAResourceSection); 605 if (iSection >= 0) 606 { 607 rc = DosSetMem((PVOID)paSections[iSection].ulAddress, paSections[iSection].cbVirtual, PAG_WRITE | PAG_READ); 608 609 ULONG ulAddr = paSections[iSection].ulAddress - 0x10000; //64KB 610 while (ulAddr < paSections[iSection].ulAddress) 611 { 612 ULONG fl = ~0UL; 613 ULONG cb = ~0UL; 614 rc = DosQueryMem((PVOID)ulAddr, &cb, &fl); 615 if (rc == NO_ERROR) 616 { 617 if (fl & PAG_GUARD) 618 rc = -1; 619 else if (fl & PAG_COMMIT) 620 fl &= ~(PAG_COMMIT); 621 else 622 fl |= PAG_COMMIT; 623 cb = (cb + 0xfffUL) & ~0xfffUL; 624 } 625 else 626 { 627 fl = PAG_COMMIT; 628 cb = 0x1000; 629 } 630 fl &= PAG_READ | PAG_COMMIT | PAG_WRITE | PAG_GUARD; 631 fl |= PAG_READ; 632 if (cb > paSections[iSection].ulAddress - ulAddr) 633 cb = paSections[iSection].ulAddress - ulAddr; 634 if (rc == NO_ERROR) 635 rc = DosSetMem((PVOID)ulAddr, cb, fl); 636 637 ulAddr += cb; 638 } 639 } 640 } 641 642 return 0; 643 } 644 645 646 /** 647 * Do TLS related matters. 648 */ 649 ULONG Win32Pe2LxImage::doTLS() 650 { 651 if (pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0UL 652 && pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size != 0UL) 653 { 654 PIMAGE_TLS_DIRECTORY pTLSDir; 655 LONG iSection; 656 iSection = getSectionIndexFromRVA(pNtHdrs->OptionalHeader. 657 DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]. 658 VirtualAddress); 659 pTLSDir = (PIMAGE_TLS_DIRECTORY)getPointerFromRVA(pNtHdrs->OptionalHeader. 660 DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS]. 661 VirtualAddress); 662 663 if (pTLSDir != NULL && iSection != -1) 664 { 665 PVOID pv; 666 667 /* 668 * According to the docs StartAddressOfRawData and EndAddressOfRawData is 669 * real pointers with a baserelocs. 670 * 671 * The docs says nothing about the two AddressOf pointers. So, we'll assume that 672 * these also are real pointers. But, we'll try compensate if they should not have 673 * base realocations. 674 */ 675 if (validateRealPointer((PVOID)pTLSDir->StartAddressOfRawData) 676 && 677 validateRealPointer((PVOID)pTLSDir->EndAddressOfRawData) 678 ) 679 { 680 setTLSAddress((PVOID)pTLSDir->StartAddressOfRawData); 681 setTLSInitSize(pTLSDir->EndAddressOfRawData - pTLSDir->StartAddressOfRawData); 682 setTLSTotalSize(pTLSDir->EndAddressOfRawData - pTLSDir->StartAddressOfRawData + pTLSDir->SizeOfZeroFill); 683 684 if (pTLSDir->AddressOfIndex) 685 { 686 if (validateRealPointer(pTLSDir->AddressOfIndex)) 687 /* assume baserelocations for thepointer; use it without any change. */ 688 setTLSIndexAddr((LPDWORD)(void*)pTLSDir->AddressOfIndex); 689 else 690 { /* assume no baserelocs for these pointers? Complain and debugint3 */ 691 eprintf(("Win32Pe2LxImage::init: TLS - AddressOfIndex(%#8x) is not a pointer with basereloc.\n", 692 pTLSDir->AddressOfIndex)); 693 pv = getPointerFromPointer(pTLSDir->AddressOfIndex); 694 if (pv == NULL) 695 { 696 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS AddressOfIndex - %#8x.\n", 697 pTLSDir->AddressOfIndex)); 698 return LDRERROR_INVALID_HEADER; 699 } 700 setTLSIndexAddr((LPDWORD)pv); 701 } 702 } 703 704 if (pTLSDir->AddressOfCallBacks) 705 { 706 if (validateRealPointer(pTLSDir->AddressOfCallBacks)) 707 /* assume baserelocations for thepointer; use it without any change. */ 708 setTLSCallBackAddr(pTLSDir->AddressOfCallBacks); 709 else 710 { /* assume no baserelocs for these pointers? Complain and debugint3 */ 711 eprintf(("Win32Pe2LxImage::init: Warning: TLS - AddressOfCallBacks(%#8x) is not a pointer with basereloc.\n", 712 pTLSDir->AddressOfCallBacks)); 713 pv = getPointerFromPointer(pTLSDir->AddressOfCallBacks); 714 if (pv == NULL) 715 { 716 eprintf(("Win32Pe2LxImage::init: invalid pointer to TLS AddressOfCallBacks - %#8x.\n", 717 pTLSDir->AddressOfIndex)); 718 return LDRERROR_INVALID_HEADER; 719 } 720 setTLSCallBackAddr((PIMAGE_TLS_CALLBACK*)pv); 721 } 722 } 723 } 724 } 725 else 726 { 727 eprintf(("Win32Pe2LxImage::init: invalid RVA to TLS Dir - %#8x. (getPointerFromRVA failed)\n", 728 pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress)); 729 return LDRERROR_INVALID_HEADER; 730 } 731 } 732 733 return 0; 734 } 735 736 /** 737 * Processes the import directory of the image. 738 * @returns LDRERROR_* 739 * @remark This could be in base class and shared with the peldr. 740 */ 741 ULONG Win32Pe2LxImage::doImports() 742 { 743 ULONG rc; 744 PIMAGE_IMPORT_DESCRIPTOR pImps; 745 746 /* 747 * Check if there is actually anything to work on. 748 */ 749 if ( !pNtHdrs->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].VirtualAddress 750 || !pNtHdrs->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].Size) 751 { 752 dprintf(("Win32Pe2LxImage::initImports: there are no imports\n")); 753 return 0; 754 } 755 756 /* 757 * Walk the IMAGE_IMPORT_DESCRIPTOR table. 758 */ 759 for (rc = 0, pImps = (PIMAGE_IMPORT_DESCRIPTOR)getPointerFromRVA(pNtHdrs->OptionalHeader.DataDirectory[IMAGE_FILE_IMPORT_DIRECTORY].VirtualAddress); 760 !rc && pImps->Name != 0 && pImps->FirstThunk != 0; 761 pImps++) 762 { 763 const char * pszName = (const char*)getPointerFromRVA(pImps->Name); 764 Win32ImageBase *pModule; 765 dprintf(("Win32Pe2LxImage::initImports: DLL %s\n", pszName)); 766 767 /* 768 * Try find the table. 769 */ 770 pModule = importsGetModule(pszName); 771 if (pModule) 772 { 773 PIMAGE_THUNK_DATA pFirstThunk; /* update this. */ 774 PIMAGE_THUNK_DATA pThunk; /* read from this. */ 775 776 /* 777 * Walk the thunks table(s). 778 */ 779 pFirstThunk = (PIMAGE_THUNK_DATA)getPointerFromRVA((ULONG)pImps->FirstThunk); 780 pThunk = pImps->u.OriginalFirstThunk == 0 ? pFirstThunk 781 : (PIMAGE_THUNK_DATA)getPointerFromRVA((ULONG)pImps->FirstThunk); 782 while (!rc && pThunk->u1.Ordinal != 0) 783 { 784 if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) 785 rc = importsByOrdinal(pModule, IMAGE_ORDINAL(pThunk->u1.Ordinal), (void**)&pFirstThunk->u1.Function); 786 else if ( pThunk->u1.Ordinal > 0 787 && pThunk->u1.Ordinal < pNtHdrs->OptionalHeader.SizeOfImage) 788 rc = importsByName(pModule, (const char*)getPointerFromRVA((ULONG)pThunk->u1.AddressOfData + 2), (void**)&pFirstThunk->u1.Function); 789 else 790 { 791 dprintf(("Win32Pe2LxImage::initImports: bad import data thunk!\n")); 792 DebugInt3(); 793 rc = LDRERROR_IMPORTS; 794 } 795 796 pThunk++; 797 pFirstThunk++; 798 } 799 } 800 else 801 { 802 dprintf(("Win32Pe2LxImage::initImports: cannot find module '%s'!!!\n", pszName)); 803 DebugInt3(); 804 rc = LDRERROR_IMPORTS; 805 } 806 } 807 808 return rc; 809 } 810 811 812 /** 813 * Find a module. 814 * 815 * @returns Pointer to module 816 * @returns NULL on failure. 817 * @param pszModName Pointer to module name. 818 * @remark This should be in base class and shared with the peldr. 819 */ 820 Win32ImageBase * Win32Pe2LxImage::importsGetModule(const char *pszModName) 821 { 822 Win32ImageBase *pMod; 823 Win32DllBase *pDll; 824 825 /* 826 * Look if it's already loaded. 827 */ 828 pDll = Win32DllBase::findModule((char*)pszModName); 829 if (pDll) 830 { 831 dprintf(("Win32Pe2LxImage::importGetModule(%s) already loaded\n", pszModName)); 832 pDll->AddRef(); 833 } 834 else if (WinExe != NULL && WinExe->matchModName(pszModName)) 835 { 836 dprintf(("Win32Pe2LxImage::importGetModule(%s) already loaded (exe)\n", pszModName)); 837 pMod = (Win32ImageBase *)WinExe; 838 pDll = NULL; 839 } 840 else 841 { 842 /* 843 * Load it (simplified). 844 */ 845 pDll = importsLoadModule(pszModName); 846 if (!pDll) 847 return NULL; 848 dprintf(("Win32Pe2LxImage::importGetModule(%s) Loaded module\n", pszModName)); 849 } 850 851 /* 852 * Update dependendcies. 853 */ 854 if (pDll) 855 { 856 /* 857 * Add the dll we just loaded to dependency list for this image. 858 */ 859 addDependency(pDll); 860 861 /* 862 * Make sure the dependency list is correct (already done in the ctor 863 * of Win32DllBase, but for LX dlls the parent is then set to NULL) 864 * so, change it here again 865 */ 866 pDll->setUnloadOrder(this); 867 pMod = pDll; 868 } 869 870 return pMod; 871 } 872 873 /** 874 * Loads a module this module is depending on. 875 * @returns Pointer to loaded module. 876 * @returns NULL on failure. 877 * @param pszModName Name of the module to be loaded. 878 * @remark This should be in base class and shared with the peldr. 879 */ 880 Win32DllBase *Win32Pe2LxImage::importsLoadModule(const char *pszModName) 881 { 882 Win32DllBase *pDll; 883 char szRenamed[CCHMAXPATH]; 884 885 /* 886 * Copy and rename the module name. (i.e. OLE32 -> OLE32OS2) 887 */ 888 Win32DllBase::renameDll(strcpy(szRenamed, pszModName)); 889 890 /* 891 * Find the filename (using the standard search stuff). 892 */ 893 char szFullname[CCHMAXPATH]; 894 if (!Win32ImageBase::findDll(szRenamed, szFullname, sizeof(szFullname))) 895 { 896 dprintf(("Module %s not found!", szRenamed)); 897 errorState = ERROR_FILE_NOT_FOUND; 898 return NULL; 899 } 900 901 /* 902 * Check which type of executable module this is. 903 */ 904 if (isPEImage(szFullname, NULL, NULL) != ERROR_SUCCESS_W) 905 { 906 /* 907 * LX image: let OS/2 do all the work for us 908 */ 909 char szModuleFailure[CCHMAXPATH]; 910 HMODULE hmodLXDll; 911 APIRET rc; 912 913 rc = DosLoadModule(szModuleFailure, sizeof(szModuleFailure), szFullname, (HMODULE *)&hmodLXDll); 914 if (rc) 915 { 916 dprintf(("DosLoadModule returned %X for %s", rc, szModuleFailure)); 917 errorState = rc; 918 return NULL; 919 } 920 921 pDll = Win32DllBase::findModuleByOS2Handle((HINSTANCE)hmodLXDll); 922 if (pDll == NULL) 923 { 924 dprintf(("Just loaded the dll, but can't find it anywhere?!!?")); 925 DebugInt3(); 926 errorState = ERROR_INTERNAL; 927 return NULL; 928 } 929 930 /* 931 * For none Pe2Lx'ed LX modules we'll have to do a little work here. 932 */ 933 if (pDll->isLxDll()) 934 { 935 Win32LxDll *pLXDll = (Win32LxDll *)pDll; 936 pLXDll->setDllHandleOS2(hmodLXDll); 937 if (pLXDll->AddRef() == -1) //-1 -> load failed (attachProcess) 938 { 939 dprintf(("Dll %s refused to be loaded; aborting", szFullname)); 940 delete pLXDll; 941 errorState = ERROR_INTERNAL; 942 return NULL; 943 } 944 } 945 } 946 else 947 { 948 /* 949 * PE image: use the peldr. 950 */ 951 Win32PeLdrDll *pPEDll; 952 953 pPEDll = new Win32PeLdrDll(szFullname, this); 954 if (!pPEDll) 955 { 956 dprintf(("pedll: Error allocating memory" )); 957 errorState = ERROR_INTERNAL; 958 return NULL; 959 } 960 dprintf(("**********************************************************************")); 961 dprintf(("********************** Loading Module *********************")); 962 dprintf(("**********************************************************************")); 963 if (pPEDll->init(0) != LDRERROR_SUCCESS) 964 { 965 dprintf(("Internal WinDll error ", pPEDll->getError())); 966 delete pPEDll; 967 return NULL; 968 } 969 970 #ifdef DEBUG 971 pPEDll->AddRef(getModuleName()); 972 #else 973 pPEDll->AddRef(); 974 #endif 975 if (pPEDll->attachProcess() == FALSE) 976 { 977 dprintf(("attachProcess failed!")); 978 delete pPEDll; 979 errorState = ERROR_INTERNAL; 980 return NULL; 981 } 982 pDll = (Win32DllBase*)pPEDll; 983 } 984 985 dprintf(("**********************************************************************")); 986 dprintf(("********************** Finished Loading Module %s ", szFullname)); 987 dprintf(("**********************************************************************")); 988 return pDll; 989 } 990 991 992 /** 993 * Resolve an import by symbol name. 994 * 995 * @returns 0 on success, error code on failure. 996 * @param pModule Pointer to module. 997 * @param uOrdinal Ordinal of the symbol to import. 998 * @param ppvAddr Where to store the symbol address. 999 * @remark This should be in base class and shared with the peldr. 1000 */ 1001 ULONG Win32Pe2LxImage::importsByOrdinal(Win32ImageBase *pModule, unsigned uOrdinal, void **ppvAddr) 1002 { 1003 void *pfn; 1004 pfn = (void*)pModule->getApi(uOrdinal); 1005 if (pfn) 1006 { 1007 dprintf(("Win32Pe2LxImage::importsByOrdinal: *%p=%p %s!%d\n", ppvAddr, pfn, pModule->getModuleName(), uOrdinal)); 1008 *ppvAddr = pfn; 1009 return 0; 1010 } 1011 1012 dprintf(("Win32Pe2LxImage::importsByOrdinal: %s!%u\n", pModule->getModuleName(), uOrdinal)); 1013 DebugInt3(); 1014 /** @todo: missing api */ 1015 *ppvAddr = NULL; 1016 return LDRERROR_IMPORTS; 1017 } 1018 1019 1020 /** 1021 * Resolve an import by symbol name. 1022 * 1023 * @returns 0 on success, error code on failure. 1024 * @param pModule Pointer to module. 1025 * @param pszSymName Name of symbol to import. 1026 * @param ppvAddr Where to store the symbol address. 1027 * @remark This should be in base class and shared with the peldr. 1028 */ 1029 ULONG Win32Pe2LxImage::importsByName(Win32ImageBase *pModule, const char *pszSymName, void **ppvAddr) 1030 { 1031 void *pfn; 1032 pfn = (void*)pModule->getApi((char*)pszSymName); 1033 if (pfn) 1034 { 1035 dprintf(("Win32Pe2LxImage::importsByName: *%p=%p %s!%s\n", ppvAddr, pfn, pModule->getModuleName(), pszSymName)); 1036 *ppvAddr = pfn; 1037 return 0; 1038 } 1039 1040 dprintf(("Win32Pe2LxImage::importsByName: %s!%s\n", pModule->getModuleName(), pszSymName)); 1041 DebugInt3(); 1042 /** @todo: missing api */ 1043 *ppvAddr = NULL; 1044 return LDRERROR_IMPORTS; 1045 } 1046 1047 1048 /** 690 1049 * Frees memory used by this object. 691 1050 * When an exception is to be thrown, this function is called first to clean up … … 711 1070 * Converts a RVA into a pointer. 712 1071 * @returns Pointer matching the given RVA, NULL on error. 713 * @param ulRVA An address relative to the imagebase of the original PE image. 714 * If this is 0UL NULL is returned. 1072 * @param ulRVA An address relative to the imagebase of the original PE image. 1073 * If this is 0UL NULL is returned. 1074 * @param fOverride If set the ulRVA doesn't have to be inside the image. 715 1075 * @sketch DEBUG: validate state, paSections != NULL 716 1076 * IF ulRVA is 0 THEN return NULL … … 724 1084 * RVA == 0 is ignored. 725 1085 */ 726 PVOID Win32Pe2LxImage::getPointerFromRVA(ULONG ulRVA) 727 { 728 int i; 729 1086 void * Win32Pe2LxImage::getPointerFromRVA(ULONG ulRVA, BOOL fOverride) 1087 { 730 1088 #ifdef DEBUG 731 1089 if (paSections == NULL) … … 739 1097 return NULL; 740 1098 741 i = 0;1099 int i = 0; 742 1100 while (i < cSections && 743 1101 (paSections[i].ulRVA > ulRVA || paSections[i].ulRVA + paSections[i].cbVirtual <= ulRVA)) /* ALIGN on page too? */ 744 1102 i++; 745 746 1103 if (i >= cSections) 1104 { 1105 /* This isn't good, but it's required to support api overrides. */ 1106 if (fOverride) 1107 return (char*)hinstance + ulRVA; 747 1108 return NULL; 1109 } 748 1110 749 1111 return (PVOID)(ulRVA - paSections[i].ulRVA + paSections[i].ulAddress); 1112 } 1113 1114 1115 /** Converts a pointer to an RVA for the loaded image. 1116 * @remark Because of export overriding addresses outside the image must be supported. 1117 */ 1118 ULONG Win32Pe2LxImage::getRVAFromPointer(void *pv, BOOL fOverride/* = FALSE*/) 1119 { 1120 #ifdef DEBUG 1121 if (paSections == NULL) 1122 { 1123 eprintf(("Win32Pe2LxImage::getPointerFromRVA: paSections is NULL!\n")); 1124 return NULL; 1125 } 1126 #endif 1127 1128 if (pv == 0UL) 1129 return NULL; 1130 1131 int i = 0; 1132 while (i < cSections && 1133 (paSections[i].ulAddress > (ULONG)pv || paSections[i].ulAddress + paSections[i].cbVirtual <= (ULONG)pv)) /* ALIGN on page too? */ 1134 i++; 1135 if (i >= cSections) 1136 { 1137 /* This isn't good, but it's required to support api overrides. */ 1138 if (fOverride) 1139 return (ULONG)pv - (ULONG)hinstance; 1140 return NULL; 1141 } 1142 1143 return (ULONG)pv - paSections[i].ulAddress + paSections[i].ulRVA; 750 1144 } 751 1145 … … 843 1237 844 1238 845 /**846 * Gets pointer to an exported procedure by procedure name.847 * @returns Address of exported procedure. 0UL if not found.848 * @param name Exported procedure name.849 * @status completely implemented.850 * @author Sander van Leeuwen851 * @remark852 */853 ULONG Win32Pe2LxImage::getApi(char *name)854 {855 APIRET rc;856 ULONG ulApiAddr;857 858 rc = DosQueryProcAddr(hmod, 0, name, (PFN *)&ulApiAddr);859 return rc == NO_ERROR ? ulApiAddr : 0;860 }861 862 863 /**864 * Gets pointer to an exported procedure by ordinal.865 * @returns Pointer to an exported procedure. 0UL if not found.866 * @param ordinal Export ordinal number.867 * @status completely implemented.868 * @author Sander van Leeuwen869 * @remark FIXME:870 * This function should be implemented for both Exe and Dll images!871 * It could be done similar in both peldr image and pe2lx images by872 * accessing PE structures.873 */874 ULONG Win32Pe2LxImage::getApi(int ordinal)875 {876 APIRET rc;877 ULONG ulApiAddr;878 879 rc = DosQueryProcAddr(hmod, ordinal, NULL, (PFN *)&ulApiAddr);880 881 return rc == NO_ERROR ? ulApiAddr : 0;882 }
Note:
See TracChangeset
for help on using the changeset viewer.