Changeset 5848 for trunk/src/kernel32/winimagepeldr.cpp
- Timestamp:
- Jun 1, 2001, 3:21:13 AM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/winimagepeldr.cpp
r5837 r5848 1 /* $Id: winimagepeldr.cpp,v 1.7 7 2001-05-30 08:23:21 sandervlExp $ */1 /* $Id: winimagepeldr.cpp,v 1.78 2001-06-01 01:21:12 phaller Exp $ */ 2 2 3 3 /* … … 55 55 #include <wprocess.h> 56 56 57 57 58 //Define COMMIT_ALL to let the pe loader commit all sections of the image 58 59 //This is very useful during debugging as you'll get lots of exceptions … … 110 111 nrsections(0), imageSize(0), dwFlags(0), section(NULL), 111 112 imageVirtBase(-1), realBaseAddress(0), imageVirtEnd(0), 112 nrNameExports(0), nrOrdExports(0), nameexports(NULL), ordexports(NULL), 113 memmap(NULL), pFixups(NULL), dwFixupSize(0), curnameexport(NULL), curordexport(NULL) 113 nrNameExports(0), nrOrdExports(0), 114 nameexports(NULL), ordexports(NULL), 115 curnameexport(NULL), curordexport(NULL), 116 memmap(NULL), pFixups(NULL), dwFixupSize(0) 114 117 { 115 118 HFILE dllfile; … … 168 171 BOOL Win32PeLdrImage::init(ULONG reservedMem) 169 172 { 173 PERF_START(init) 174 170 175 LPVOID win32file = NULL; 171 176 ULONG filesize, ulRead, ulNewPos; … … 217 222 //Allocate memory to hold the entire image 218 223 if(allocSections(reservedMem) == FALSE) { 219 dprintf((LOG, "Failed to allocate image memory for %s at %x, rc %d", szFileName, oh.ImageBase, errorState)); ;224 dprintf((LOG, "Failed to allocate image memory for %s at %x, rc %d", szFileName, oh.ImageBase, errorState)); 220 225 goto failure; 221 226 } … … 650 655 } 651 656 } 657 658 PERF_ELAPSED(init, "Win32PeLdrImage::init", szFileName) 659 660 652 661 return(TRUE); 653 662 … … 688 697 // 689 698 //****************************************************************************** 699 700 #define DOSREAD_IDEAL_SIZE 61440 701 static inline APIRET _Optlink fastDosRead(HFILE hFile, 702 PVOID pAddress, 703 ULONG ulSize, 704 PULONG pulBytesRead) 705 { 706 /* we better break the DosRead into multiple calls */ 707 PBYTE p = (PBYTE)pAddress; 708 ULONG ulReadBytes; 709 APIRET rc; 710 711 *pulBytesRead = ulSize; 712 713 do 714 { 715 rc = DosRead(hFile, 716 p, 717 min(DOSREAD_IDEAL_SIZE, ulSize), 718 &ulReadBytes); 719 if (rc != NO_ERROR) 720 { 721 /* in case of errors bail out */ 722 *pulBytesRead = 0; 723 return rc; 724 } 725 726 ulSize -= ulReadBytes; 727 p += ulReadBytes; 728 } 729 while (ulSize > 0); 730 731 return NO_ERROR; 732 } 733 734 690 735 BOOL Win32PeLdrImage::commitPage(ULONG virtAddress, BOOL fWriteAccess, int fPageCmd) 691 736 { … … 783 828 goto fail; 784 829 } 785 rc = DosRead(hFile, (PVOID)virtAddress, size, &ulRead); 830 831 // 2001-05-31 PH 832 // ensure DosRead() does not have to read more 833 // than 65535 bytes, otherwise split into two requests! 834 rc = fastDosRead(hFile, (PVOID)virtAddress, size, &ulRead); 786 835 if(rc) { 787 836 DosExitCritSec(); … … 1277 1326 BOOL Win32PeLdrImage::processExports(char *win32file) 1278 1327 { 1279 IMAGE_SECTION_HEADER sh; 1280 PIMAGE_EXPORT_DIRECTORY ped; 1281 ULONG *ptrNames, *ptrAddress; 1282 USHORT *ptrOrd; 1283 BOOL fForwarder; 1284 int i; 1328 PERF_START(processexports) 1329 1330 IMAGE_SECTION_HEADER sh; 1331 PIMAGE_EXPORT_DIRECTORY ped; 1332 ULONG *ptrNames, *ptrAddress; 1333 USHORT *ptrOrd; 1334 BOOL fForwarder; 1335 int i; 1285 1336 1286 1337 /* get section header and pointer to data directory for .edata section */ 1287 1338 if((ped = (PIMAGE_EXPORT_DIRECTORY)ImageDirectoryOffset 1288 (win32file, IMAGE_DIRECTORY_ENTRY_EXPORT)) != NULL && 1289 GetSectionHdrByImageDir(win32file, IMAGE_DIRECTORY_ENTRY_EXPORT, &sh) ) { 1290 1291 dprintf((LOG, "Exported Functions: " )); 1339 (win32file, IMAGE_DIRECTORY_ENTRY_EXPORT)) != NULL && 1340 GetSectionHdrByImageDir(win32file, IMAGE_DIRECTORY_ENTRY_EXPORT, &sh) ) 1341 { 1342 1343 dprintf((LOG, "Exported Functions: " )); 1292 1344 ptrOrd = (USHORT *)((ULONG)ped->AddressOfNameOrdinals + 1293 1345 (ULONG)win32file); 1294 1346 ptrNames = (ULONG *)((ULONG)ped->AddressOfNames + 1295 1347 (ULONG)win32file); 1296 1348 ptrAddress = (ULONG *)((ULONG)ped->AddressOfFunctions + 1297 1349 (ULONG)win32file); 1298 1350 nrOrdExports = ped->NumberOfFunctions; 1299 1351 nrNameExports = ped->NumberOfNames; 1300 1352 1301 1353 int ord, RVAExport; 1302 1354 char *name; 1303 1355 for(i=0;i<ped->NumberOfNames;i++) 1304 1356 { 1305 fForwarder = FALSE; 1306 ord = ptrOrd[i] + ped->Base; 1307 name = (char *)((ULONG)ptrNames[i] + (ULONG)win32file); 1308 RVAExport = ptrAddress[ptrOrd[i]]; 1309 1310 /* forwarder? ulRVA within export directory. */ 1311 if(RVAExport > oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress && 1312 RVAExport < oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 1313 + oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) 1314 { 1315 fForwarder = AddForwarder(oh.ImageBase + RVAExport, name, ord); 1316 } 1317 if(!fForwarder) { 1318 //points to code (virtual address relative to oh.ImageBase 1319 AddNameExport(oh.ImageBase + RVAExport, name, ord); 1320 dprintf((LOG, "address 0x%x %s @%d (0x%08x)", RVAExport, name, ord, realBaseAddress + RVAExport)); 1321 } 1322 } 1357 fForwarder = FALSE; 1358 ord = ptrOrd[i] + ped->Base; 1359 name = (char *)((ULONG)ptrNames[i] + (ULONG)win32file); 1360 RVAExport = ptrAddress[ptrOrd[i]]; 1361 1362 /* forwarder? ulRVA within export directory. */ 1363 if(RVAExport > oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress && 1364 RVAExport < oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 1365 + oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) 1366 { 1367 fForwarder = AddForwarder(oh.ImageBase + RVAExport, name, ord); 1368 } 1369 1370 if(!fForwarder) 1371 { 1372 //points to code (virtual address relative to oh.ImageBase 1373 AddNameExport(oh.ImageBase + RVAExport, name, ord); 1374 dprintf((LOG, "address 0x%x %s @%d (0x%08x)", RVAExport, name, ord, realBaseAddress + RVAExport)); 1375 } 1376 } 1377 1323 1378 for(i=0;i<max(ped->NumberOfNames,ped->NumberOfFunctions);i++) 1324 1379 { 1325 fForwarder = FALSE; 1326 ord = ped->Base + i; //Correct?? 1327 RVAExport = ptrAddress[i]; 1328 /* forwarder? ulRVA within export directory. */ 1329 if(RVAExport > oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress && 1330 RVAExport < oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 1331 + oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) 1332 { 1333 fForwarder = AddForwarder(oh.ImageBase + RVAExport, NULL, ord); 1334 } 1335 if(!fForwarder && RVAExport) { 1336 //points to code (virtual address relative to oh.ImageBase 1337 dprintf((LOG, "ord %d at 0x%08x (0x%08x)", ord, RVAExport, realBaseAddress + RVAExport)); 1338 AddOrdExport(oh.ImageBase + RVAExport, ord); 1339 } 1340 } 1341 } 1380 fForwarder = FALSE; 1381 ord = ped->Base + i; //Correct?? 1382 RVAExport = ptrAddress[i]; 1383 /* forwarder? ulRVA within export directory. */ 1384 if(RVAExport > oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress && 1385 RVAExport < oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 1386 + oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) 1387 { 1388 fForwarder = AddForwarder(oh.ImageBase + RVAExport, NULL, ord); 1389 } 1390 1391 if(!fForwarder && RVAExport) 1392 { 1393 //points to code (virtual address relative to oh.ImageBase 1394 dprintf((LOG, "ord %d at 0x%08x (0x%08x)", ord, RVAExport, realBaseAddress + RVAExport)); 1395 AddOrdExport(oh.ImageBase + RVAExport, ord); 1396 } 1397 } 1398 } 1399 1400 PERF_ELAPSED(processexports, "Win32PeLdrImage::processExports", getModuleName()) 1401 1342 1402 return(TRUE); 1343 1403 } … … 1346 1406 void Win32PeLdrImage::AddNameExport(ULONG virtaddr, char *apiname, ULONG ordinal, BOOL fAbsoluteAddress) 1347 1407 { 1348 ULONG nsize; 1349 1350 if(nameexports == NULL) { 1351 nameExportSize= 4096; 1352 nameexports = (NameExport *)malloc(nameExportSize); 1353 curnameexport = nameexports; 1354 } 1355 nsize = (ULONG)curnameexport - (ULONG)nameexports; 1356 if(nsize + sizeof(NameExport) + strlen(apiname) > nameExportSize) { 1357 nameExportSize += 4096; 1358 char *tmp = (char *)nameexports; 1359 nameexports = (NameExport *)malloc(nameExportSize); 1360 memcpy(nameexports, tmp, nsize); 1361 curnameexport = (NameExport *)((ULONG)nameexports + nsize); 1362 free(tmp); 1363 } 1364 if(fAbsoluteAddress) {//forwarders use absolute address 1365 curnameexport->virtaddr = virtaddr; 1366 } 1367 else curnameexport->virtaddr = realBaseAddress + (virtaddr - oh.ImageBase); 1368 curnameexport->ordinal = ordinal; 1369 *(ULONG *)curnameexport->name = 0; 1370 strcpy(curnameexport->name, apiname); 1371 1372 curnameexport->nlength = strlen(apiname) + 1; 1373 if(curnameexport->nlength < sizeof(curnameexport->name)) 1374 curnameexport->nlength = sizeof(curnameexport->name); 1375 1376 curnameexport = (NameExport *)((ULONG)curnameexport->name + curnameexport->nlength); 1377 } 1378 //****************************************************************************** 1379 //****************************************************************************** 1380 void Win32PeLdrImage::AddOrdExport(ULONG virtaddr, ULONG ordinal, BOOL fAbsoluteAddress) 1381 { 1382 if(ordexports == NULL) { 1383 ordexports = (OrdExport *)malloc(nrOrdExports * sizeof(OrdExport)); 1384 curordexport = ordexports; 1385 } 1386 if(fAbsoluteAddress) {//forwarders use absolute address 1387 curordexport->virtaddr = virtaddr; 1388 } 1389 else curordexport->virtaddr = realBaseAddress + (virtaddr - oh.ImageBase); 1390 1391 curordexport->ordinal = ordinal; 1392 curordexport++; 1393 } 1394 //****************************************************************************** 1395 //****************************************************************************** 1396 BOOL Win32PeLdrImage::AddForwarder(ULONG virtaddr, char *apiname, ULONG ordinal) 1397 { 1398 char *forward = (char *)(realBaseAddress + (virtaddr - oh.ImageBase)); 1399 char *forwarddll, *forwardapi; 1400 Win32DllBase *WinDll; 1401 DWORD exportaddr; 1402 int forwardord; 1403 1404 forwarddll = strdup(forward); 1405 if(forwarddll == NULL) { 1406 return FALSE; 1407 } 1408 forwardapi = strchr(forwarddll, '.'); 1409 if(forwardapi == NULL) { 1410 goto fail; 1411 } 1412 *forwardapi++ = 0; 1413 if(strlen(forwarddll) == 0 || strlen(forwardapi) == 0) { 1414 goto fail; 1415 } 1416 WinDll = Win32DllBase::findModule(forwarddll); 1417 if(WinDll == NULL) { 1418 WinDll = loadDll(forwarddll); 1419 if(WinDll == NULL) { 1420 dprintf((LOG, "ERROR: couldn't find forwarder %s.%s", forwarddll, forwardapi)); 1421 goto fail; 1422 } 1423 } 1424 //check if name or ordinal forwarder 1408 ULONG nsize; 1409 int iApiNameLength = strlen(apiname); 1410 1411 if(nameexports == NULL) 1412 { 1413 nameExportSize= 4096; 1414 nameexports = (NameExport *)malloc(nameExportSize); 1415 curnameexport = nameexports; 1416 } 1417 1418 nsize = (ULONG)curnameexport - (ULONG)nameexports; 1419 if(nsize + sizeof(NameExport) + iApiNameLength > nameExportSize) 1420 { 1421 nameExportSize += 4096; 1422 char *tmp = (char *)nameexports; 1423 nameexports = (NameExport *)malloc(nameExportSize); 1424 memcpy(nameexports, tmp, nsize); 1425 curnameexport = (NameExport *)((ULONG)nameexports + nsize); 1426 free(tmp); 1427 } 1428 1429 if(fAbsoluteAddress) //forwarders use absolute address 1430 curnameexport->virtaddr = virtaddr; 1431 else 1432 curnameexport->virtaddr = realBaseAddress + (virtaddr - oh.ImageBase); 1433 1434 curnameexport->ordinal = ordinal; 1435 *(ULONG *)curnameexport->name = 0; 1436 strcpy(curnameexport->name, apiname); 1437 1438 curnameexport->nlength = iApiNameLength + 1; 1439 if(curnameexport->nlength < sizeof(curnameexport->name)) 1440 curnameexport->nlength = sizeof(curnameexport->name); 1441 1442 curnameexport = (NameExport *)((ULONG)curnameexport->name + curnameexport->nlength); 1443 } 1444 //****************************************************************************** 1445 //****************************************************************************** 1446 void Win32PeLdrImage::AddOrdExport(ULONG virtaddr, 1447 ULONG ordinal, 1448 BOOL fAbsoluteAddress) 1449 { 1450 if(ordexports == NULL) 1451 { 1452 ordexports = (OrdExport *)malloc(nrOrdExports * sizeof(OrdExport)); 1453 curordexport = ordexports; 1454 } 1455 1456 if(fAbsoluteAddress) //forwarders use absolute address 1457 curordexport->virtaddr = virtaddr; 1458 else 1459 curordexport->virtaddr = realBaseAddress + (virtaddr - oh.ImageBase); 1460 1461 curordexport->ordinal = ordinal; 1462 curordexport++; 1463 } 1464 //****************************************************************************** 1465 //****************************************************************************** 1466 BOOL Win32PeLdrImage::AddForwarder(ULONG virtaddr, 1467 char *apiname, 1468 ULONG ordinal) 1469 { 1470 char *forward = (char *)(realBaseAddress + (virtaddr - oh.ImageBase)); 1471 char *forwarddll, *forwardapi, *forwardapi0; 1472 Win32DllBase *WinDll; 1473 DWORD exportaddr; 1474 int forwardord; 1475 int iForwardApiLength; /* save strlen result */ 1476 1477 // 2001-06-01 PH 1478 // we do exactly know which character we replace: the "." is zeroed 1479 // so we can cheaply restore the name at the end of the method. 1480 // forwarddll = strdup(forward); 1481 // if(forwarddll == NULL) 1482 // { 1483 // return FALSE; 1484 // } 1485 forwarddll = forward; 1486 1487 forwardapi = strchr(forwarddll, '.'); 1488 if(forwardapi == NULL) 1489 { 1490 goto fail; 1491 } 1492 *forwardapi0 = 0; 1493 forwardapi=forwardapi0++; 1494 iForwardApiLength = strlen(forwardapi); 1495 1496 if(strlen(forwarddll) == 0 || iForwardApiLength == 0) 1497 { 1498 goto fail; 1499 } 1500 1501 WinDll = Win32DllBase::findModule(forwarddll); 1502 if(WinDll == NULL) 1503 { 1504 WinDll = loadDll(forwarddll); 1505 if(WinDll == NULL) 1506 { 1507 dprintf((LOG, "ERROR: couldn't find forwarder %s.%s", forwarddll, forwardapi)); 1508 goto fail; 1509 } 1510 } 1511 1512 //check if name or ordinal forwarder 1513 if(*forwardapi >= '0' && *forwardapi <= '9') 1514 { 1515 forwardord = atoi(forwardapi); 1516 } 1517 else 1425 1518 forwardord = 0; 1426 if(*forwardapi >= '0' && *forwardapi <= '9') { 1427 forwardord = atoi(forwardapi); 1428 } 1429 if(forwardord != 0 || (strlen(forwardapi) == 1 && *forwardapi == '0')) { 1430 exportaddr = WinDll->getApi(forwardord); 1431 } 1432 else exportaddr = WinDll->getApi(forwardapi); 1433 1434 if(apiname) { 1435 dprintf((LOG, "address 0x%x %s @%d (0x%08x) forwarder %s.%s", virtaddr - oh.ImageBase, apiname, ordinal, virtaddr, forwarddll, forwardapi)); 1436 AddNameExport(exportaddr, apiname, ordinal, TRUE); 1437 } 1438 else { 1439 dprintf((LOG, "address 0x%x @%d (0x%08x) forwarder %s.%s", virtaddr - oh.ImageBase, ordinal, virtaddr, forwarddll, forwardapi)); 1440 AddOrdExport(exportaddr, ordinal, TRUE); 1441 } 1442 free(forwarddll); 1443 return TRUE; 1444 1445 fail: 1446 free(forwarddll); 1519 1520 if(forwardord != 0 || (iForwardApiLength == 1 && *forwardapi == '0')) 1521 exportaddr = WinDll->getApi(forwardord); 1522 else 1523 exportaddr = WinDll->getApi(forwardapi); 1524 1525 if(apiname) 1526 { 1527 dprintf((LOG, "address 0x%x %s @%d (0x%08x) forwarder %s.%s", virtaddr - oh.ImageBase, apiname, ordinal, virtaddr, forwarddll, forwardapi)); 1528 AddNameExport(exportaddr, apiname, ordinal, TRUE); 1529 } 1530 else 1531 { 1532 dprintf((LOG, "address 0x%x @%d (0x%08x) forwarder %s.%s", virtaddr - oh.ImageBase, ordinal, virtaddr, forwarddll, forwardapi)); 1533 AddOrdExport(exportaddr, ordinal, TRUE); 1534 } 1535 1536 // free(forwarddll); 1537 *forwardapi0 = '.'; 1538 return TRUE; 1539 1540 fail: 1541 // free(forwarddll); 1542 *forwardapi0 = '.'; 1447 1543 return FALSE; 1448 1544 } … … 1451 1547 Win32DllBase *Win32PeLdrImage::loadDll(char *pszCurModule) 1452 1548 { 1549 PERF_START(loaddll) 1550 1453 1551 Win32DllBase *WinDll = NULL; 1454 1552 char modname[CCHMAXPATH]; … … 1538 1636 dprintf((LOG, "**********************************************************************" )); 1539 1637 1638 1639 PERF_ELAPSED(loaddll, "Win32PeLdrImage::loadDll", pszCurModule) 1640 1540 1641 return WinDll; 1541 1642 } … … 1550 1651 BOOL Win32PeLdrImage::processImports(char *win32file) 1551 1652 { 1653 PERF_START(processimports) 1654 1552 1655 PIMAGE_IMPORT_DESCRIPTOR pID; 1553 1656 IMAGE_SECTION_HEADER shID; … … 1773 1876 1774 1877 free(pszModules); 1878 1879 PERF_ELAPSED(processimports, "Win32PeLdrImage::processImports", getModuleName()) 1880 1775 1881 return TRUE; 1776 1882 } … … 1811 1917 NameExport *curexport; 1812 1918 ULONG ulAPIOrdinal; /* api requested by ordinal */ 1813 1919 1814 1920 apilen = strlen(name) + 1; 1815 1921 if(apilen < 4) … … 1828 1934 *(ULONG *)curexport->name == *(ULONG *)apiname) 1829 1935 { 1830 if(strcmp(curexport->name, apiname) == 0) 1831 return(curexport->virtaddr); 1936 if(strcmp(curexport->name, apiname) == 0) 1937 { 1938 return(curexport->virtaddr); 1939 } 1832 1940 } 1833 1941 curexport = (NameExport *)((ULONG)curexport->name + curexport->nlength); … … 1839 1947 ULONG Win32PeLdrImage::getApi(int ordinal) 1840 1948 { 1841 ULONG apiaddr, i; 1842 OrdExport *curexport; 1843 NameExport *nexport; 1844 1845 curexport = ordexports; 1846 for(i=0;i<nrOrdExports;i++) { 1847 if(curexport->ordinal == ordinal) 1848 return(curexport->virtaddr); 1849 curexport++; 1850 } 1851 //Name exports also contain an ordinal, so check this 1852 nexport = nameexports; 1853 for(i=0;i<nrNameExports;i++) { 1854 if(nexport->ordinal == ordinal) 1855 return(nexport->virtaddr); 1856 1857 nexport = (NameExport *)((ULONG)nexport->name + nexport->nlength); 1858 } 1859 return(0); 1949 ULONG apiaddr, i; 1950 OrdExport *curexport; 1951 NameExport *nexport; 1952 1953 curexport = ordexports; 1954 for(i=0;i<nrOrdExports;i++) 1955 { 1956 if(curexport->ordinal == ordinal) 1957 return(curexport->virtaddr); 1958 curexport++; 1959 } 1960 1961 //Name exports also contain an ordinal, so check this 1962 nexport = nameexports; 1963 for(i=0;i<nrNameExports;i++) 1964 { 1965 if(nexport->ordinal == ordinal) 1966 return(nexport->virtaddr); 1967 1968 nexport = (NameExport *)((ULONG)nexport->name + nexport->nlength); 1969 } 1970 return(0); 1860 1971 } 1861 1972 //******************************************************************************
Note:
See TracChangeset
for help on using the changeset viewer.