Changeset 56 for trunk/src/helpers/dosh2.c
- Timestamp:
- Apr 8, 2001, 9:17:16 AM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/dosh2.c
r55 r56 64 64 65 65 #include "helpers\dosh.h" 66 #include "helpers\ensure.h" 67 #include "helpers\standards.h" 66 68 #include "helpers\stringh.h" 67 69 … … 1236 1238 *@@added V0.9.9 (2001-03-11) [lafaix] 1237 1239 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1240 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code 1238 1241 */ 1239 1242 … … 1242 1245 PULONG pcModules) // out: array item count 1243 1246 { 1244 APIRET arc = NO_ERROR;1245 1246 1247 if ( (pExec) 1247 1248 && (pExec->ulOS == EXEOS_OS2) 1248 1249 ) 1249 1250 { 1251 ENSURE_BEGIN; 1250 1252 ULONG cModules = 0; 1251 1253 PFSYSMODULE paModules = NULL; … … 1255 1257 { 1256 1258 // 32-bit OS/2 executable: 1257 if (cModules = pExec->pLXHeader->ulImportModTblCnt) 1259 cModules = pExec->pLXHeader->ulImportModTblCnt; 1260 1261 if (cModules) 1258 1262 { 1259 1263 ULONG cb = sizeof(FSYSMODULE) * cModules; // V0.9.9 (2001-04-03) [umoeller] 1264 ULONG ulDummy; 1260 1265 1261 1266 paModules = (PFSYSMODULE)malloc(cb); 1262 1267 if (!paModules) 1263 arc = ERROR_NOT_ENOUGH_MEMORY; // V0.9.9 (2001-04-03) [umoeller] 1264 else 1268 ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY); // V0.9.9 (2001-04-03) [umoeller] 1269 1270 memset(paModules, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 1271 1272 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1273 pExec->pLXHeader->ulImportModTblOfs 1274 + pExec->pDosExeHeader->ulNewHeaderOfs, 1275 FILE_BEGIN, 1276 &ulDummy)); 1277 1278 for (i = 0; i < cModules; i++) 1265 1279 { 1266 ULONG ulDummy; 1267 1268 memset(paModules, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 1269 1270 // V0.9.9 (2001-04-03) [umoeller]: 1271 // Martin, I added error checking to all the below 1272 // Dos* calls. You can't just read around a file 1273 // and assume it will always be valid... especially 1274 // if you fill dynamically allocated memory. 1275 1276 if (!(arc = DosSetFilePtr(pExec->hfExe, 1277 pExec->pLXHeader->ulImportModTblOfs 1278 + pExec->pDosExeHeader->ulNewHeaderOfs, 1279 FILE_BEGIN, 1280 &ulDummy))) 1281 { 1282 for (i = 0; i < cModules; i++) 1283 { 1284 BYTE bLen = 0; 1285 1286 // reading the length of the module name 1287 if (!(arc = DosRead(pExec->hfExe, 1288 &bLen, 1289 1, 1290 &ulDummy))) 1291 { 1292 // At most 127 bytes 1293 bLen &= 0x7F; 1294 1295 // reading the module name 1296 if (!(arc = DosRead(pExec->hfExe, 1297 paModules[i].achModuleName, 1298 bLen, 1299 &ulDummy))) 1300 // module names are not null terminated, so we must 1301 // do it now 1302 paModules[i].achModuleName[bLen] = 0; 1303 } 1304 1305 if (arc) 1306 break; // V0.9.9 (2001-04-03) [umoeller] 1307 1308 } // end for 1309 } 1310 } 1280 BYTE bLen = 0; 1281 1282 // reading the length of the module name 1283 ENSURE_SAFE(DosRead(pExec->hfExe, &bLen, 1, &ulDummy)); 1284 1285 // At most 127 bytes 1286 bLen &= 0x7F; 1287 1288 // reading the module name 1289 ENSURE_SAFE(DosRead(pExec->hfExe, 1290 paModules[i].achModuleName, 1291 bLen, 1292 &ulDummy)); 1293 1294 // module names are not null terminated, so we must 1295 // do it now 1296 paModules[i].achModuleName[bLen] = 0; 1297 } // end for 1311 1298 } 1312 1299 } // end LX … … 1314 1301 { 1315 1302 // 16-bit OS/2 executable: 1316 if (cModules = pExec->pNEHeader->usModuleTblEntries) 1303 cModules = pExec->pNEHeader->usModuleTblEntries; 1304 1305 if (cModules) 1317 1306 { 1318 1307 ULONG cb = sizeof(FSYSMODULE) * cModules; … … 1320 1309 paModules = (PFSYSMODULE)malloc(cb); 1321 1310 if (!paModules) 1322 arc = ERROR_NOT_ENOUGH_MEMORY; // V0.9.9 (2001-04-03) [umoeller] 1323 else 1311 ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY); // V0.9.9 (2001-04-03) [umoeller] 1312 1313 memset(paModules, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 1314 1315 for (i = 0; i < cModules; i ++) 1324 1316 { 1325 memset(paModules, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 1326 1327 for (i = 0; i < cModules; i ++) 1328 { 1329 BYTE bLen; 1330 USHORT usOfs; 1331 ULONG ulDummy; 1332 1333 // the module reference table contains offsets 1334 // relative to the import table; we hence read 1335 // the offset in the module reference table, and 1336 // then we read the name in the import table 1337 1338 if ( (!(arc = DosSetFilePtr(pExec->hfExe, 1339 pExec->pNEHeader->usModRefTblOfs 1340 + pExec->pDosExeHeader->ulNewHeaderOfs 1341 + sizeof(usOfs) * i, 1342 FILE_BEGIN, 1343 &ulDummy))) 1344 && (!(arc = DosRead(pExec->hfExe, 1345 &usOfs, 1346 2, 1347 &ulDummy))) 1348 && (!(arc = DosSetFilePtr(pExec->hfExe, 1349 pExec->pNEHeader->usImportTblOfs 1350 + pExec->pDosExeHeader->ulNewHeaderOfs 1351 + usOfs, 1352 FILE_BEGIN, 1353 &ulDummy))) 1354 && (!(arc = DosRead(pExec->hfExe, 1355 &bLen, 1356 1, 1357 &ulDummy))) 1358 ) 1359 { 1360 bLen &= 0x7F; 1361 1362 if (!(arc = DosRead(pExec->hfExe, 1363 paModules[i].achModuleName, 1364 bLen, 1365 &ulDummy))) 1366 paModules[i].achModuleName[bLen] = 0; 1367 } 1368 1369 if (arc) 1370 break; // V0.9.9 (2001-04-03) [umoeller] 1371 } // end for 1372 } 1317 BYTE bLen; 1318 USHORT usOfs; 1319 ULONG ulDummy; 1320 1321 // the module reference table contains offsets 1322 // relative to the import table; we hence read 1323 // the offset in the module reference table, and 1324 // then we read the name in the import table 1325 1326 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1327 pExec->pNEHeader->usModRefTblOfs 1328 + pExec->pDosExeHeader->ulNewHeaderOfs 1329 + sizeof(usOfs) * i, 1330 FILE_BEGIN, 1331 &ulDummy)); 1332 1333 ENSURE_SAFE(DosRead(pExec->hfExe, &usOfs, 2, &ulDummy)); 1334 1335 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1336 pExec->pNEHeader->usImportTblOfs 1337 + pExec->pDosExeHeader->ulNewHeaderOfs 1338 + usOfs, 1339 FILE_BEGIN, 1340 &ulDummy)); 1341 1342 ENSURE_SAFE(DosRead(pExec->hfExe, &bLen, 1, &ulDummy)); 1343 1344 bLen &= 0x7F; 1345 1346 ENSURE_SAFE(DosRead(pExec->hfExe, 1347 paModules[i].achModuleName, 1348 bLen, 1349 &ulDummy)); 1350 1351 paModules[i].achModuleName[bLen] = 0; 1352 } // end for 1373 1353 } 1374 1354 } 1375 1355 else 1376 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller] 1377 1378 if (arc) 1379 { 1356 ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller] 1357 1358 // no error: output data 1359 *ppaModules = paModules; 1360 *pcModules = cModules; 1361 1362 ENSURE_FINALLY; 1380 1363 // if we had an error above, clean up 1381 if (paModules) 1382 free(paModules); 1383 } 1384 else 1385 { 1386 // no error: output data 1387 *ppaModules = paModules; 1388 *pcModules = cModules; 1389 } 1364 free(paModules); 1365 ENSURE_END; 1390 1366 } 1391 1367 else 1392 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller]1393 1394 return (arc);1368 ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller] 1369 1370 ENSURE_OK; 1395 1371 } 1396 1372 … … 1404 1380 APIRET doshExecFreeImportedModules(PFSYSMODULE paModules) 1405 1381 { 1406 if (paModules) // V0.9.9 (2001-04-04) [umoeller] 1407 free(paModules); 1382 free(paModules); 1408 1383 return (NO_ERROR); 1409 1384 } … … 1418 1393 *@@added V0.9.9 (2001-03-30) [lafaix] 1419 1394 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1395 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code 1420 1396 */ 1421 1397 … … 1424 1400 PULONG pcEntries) // out: entry table entry count; ptr can be NULL 1425 1401 { 1426 APIRET arc = NO_ERROR;1427 1428 1402 ULONG ulDummy; 1429 1430 if (!(arc = DosSetFilePtr(pExec->hfExe, 1431 pExec->pLXHeader->ulEntryTblOfs 1432 + pExec->pDosExeHeader->ulNewHeaderOfs, 1433 FILE_BEGIN, 1434 &ulDummy))) 1435 { 1436 USHORT usOrdinal = 1, 1437 usCurrent = 0; 1438 int i; 1439 1440 while (!arc) // V0.9.9 (2001-04-03) [umoeller] 1403 USHORT usOrdinal = 1, 1404 usCurrent = 0; 1405 int i; 1406 1407 ENSURE(DosSetFilePtr(pExec->hfExe, 1408 pExec->pLXHeader->ulEntryTblOfs 1409 + pExec->pDosExeHeader->ulNewHeaderOfs, 1410 FILE_BEGIN, 1411 &ulDummy)); 1412 1413 while (TRUE) 1414 { 1415 BYTE bCnt, 1416 bType, 1417 bFlag; 1418 1419 ENSURE(DosRead(pExec->hfExe, &bCnt, 1, &ulDummy)); 1420 1421 if (bCnt == 0) 1422 // end of the entry table 1423 break; 1424 1425 ENSURE(DosRead(pExec->hfExe, &bType, 1, &ulDummy)); 1426 1427 switch (bType & 0x7F) 1441 1428 { 1442 BYTE bCnt, 1443 bType, 1444 bFlag; 1445 1446 if (!(arc = DosRead(pExec->hfExe, 1447 &bCnt, 1448 1, 1449 &ulDummy))) 1450 { 1451 if (bCnt == 0) 1452 // end of the entry table 1453 break; 1454 1455 if (!(arc = DosRead(pExec->hfExe, 1456 &bType, 1457 1, 1458 &ulDummy))) 1429 /* 1430 * unused entries 1431 * 1432 */ 1433 1434 case 0: 1435 usOrdinal += bCnt; 1436 break; 1437 1438 /* 1439 * 16-bit entries 1440 * 1441 * the bundle type is followed by the object number 1442 * and by bCnt bFlag+usOffset entries 1443 * 1444 */ 1445 1446 case 1: 1447 ENSURE(DosSetFilePtr(pExec->hfExe, 1448 sizeof(USHORT), 1449 FILE_CURRENT, 1450 &ulDummy)); 1451 1452 for (i = 0; i < bCnt; i ++) 1459 1453 { 1460 switch (bType & 0x7F) 1454 ENSURE(DosRead(pExec->hfExe, &bFlag, 1, &ulDummy)); 1455 1456 if (bFlag & 0x01) 1461 1457 { 1462 /* 1463 * unused entries 1464 * 1465 */ 1466 1467 case 0: 1468 usOrdinal += bCnt; 1469 break; 1470 1471 /* 1472 * 16-bit entries 1473 * 1474 * the bundle type is followed by the object number 1475 * and by bCnt bFlag+usOffset entries 1476 * 1477 */ 1478 1479 case 1: 1480 if (!(arc = DosSetFilePtr(pExec->hfExe, 1481 sizeof(USHORT), 1482 FILE_CURRENT, 1483 &ulDummy))) 1484 { 1485 for (i = 0; i < bCnt; i ++) 1486 { 1487 if (!(arc = DosRead(pExec->hfExe, 1488 &bFlag, 1489 1, 1490 &ulDummy))) 1491 { 1492 if (bFlag & 0x01) 1493 { 1494 if (paFunctions) 1495 { 1496 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1497 paFunctions[usCurrent].ulType = 1; 1498 paFunctions[usCurrent].achFunctionName[0] = 0; 1499 } 1500 usCurrent++; 1501 } 1502 1503 usOrdinal++; 1504 1505 arc = DosSetFilePtr(pExec->hfExe, 1506 sizeof(USHORT), 1507 FILE_CURRENT, 1508 &ulDummy); 1509 } 1510 1511 if (arc) 1512 break; // V0.9.9 (2001-04-03) [umoeller] 1513 1514 } // end for 1515 } 1516 break; 1517 1518 /* 1519 * 286 call gate entries 1520 * 1521 * the bundle type is followed by the object number 1522 * and by bCnt bFlag+usOffset+usCallGate entries 1523 * 1524 */ 1525 1526 case 2: 1527 if (!(arc = DosSetFilePtr(pExec->hfExe, 1528 sizeof(USHORT), 1529 FILE_CURRENT, 1530 &ulDummy))) 1531 { 1532 for (i = 0; i < bCnt; i ++) 1533 { 1534 if (!(arc = DosRead(pExec->hfExe, 1535 &bFlag, 1536 1, 1537 &ulDummy))) 1538 { 1539 if (bFlag & 0x01) 1540 { 1541 if (paFunctions) 1542 { 1543 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1544 paFunctions[usCurrent].ulType = 2; 1545 paFunctions[usCurrent].achFunctionName[0] = 0; 1546 } 1547 usCurrent++; 1548 } 1549 1550 usOrdinal++; 1551 1552 arc = DosSetFilePtr(pExec->hfExe, 1553 sizeof(USHORT) + sizeof(USHORT), 1554 FILE_CURRENT, 1555 &ulDummy); 1556 } 1557 1558 if (arc) 1559 break; // V0.9.9 (2001-04-03) [umoeller] 1560 1561 } // end for 1562 } 1563 break; 1564 1565 /* 1566 * 32-bit entries 1567 * 1568 * the bundle type is followed by the object number 1569 * and by bCnt bFlag+ulOffset entries 1570 * 1571 */ 1572 1573 case 3: 1574 if (!(arc = DosSetFilePtr(pExec->hfExe, 1575 sizeof(USHORT), 1576 FILE_CURRENT, 1577 &ulDummy))) 1578 { 1579 for (i = 0; i < bCnt; i ++) 1580 { 1581 if (!(arc = DosRead(pExec->hfExe, 1582 &bFlag, 1583 1, 1584 &ulDummy))) 1585 { 1586 if (bFlag & 0x01) 1587 { 1588 if (paFunctions) 1589 { 1590 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1591 paFunctions[usCurrent].ulType = 3; 1592 paFunctions[usCurrent].achFunctionName[0] = 0; 1593 } 1594 usCurrent++; 1595 } 1596 1597 usOrdinal++; 1598 1599 arc = DosSetFilePtr(pExec->hfExe, 1600 sizeof(ULONG), 1601 FILE_CURRENT, 1602 &ulDummy); 1603 } 1604 1605 if (arc) 1606 break; // V0.9.9 (2001-04-03) [umoeller] 1607 } // end for 1608 } 1609 break; 1610 1611 /* 1612 * forwarder entries 1613 * 1614 * the bundle type is followed by a reserved word 1615 * and by bCnt bFlag+usModOrd+ulOffsOrdNum entries 1616 * 1617 */ 1618 1619 case 4: 1620 if (!(arc = DosSetFilePtr(pExec->hfExe, 1621 sizeof(USHORT), 1622 FILE_CURRENT, 1623 &ulDummy))) 1624 { 1625 for (i = 0; i < bCnt; i ++) 1626 { 1627 if (!(arc = DosSetFilePtr(pExec->hfExe, 1628 sizeof(BYTE) + sizeof(USHORT) + sizeof(ULONG), 1629 FILE_CURRENT, 1630 &ulDummy))) 1631 { 1632 if (paFunctions) 1633 { 1634 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1635 paFunctions[usCurrent].ulType = 4; 1636 paFunctions[usCurrent].achFunctionName[0] = 0; 1637 } 1638 usCurrent++; 1639 1640 usOrdinal++; 1641 } 1642 1643 if (arc) 1644 break; // V0.9.9 (2001-04-03) [umoeller] 1645 } // end for 1646 } 1647 break; 1648 1649 /* 1650 * unknown bundle type 1651 * 1652 * we don't know how to handle this bundle, so we must 1653 * stop parsing the entry table here (as we don't know the 1654 * bundle size); if paFunctions is not null, we fill it with 1655 * informative data 1656 */ 1657 1658 default: 1659 if (paFunctions) 1660 { 1661 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1662 paFunctions[usCurrent].ulType = bType; 1663 sprintf(paFunctions[usCurrent].achFunctionName, 1664 "Unknown bundle type encountered (%d). Aborting entry table scan.", 1665 bType); 1666 1667 arc = ERROR_INVALID_LIST_FORMAT; 1668 // whatever 1669 // V0.9.9 (2001-04-03) [umoeller] 1670 } 1671 1672 usCurrent++; 1673 } // end switch (bType & 0x7F) 1458 if (paFunctions) 1459 { 1460 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1461 paFunctions[usCurrent].ulType = 1; 1462 paFunctions[usCurrent].achFunctionName[0] = 0; 1463 } 1464 usCurrent++; 1465 } 1466 1467 usOrdinal++; 1468 1469 ENSURE(DosSetFilePtr(pExec->hfExe, 1470 sizeof(USHORT), 1471 FILE_CURRENT, 1472 &ulDummy)); 1473 1474 } // end for 1475 break; 1476 1477 /* 1478 * 286 call gate entries 1479 * 1480 * the bundle type is followed by the object number 1481 * and by bCnt bFlag+usOffset+usCallGate entries 1482 * 1483 */ 1484 1485 case 2: 1486 ENSURE(DosSetFilePtr(pExec->hfExe, 1487 sizeof(USHORT), 1488 FILE_CURRENT, 1489 &ulDummy)); 1490 1491 for (i = 0; i < bCnt; i ++) 1492 { 1493 ENSURE(DosRead(pExec->hfExe, &bFlag, 1, &ulDummy)); 1494 1495 if (bFlag & 0x01) 1496 { 1497 if (paFunctions) 1498 { 1499 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1500 paFunctions[usCurrent].ulType = 2; 1501 paFunctions[usCurrent].achFunctionName[0] = 0; 1502 } 1503 usCurrent++; 1504 } 1505 1506 usOrdinal++; 1507 1508 ENSURE(DosSetFilePtr(pExec->hfExe, 1509 sizeof(USHORT) + sizeof(USHORT), 1510 FILE_CURRENT, 1511 &ulDummy)); 1512 1513 } // end for 1514 break; 1515 1516 /* 1517 * 32-bit entries 1518 * 1519 * the bundle type is followed by the object number 1520 * and by bCnt bFlag+ulOffset entries 1521 * 1522 */ 1523 1524 case 3: 1525 ENSURE(DosSetFilePtr(pExec->hfExe, 1526 sizeof(USHORT), 1527 FILE_CURRENT, 1528 &ulDummy)); 1529 1530 for (i = 0; i < bCnt; i ++) 1531 { 1532 ENSURE(DosRead(pExec->hfExe, &bFlag, 1, &ulDummy)); 1533 1534 if (bFlag & 0x01) 1535 { 1536 if (paFunctions) 1537 { 1538 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1539 paFunctions[usCurrent].ulType = 3; 1540 paFunctions[usCurrent].achFunctionName[0] = 0; 1541 } 1542 usCurrent++; 1543 } 1544 1545 usOrdinal++; 1546 1547 ENSURE(DosSetFilePtr(pExec->hfExe, 1548 sizeof(ULONG), 1549 FILE_CURRENT, 1550 &ulDummy)); 1551 } // end for 1552 break; 1553 1554 /* 1555 * forwarder entries 1556 * 1557 * the bundle type is followed by a reserved word 1558 * and by bCnt bFlag+usModOrd+ulOffsOrdNum entries 1559 * 1560 */ 1561 1562 case 4: 1563 ENSURE(DosSetFilePtr(pExec->hfExe, 1564 sizeof(USHORT), 1565 FILE_CURRENT, 1566 &ulDummy)); 1567 1568 for (i = 0; i < bCnt; i ++) 1569 { 1570 ENSURE(DosSetFilePtr(pExec->hfExe, 1571 sizeof(BYTE) + sizeof(USHORT) + sizeof(ULONG), 1572 FILE_CURRENT, 1573 &ulDummy)); 1574 1575 if (paFunctions) 1576 { 1577 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1578 paFunctions[usCurrent].ulType = 4; 1579 paFunctions[usCurrent].achFunctionName[0] = 0; 1580 } 1581 usCurrent++; 1582 1583 usOrdinal++; 1584 } // end for 1585 break; 1586 1587 /* 1588 * unknown bundle type 1589 * 1590 * we don't know how to handle this bundle, so we must 1591 * stop parsing the entry table here (as we don't know the 1592 * bundle size); if paFunctions is not null, we fill it with 1593 * informative data 1594 */ 1595 1596 default: 1597 if (paFunctions) 1598 { 1599 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1600 paFunctions[usCurrent].ulType = bType; 1601 sprintf(paFunctions[usCurrent].achFunctionName, 1602 "Unknown bundle type encountered (%d). Aborting entry table scan.", 1603 bType); 1604 1605 usCurrent++; 1674 1606 } 1675 } 1676 } // end while (!arc) 1677 1678 if (!arc) 1679 if (pcEntries) 1680 *pcEntries = usCurrent; 1681 } 1682 1683 return (arc); 1607 ENSURE_FAIL(ERROR_INVALID_LIST_FORMAT); 1608 // whatever 1609 // V0.9.9 (2001-04-03) [umoeller] 1610 } // end switch (bType & 0x7F) 1611 } // end while (TRUE) 1612 1613 if (pcEntries) 1614 *pcEntries = usCurrent; 1615 1616 ENSURE_OK; 1684 1617 } 1685 1618 … … 1693 1626 *@@added V0.9.9 (2001-03-30) [lafaix] 1694 1627 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1628 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code 1695 1629 */ 1696 1630 … … 1699 1633 PULONG pcEntries) // out: entry table entry count; ptr can be NULL 1700 1634 { 1701 APIRET arc = NO_ERROR;1702 1635 ULONG ulDummy; 1703 1704 if (!(arc = DosSetFilePtr(pExec->hfExe, 1705 pExec->pNEHeader->usEntryTblOfs 1706 + pExec->pDosExeHeader->ulNewHeaderOfs, 1707 FILE_BEGIN, 1708 &ulDummy))) 1709 { 1710 USHORT usOrdinal = 1, 1711 usCurrent = 0; 1712 int i; 1713 1714 while (!arc) // V0.9.9 (2001-04-03) [umoeller] 1636 USHORT usOrdinal = 1, 1637 usCurrent = 0; 1638 int i; 1639 1640 ENSURE(DosSetFilePtr(pExec->hfExe, 1641 pExec->pNEHeader->usEntryTblOfs 1642 + pExec->pDosExeHeader->ulNewHeaderOfs, 1643 FILE_BEGIN, 1644 &ulDummy)); 1645 1646 while (TRUE) 1647 { 1648 BYTE bCnt, 1649 bType, 1650 bFlag; 1651 1652 ENSURE(DosRead(pExec->hfExe, &bCnt, 1, &ulDummy)); 1653 1654 if (bCnt == 0) 1655 // end of the entry table 1656 break; 1657 1658 ENSURE(DosRead(pExec->hfExe, &bType, 1, &ulDummy)); 1659 1660 for (i = 0; i < bCnt; i++) 1715 1661 { 1716 BYTE bCnt, 1717 bType, 1718 bFlag; 1719 1720 if (!(arc = DosRead(pExec->hfExe, 1721 &bCnt, 1722 1, 1723 &ulDummy))) 1662 ENSURE(DosRead(pExec->hfExe, 1663 &bFlag, 1664 1, 1665 &ulDummy)); 1666 1667 if (bFlag & 0x01) 1724 1668 { 1725 if (bCnt == 0) 1726 // end of the entry table 1727 break; 1728 1729 if (!(arc = DosRead(pExec->hfExe, 1730 &bType, 1731 1, 1732 &ulDummy))) 1669 if (paFunctions) 1733 1670 { 1734 for (i = 0; i < bCnt; i++) 1735 { 1736 if (!(arc = DosRead(pExec->hfExe, 1737 &bFlag, 1738 1, 1739 &ulDummy))) 1740 { 1741 if (bFlag & 0x01) 1742 { 1743 if (paFunctions) 1744 { 1745 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1746 paFunctions[usCurrent].ulType = 1; // 16-bit entry 1747 paFunctions[usCurrent].achFunctionName[0] = 0; 1748 } 1749 usCurrent++; 1750 } 1751 1752 usOrdinal++; 1753 1754 if (bType == 0xFF) 1755 // moveable segment 1756 arc = DosSetFilePtr(pExec->hfExe, 1757 5, 1758 FILE_CURRENT, 1759 &ulDummy); 1760 else 1761 // fixed segment 1762 arc = DosSetFilePtr(pExec->hfExe, 1763 2, 1764 FILE_CURRENT, 1765 &ulDummy); 1766 } 1767 1768 if (arc) 1769 break; // V0.9.9 (2001-04-03) [umoeller] 1770 1771 } // end for 1671 paFunctions[usCurrent].ulOrdinal = usOrdinal; 1672 paFunctions[usCurrent].ulType = 1; // 16-bit entry 1673 paFunctions[usCurrent].achFunctionName[0] = 0; 1772 1674 } 1675 usCurrent++; 1773 1676 } 1774 } // end while (!arc) 1775 1776 if (!arc) 1777 if (pcEntries) 1778 *pcEntries = usCurrent; 1779 } 1780 1781 return (arc); 1677 1678 usOrdinal++; 1679 1680 if (bType == 0xFF) 1681 { 1682 // moveable segment 1683 ENSURE(DosSetFilePtr(pExec->hfExe, 1684 5, 1685 FILE_CURRENT, 1686 &ulDummy)); 1687 } 1688 else 1689 { 1690 // fixed segment 1691 ENSURE(DosSetFilePtr(pExec->hfExe, 1692 2, 1693 FILE_CURRENT, 1694 &ulDummy)); 1695 } 1696 1697 } // end for 1698 } // end while (TRUE) 1699 1700 if (pcEntries) 1701 *pcEntries = usCurrent; 1702 1703 ENSURE_OK; 1782 1704 } 1783 1705 … … 1787 1709 * 1788 1710 *@@added V0.9.9 (2001-04-01) [lafaix] 1711 *@@changed V0.9.9 (2001-04-07) [umoeller]: added _Optlink, or this won't compile as C++ 1789 1712 */ 1790 1713 … … 1814 1737 *@@changed V0.9.9 (2001-04-02) [lafaix]: the first entry is special 1815 1738 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1739 *@@changed V0.9.9 (2001-04-05) [lafaix]: removed the 127 char limit 1740 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code 1816 1741 */ 1817 1742 … … 1820 1745 PFSYSFUNCTION paFunctions) 1821 1746 { 1822 APIRET arc = NO_ERROR;1823 1747 ULONG ulDummy; 1824 1748 1825 1749 USHORT usOrdinal; 1826 1750 PFSYSFUNCTION pFunction; 1827 BOOL bFirst = TRUE; 1828 1829 while (!arc) // V0.9.9 (2001-04-03) [umoeller] 1751 1752 while (TRUE) 1830 1753 { 1831 1754 BYTE bLen; … … 1833 1756 int i; 1834 1757 1835 if (!(arc = DosRead(pExec->hfExe, 1836 &bLen, 1837 1, 1838 &ulDummy))) 1758 ENSURE(DosRead(pExec->hfExe, &bLen, 1, &ulDummy)); 1759 1760 if (bLen == 0) 1761 // end of the name table 1762 break; 1763 1764 ENSURE(DosRead(pExec->hfExe, &achName, bLen, &ulDummy)); 1765 achName[bLen] = 0; 1766 1767 ENSURE(DosRead(pExec->hfExe, &usOrdinal, sizeof(USHORT), &ulDummy)); 1768 1769 if ((pFunction = (PFSYSFUNCTION)bsearch(&usOrdinal, 1770 paFunctions, 1771 cFunctions, 1772 sizeof(FSYSFUNCTION), 1773 Compare))) 1839 1774 { 1840 if (bLen == 0) 1841 // end of the name table 1842 break; 1843 1844 // the LX docs says that len is limited to 127 (the 8th bit being 1845 // reserved for future use); but does this applies to 16bits 1846 // tables too? 1847 // in any case, we must skip the first entry (module name in the 1848 // resident name table, and module description in non-resident 1849 // name table) 1850 if (bFirst) 1851 bFirst = FALSE; 1852 else 1853 bLen &= 0x7F; 1854 1855 if (!(arc = DosRead(pExec->hfExe, 1856 &achName, 1857 bLen, 1858 &ulDummy))) 1859 { 1860 achName[bLen] = 0; 1861 1862 if (!(arc = DosRead(pExec->hfExe, 1863 &usOrdinal, 1864 sizeof(USHORT), 1865 &ulDummy))) 1866 { 1867 if ((pFunction = (PFSYSFUNCTION)bsearch(&usOrdinal, 1868 paFunctions, 1869 cFunctions, 1870 sizeof(FSYSFUNCTION), 1871 Compare))) 1872 { 1873 memcpy(pFunction->achFunctionName, 1874 achName, 1875 bLen+1); 1876 } 1877 } 1878 } 1775 memcpy(pFunction->achFunctionName, 1776 achName, 1777 bLen+1); 1879 1778 } 1880 1779 } 1881 1780 1882 return (arc);1781 ENSURE_OK; 1883 1782 } 1884 1783 … … 1911 1810 *@@added V0.9.9 (2001-03-11) [lafaix] 1912 1811 *@@changed V0.9.9 (2001-04-03) [umoeller]: added tons of error checking, changed prototype to return APIRET 1812 *@@changed V0.9.9 (2001-04-05) [lafaix]: rewritten error checking code 1913 1813 */ 1914 1814 … … 1917 1817 PULONG pcFunctions) // out: array item count 1918 1818 { 1919 APIRET arc = NO_ERROR;1920 1921 1819 if ( (pExec) 1922 1820 && (pExec->ulOS == EXEOS_OS2) 1923 1821 ) 1924 1822 { 1823 ENSURE_BEGIN; 1925 1824 ULONG cFunctions = 0; 1926 1825 PFSYSFUNCTION paFunctions = NULL; … … 1936 1835 // the entry table 1937 1836 1938 if (!(arc = ScanLXEntryTable(pExec, 1939 NULL, 1940 &cFunctions))) 1837 ENSURE(ScanLXEntryTable(pExec, NULL, &cFunctions)); 1838 1839 // we now have the number of exported entries; let us 1840 // build them 1841 1842 if (cFunctions) 1941 1843 { 1942 // we now have the number of exported entries; let us 1943 // build them 1944 1945 if (cFunctions) 1946 { 1947 ULONG cb = sizeof(FSYSFUNCTION) * cFunctions; 1948 1949 paFunctions = (PFSYSFUNCTION)malloc(cb); 1950 if (!paFunctions) 1951 arc = ERROR_NOT_ENOUGH_MEMORY; // V0.9.9 (2001-04-03) [umoeller] 1952 else 1953 { 1954 // we rescan the entry table (the cost is not as bad 1955 // as it may seem, due to disk caching) 1956 1957 if ( (!(arc = ScanLXEntryTable(pExec, paFunctions, NULL))) 1958 // we now scan the resident name table entries 1959 && (!(arc = DosSetFilePtr(pExec->hfExe, 1960 pExec->pLXHeader->ulResdNameTblOfs 1961 + pExec->pDosExeHeader->ulNewHeaderOfs, 1962 FILE_BEGIN, 1963 &ulDummy))) 1964 && (!(arc = ScanNameTable(pExec, cFunctions, paFunctions))) 1965 // we now scan the non-resident name table entries, 1966 // whose offset is _from the begining of the file_ 1967 && (!(arc = DosSetFilePtr(pExec->hfExe, 1968 pExec->pLXHeader->ulNonResdNameTblOfs, 1969 FILE_BEGIN, 1970 &ulDummy))) 1971 ) 1972 { 1973 arc = ScanNameTable(pExec, cFunctions, paFunctions); 1974 } 1975 } 1976 } // end if (cFunctions) 1977 } 1844 ULONG cb = sizeof(FSYSFUNCTION) * cFunctions; 1845 1846 paFunctions = (PFSYSFUNCTION)malloc(cb); 1847 if (!paFunctions) 1848 ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY); 1849 1850 // we rescan the entry table (the cost is not as bad 1851 // as it may seem, due to disk caching) 1852 1853 ENSURE_SAFE(ScanLXEntryTable(pExec, paFunctions, NULL)); 1854 1855 // we now scan the resident name table entries 1856 1857 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1858 pExec->pLXHeader->ulResdNameTblOfs 1859 + pExec->pDosExeHeader->ulNewHeaderOfs, 1860 FILE_BEGIN, 1861 &ulDummy)); 1862 1863 ENSURE_SAFE(ScanNameTable(pExec, cFunctions, paFunctions)); 1864 1865 // we now scan the non-resident name table entries, 1866 // whose offset is _from the begining of the file_ 1867 1868 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1869 pExec->pLXHeader->ulNonResdNameTblOfs, 1870 FILE_BEGIN, 1871 &ulDummy)); 1872 1873 ENSURE_SAFE(ScanNameTable(pExec, cFunctions, paFunctions)); 1874 } // end if (cFunctions) 1978 1875 } 1979 1876 else if (pExec->ulExeFormat == EXEFORMAT_NE) … … 1985 1882 // have to count them in the entry table 1986 1883 1987 if (!(arc = ScanNEEntryTable(pExec, 1988 NULL, 1989 &cFunctions))) 1884 ENSURE(ScanNEEntryTable(pExec, NULL, &cFunctions)); 1885 1886 // we now have the number of exported entries; let us 1887 // build them 1888 1889 if (cFunctions) 1990 1890 { 1991 // we now have the number of exported entries; let us 1992 // build them 1993 1994 if (cFunctions) 1995 { 1996 USHORT usOrdinal = 1, 1997 usCurrent = 0; 1998 1999 paFunctions = (PFSYSFUNCTION)malloc(sizeof(FSYSFUNCTION) * cFunctions); 2000 if (!paFunctions) 2001 arc = ERROR_NOT_ENOUGH_MEMORY; 2002 else 2003 { 2004 // we rescan the entry table (the cost is not as bad 2005 // as it may seem, due to disk caching) 2006 2007 if ( (!(arc = ScanNEEntryTable(pExec, paFunctions, NULL))) 2008 // we now scan the resident name table entries 2009 && (!(arc = DosSetFilePtr(pExec->hfExe, 2010 pExec->pNEHeader->usResdNameTblOfs 2011 + pExec->pDosExeHeader->ulNewHeaderOfs, 2012 FILE_BEGIN, 2013 &ulDummy))) 2014 && (!(arc = ScanNameTable(pExec, cFunctions, paFunctions))) 2015 // we now scan the non-resident name table entries, 2016 // whose offset is _from the begining of the file_ 2017 && (!(arc = DosSetFilePtr(pExec->hfExe, 2018 pExec->pNEHeader->ulNonResdTblOfs, 2019 FILE_BEGIN, 2020 &ulDummy))) 2021 ) 2022 { 2023 arc = ScanNameTable(pExec, cFunctions, paFunctions); 2024 } 2025 } 2026 } 1891 USHORT usOrdinal = 1, 1892 usCurrent = 0; 1893 1894 paFunctions = (PFSYSFUNCTION)malloc(sizeof(FSYSFUNCTION) * cFunctions); 1895 if (!paFunctions) 1896 ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY); 1897 1898 // we rescan the entry table (the cost is not as bad 1899 // as it may seem, due to disk caching) 1900 1901 ENSURE_SAFE(ScanNEEntryTable(pExec, paFunctions, NULL)); 1902 1903 // we now scan the resident name table entries 1904 1905 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1906 pExec->pNEHeader->usResdNameTblOfs 1907 + pExec->pDosExeHeader->ulNewHeaderOfs, 1908 FILE_BEGIN, 1909 &ulDummy)); 1910 1911 ENSURE_SAFE(ScanNameTable(pExec, cFunctions, paFunctions)); 1912 1913 // we now scan the non-resident name table entries, 1914 // whose offset is _from the begining of the file_ 1915 1916 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 1917 pExec->pNEHeader->ulNonResdTblOfs, 1918 FILE_BEGIN, 1919 &ulDummy)); 1920 1921 ENSURE_SAFE(ScanNameTable(pExec, cFunctions, paFunctions)); 2027 1922 } 2028 1923 } 2029 1924 else 2030 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller] 2031 2032 if (arc) // V0.9.9 (2001-04-03) [umoeller] 2033 { 1925 ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller] 1926 1927 // no error: output data 1928 *ppaFunctions = paFunctions; 1929 *pcFunctions = cFunctions; 1930 1931 ENSURE_FINALLY; 2034 1932 // if we had an error above, clean up 2035 if (paFunctions) 2036 free(paFunctions); 2037 } 2038 else 2039 { 2040 // no error: output data 2041 *ppaFunctions = paFunctions; 2042 *pcFunctions = cFunctions; 2043 } 1933 free(paFunctions); 1934 ENSURE_END; 2044 1935 } 2045 1936 else 2046 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller]2047 2048 return (arc);1937 ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller] 1938 1939 ENSURE_OK; 2049 1940 } 2050 1941 … … 2058 1949 APIRET doshExecFreeExportedFunctions(PFSYSFUNCTION paFunctions) 2059 1950 { 2060 if (paFunctions) // V0.9.9 (2001-04-04) [umoeller]2061 free(paFunctions); 1951 free(paFunctions); 1952 2062 1953 return (NO_ERROR); 2063 1954 } … … 2091 1982 PULONG pcResources) // out: array item count 2092 1983 { 2093 APIRET arc = NO_ERROR;2094 2095 1984 if ( (pExec) 2096 1985 && (pExec->ulOS == EXEOS_OS2) 2097 1986 ) 2098 1987 { 1988 ENSURE_BEGIN; 2099 1989 ULONG cResources = 0; 2100 1990 PFSYSRESOURCE paResources = NULL; … … 2103 1993 { 2104 1994 // 32-bit OS/2 executable: 2105 if (cResources = pExec->pLXHeader->ulResTblCnt) 1995 cResources = pExec->pLXHeader->ulResTblCnt; 1996 1997 if (cResources) 2106 1998 { 1999 #pragma pack(1) // V0.9.9 (2001-04-02) [umoeller] 2000 struct rsrc32 /* Resource Table Entry */ 2001 { 2002 unsigned short type; /* Resource type */ 2003 unsigned short name; /* Resource name */ 2004 unsigned long cb; /* Resource size */ 2005 unsigned short obj; /* Object number */ 2006 unsigned long offset; /* Offset within object */ 2007 } rs; 2008 2009 struct o32_obj /* Flat .EXE object table entry */ 2010 { 2011 unsigned long o32_size; /* Object virtual size */ 2012 unsigned long o32_base; /* Object base virtual address */ 2013 unsigned long o32_flags; /* Attribute flags */ 2014 unsigned long o32_pagemap; /* Object page map index */ 2015 unsigned long o32_mapsize; /* Number of entries in object page map */ 2016 unsigned long o32_reserved; /* Reserved */ 2017 } ot; 2018 #pragma pack() // V0.9.9 (2001-04-03) [umoeller] 2019 2107 2020 ULONG cb = sizeof(FSYSRESOURCE) * cResources; 2021 ULONG ulDummy; 2022 int i; 2023 2108 2024 paResources = (PFSYSRESOURCE)malloc(cb); 2109 2025 if (!paResources) 2110 arc = ERROR_NOT_ENOUGH_MEMORY; 2111 else 2026 ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY); 2027 2028 memset(paResources, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 2029 2030 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 2031 pExec->pLXHeader->ulResTblOfs 2032 + pExec->pDosExeHeader->ulNewHeaderOfs, 2033 FILE_BEGIN, 2034 &ulDummy)); 2035 2036 for (i = 0; i < cResources; i++) 2112 2037 { 2113 ULONG ulDummy; 2114 2115 memset(paResources, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 2116 2117 // V0.9.9 (2001-04-03) [umoeller]: 2118 // Martin, I added error checking to all the below 2119 // Dos* calls. You can't just read around a file 2120 // and assume it will always be valid... especially 2121 // if you fill dynamically allocated memory. 2122 if (!(arc = DosSetFilePtr(pExec->hfExe, 2123 pExec->pLXHeader->ulResTblOfs 2124 + pExec->pDosExeHeader->ulNewHeaderOfs, 2125 FILE_BEGIN, 2126 &ulDummy))) 2127 { 2128 int i; 2129 2130 // V0.9.9 (2001-04-03) [umoeller]: 2131 // Besides, packing was missing. 2132 #pragma pack(1) // V0.9.9 (2001-04-02) [umoeller] 2133 struct rsrc32 /* Resource Table Entry */ 2134 { 2135 unsigned short type; /* Resource type */ 2136 unsigned short name; /* Resource name */ 2137 unsigned long cb; /* Resource size */ 2138 unsigned short obj; /* Object number */ 2139 unsigned long offset; /* Offset within object */ 2140 } rs; 2141 2142 struct o32_obj /* Flat .EXE object table entry */ 2143 { 2144 unsigned long o32_size; /* Object virtual size */ 2145 unsigned long o32_base; /* Object base virtual address */ 2146 unsigned long o32_flags; /* Attribute flags */ 2147 unsigned long o32_pagemap; /* Object page map index */ 2148 unsigned long o32_mapsize; /* Number of entries in object page map */ 2149 unsigned long o32_reserved; /* Reserved */ 2150 } ot; 2151 #pragma pack() // V0.9.9 (2001-04-03) [umoeller] 2152 2153 for (i = 0; i < cResources; i++) 2154 { 2155 arc = DosRead(pExec->hfExe, 2156 &rs, 2157 14, 2158 &ulDummy); 2159 if (arc) 2160 break; // V0.9.9 (2001-04-03) [umoeller] 2161 else 2162 { 2163 paResources[i].ulID = rs.name; 2164 paResources[i].ulType = rs.type; 2165 paResources[i].ulSize = rs.cb; 2166 paResources[i].ulFlag = rs.obj; // Temp storage for Object 2167 // number. Will be filled 2168 // with resource flag 2169 // later. 2170 } 2171 } 2172 2173 if (!arc) // V0.9.9 (2001-04-03) [umoeller] 2174 { 2175 for (i = 0; i < cResources; i++) 2176 { 2177 ULONG ulOfsThis 2178 = pExec->pLXHeader->ulObjTblOfs 2038 ENSURE_SAFE(DosRead(pExec->hfExe, &rs, 14, &ulDummy)); 2039 2040 paResources[i].ulID = rs.name; 2041 paResources[i].ulType = rs.type; 2042 paResources[i].ulSize = rs.cb; 2043 paResources[i].ulFlag = rs.obj; // Temp storage for Object 2044 // number. Will be filled 2045 // with resource flag 2046 // later. 2047 } 2048 2049 for (i = 0; i < cResources; i++) 2050 { 2051 ULONG ulOfsThis = pExec->pLXHeader->ulObjTblOfs 2179 2052 + pExec->pDosExeHeader->ulNewHeaderOfs 2180 2053 + ( sizeof(ot) 2181 2054 * (paResources[i].ulFlag - 1)); 2182 2055 2183 if (!(arc = DosSetFilePtr(pExec->hfExe, 2184 ulOfsThis, 2185 FILE_BEGIN, 2186 &ulDummy))) 2187 { 2188 if (!(arc = DosRead(pExec->hfExe, 2189 &ot, 2190 sizeof(ot), 2191 &ulDummy))) 2192 { 2193 paResources[i].ulFlag = ((ot.o32_flags & OBJWRITE) 2194 ? 0 2195 : RNPURE); 2196 paResources[i].ulFlag |= ((ot.o32_flags & OBJDISCARD) 2197 ? 4096 2198 : 0); 2199 paResources[i].ulFlag |= ((ot.o32_flags & OBJSHARED) 2200 ? RNMOVE 2201 : 0); 2202 paResources[i].ulFlag |= ((ot.o32_flags & OBJPRELOAD) 2203 ? RNPRELOAD 2204 : 0); 2205 } 2206 } 2207 2208 if (arc) 2209 break; // V0.9.9 (2001-04-03) [umoeller] 2210 } // end for 2211 } 2212 } // end if !DosSetFilePtr(pExec->hfExe, 2213 } // end if paResources = (PFSYSRESOURCE)malloc(sizeof(FSYSRESOURCE) * cResources); 2056 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 2057 ulOfsThis, 2058 FILE_BEGIN, 2059 &ulDummy)); 2060 2061 ENSURE_SAFE(DosRead(pExec->hfExe, &ot, sizeof(ot), &ulDummy)); 2062 2063 paResources[i].ulFlag = ((ot.o32_flags & OBJWRITE) 2064 ? 0 2065 : RNPURE); 2066 paResources[i].ulFlag |= ((ot.o32_flags & OBJDISCARD) 2067 ? 4096 2068 : 0); 2069 paResources[i].ulFlag |= ((ot.o32_flags & OBJSHARED) 2070 ? RNMOVE 2071 : 0); 2072 paResources[i].ulFlag |= ((ot.o32_flags & OBJPRELOAD) 2073 ? RNPRELOAD 2074 : 0); 2075 } // end for 2214 2076 } // end if (cResources) 2215 2077 } // end if (pExec->ulExeFormat == EXEFORMAT_LX) … … 2217 2079 { 2218 2080 // 16-bit OS/2 executable: 2219 if (cResources = pExec->pNEHeader->usResSegmCount) 2081 cResources = pExec->pNEHeader->usResSegmCount; 2082 2083 if (cResources) 2220 2084 { 2221 2085 #pragma pack(1) // V0.9.9 (2001-04-02) [umoeller] … … 2231 2095 2232 2096 ULONG cb = sizeof(FSYSRESOURCE) * cResources; 2097 ULONG ulDummy; 2098 int i; 2233 2099 2234 2100 paResources = (PFSYSRESOURCE)malloc(cb); 2235 2101 if (!paResources) 2236 arc = ERROR_NOT_ENOUGH_MEMORY; 2237 else 2102 ENSURE_FAIL(ERROR_NOT_ENOUGH_MEMORY); 2103 2104 memset(paResources, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 2105 2106 // we first read the resources IDs and types 2107 2108 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 2109 pExec->pNEHeader->usResTblOfs 2110 + pExec->pDosExeHeader->ulNewHeaderOfs, 2111 FILE_BEGIN, 2112 &ulDummy)); 2113 2114 for (i = 0; i < cResources; i++) 2238 2115 { 2239 ULONG ulDummy; 2240 2241 memset(paResources, 0, cb); // V0.9.9 (2001-04-03) [umoeller] 2242 2243 // we first read the resources IDs and types 2244 if (!(arc = DosSetFilePtr(pExec->hfExe, 2245 pExec->pNEHeader->usResTblOfs 2246 + pExec->pDosExeHeader->ulNewHeaderOfs, 2247 FILE_BEGIN, 2248 &ulDummy))) 2249 { 2250 int i; 2251 2252 for (i = 0; i < cResources; i++) 2253 { 2254 arc = DosRead(pExec->hfExe, &rti, sizeof(rti), &ulDummy); 2255 if (arc) 2256 break; 2257 else 2258 { 2259 paResources[i].ulID = rti.name; 2260 paResources[i].ulType = rti.type; 2261 } 2262 } 2263 2264 if (!arc) 2265 { 2266 // we then read their sizes and flags 2267 for (i = 0; i < cResources; i++) 2268 { 2269 if (!(arc = DosSetFilePtr(pExec->hfExe, 2270 pExec->pDosExeHeader->ulNewHeaderOfs 2271 + pExec->pNEHeader->usSegTblOfs 2272 + (sizeof(ns) 2273 * ( pExec->pNEHeader->usSegTblEntries 2274 - pExec->pNEHeader->usResSegmCount 2275 + i)), 2276 FILE_BEGIN, 2277 &ulDummy))) 2278 { 2279 if (!(arc = DosRead(pExec->hfExe, 2280 &ns, 2281 sizeof(ns), 2282 &ulDummy))) 2283 { 2284 paResources[i].ulSize = ns.ns_cbseg; 2285 2286 paResources[i].ulFlag = (ns.ns_flags & OBJPRELOAD) ? RNPRELOAD : 0; 2287 paResources[i].ulFlag |= (ns.ns_flags & OBJSHARED) ? RNPURE : 0; 2288 paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? RNMOVE : 0; 2289 paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? 4096 : 0; 2290 } 2291 } 2292 2293 if (arc) 2294 break; // V0.9.9 (2001-04-04) [umoeller] 2295 } // end for 2296 } 2297 } // end if !arc = DosSetFilePtr(pExec->hfExe, 2298 } // end if paResources = (PFSYSRESOURCE)malloc(sizeof(FSYSRESOURCE) * cResources); 2116 ENSURE_SAFE(DosRead(pExec->hfExe, &rti, sizeof(rti), &ulDummy)); 2117 2118 paResources[i].ulID = rti.name; 2119 paResources[i].ulType = rti.type; 2120 } 2121 2122 // we then read their sizes and flags 2123 2124 for (i = 0; i < cResources; i++) 2125 { 2126 ENSURE_SAFE(DosSetFilePtr(pExec->hfExe, 2127 pExec->pDosExeHeader->ulNewHeaderOfs 2128 + pExec->pNEHeader->usSegTblOfs 2129 + (sizeof(ns) 2130 * ( pExec->pNEHeader->usSegTblEntries 2131 - pExec->pNEHeader->usResSegmCount 2132 + i)), 2133 FILE_BEGIN, 2134 &ulDummy)); 2135 2136 ENSURE_SAFE(DosRead(pExec->hfExe, &ns, sizeof(ns), &ulDummy)); 2137 2138 paResources[i].ulSize = ns.ns_cbseg; 2139 2140 paResources[i].ulFlag = (ns.ns_flags & OBJPRELOAD) ? RNPRELOAD : 0; 2141 paResources[i].ulFlag |= (ns.ns_flags & OBJSHARED) ? RNPURE : 0; 2142 paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? RNMOVE : 0; 2143 paResources[i].ulFlag |= (ns.ns_flags & OBJDISCARD) ? 4096 : 0; 2144 } 2299 2145 } // end if (cResources) 2300 2146 } // end else if (pExec->ulExeFormat == EXEFORMAT_NE) 2301 2147 else 2302 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller] 2303 2304 if (arc) // V0.9.9 (2001-04-03) [umoeller] 2305 { 2148 ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller] 2149 2150 *ppaResources = paResources; 2151 *pcResources = cResources; 2152 2153 ENSURE_FINALLY; 2306 2154 // if we had an error above, clean up 2307 if (paResources) 2308 free(paResources); 2309 } 2310 else 2311 { 2312 // no error: output data 2313 *ppaResources = paResources; 2314 *pcResources = cResources; 2315 } 2155 free(paResources); 2156 ENSURE_END; 2316 2157 } 2317 2158 else 2318 arc = ERROR_INVALID_EXE_SIGNATURE; // V0.9.9 (2001-04-03) [umoeller]2319 2320 return (arc);2159 ENSURE_FAIL(ERROR_INVALID_EXE_SIGNATURE); // V0.9.9 (2001-04-03) [umoeller] 2160 2161 ENSURE_OK; 2321 2162 } 2322 2163 … … 2330 2171 APIRET doshExecFreeResources(PFSYSRESOURCE paResources) 2331 2172 { 2332 if (paResources) // V0.9.9 (2001-04-04) [umoeller] 2333 free(paResources); 2173 free(paResources); 2334 2174 return (NO_ERROR); 2335 2175 } … … 2712 2552 PUSHORT posCount, // in/out: partition count 2713 2553 BYTE bDisk, // in: disk of partition 2714 c har *pszBootName,// in: boot partition name2554 const char *pszBootName, // in: boot partition name 2715 2555 CHAR cLetter, // in/out: drive letter 2716 2556 BYTE bFsType, // in: file system type … … 2720 2560 { 2721 2561 APIRET arc = NO_ERROR; 2722 PPARTITIONINFO ppiNew = (PPARTITIONINFO)malloc(sizeof(PARTITIONINFO));2562 PPARTITIONINFO ppiNew = NEW(PARTITIONINFO); 2723 2563 if (ppiNew) 2724 2564 { 2565 ZERO(ppiNew); 2566 2725 2567 // store data 2726 2568 ppiNew->bDisk = bDisk; 2727 if ( fBootable)2569 if ((fBootable) && (pszBootName) ) 2728 2570 { 2729 2571 memcpy(ppiNew->szBootName, pszBootName, 8); … … 2806 2648 *@@ doshGetBootManager: 2807 2649 * this goes thru the master boot records on all 2808 * disks to find the boot manager partition s.2650 * disks to find the boot manager partition. 2809 2651 * 2810 2652 * Returns: 2653 * 2811 2654 * -- NO_ERROR: boot manager found; in that case, 2812 2655 * information about the boot manager … … 2814 2657 * *BmInfo. Any of these pointers can 2815 2658 * be NULL if you're not interested. 2659 * 2816 2660 * -- ERROR_NOT_SUPPORTED (50): boot manager not installed. 2817 2661 * … … 2823 2667 APIRET doshGetBootManager(USHORT *pusDisk, // out: if != NULL, boot manager disk (1, 2, ...) 2824 2668 USHORT *pusPart, // out: if != NULL, index of bmgr primary partition (0-3) 2825 PAR_INFO * BmInfo)// out: if != NULL, boot manager partition info2669 PAR_INFO *pBmInfo) // out: if != NULL, boot manager partition info 2826 2670 { 2827 2671 APIRET arc = NO_ERROR; … … 2839 2683 // for each disk, read the MBR, which has the 2840 2684 // primary partitions 2841 if ((arc = doshReadSector(usDisk, &MBoot, 2842 0, 0, 1))) 2685 if ((arc = doshReadSector(usDisk, 2686 &MBoot, 2687 0, // head 2688 0, // cylinder 2689 1))) // sector 2843 2690 return (arc); 2844 2691 2845 // Lookup BootManager partition 2692 // scan primary partitions for whether 2693 // BootManager partition exists 2846 2694 for (usPrim = 0; usPrim < 4; usPrim++) 2847 2695 { 2848 2696 if (MBoot.sPrtnInfo[usPrim].bFileSysCode == 0x0A) 2849 2697 { 2850 if (BmInfo) 2851 *BmInfo = MBoot.sPrtnInfo[usPrim]; 2698 // this is boot manager: 2699 if (pBmInfo) 2700 *pBmInfo = MBoot.sPrtnInfo[usPrim]; 2852 2701 if (pusPart) 2853 2702 *pusPart = usPrim; 2854 2703 if (pusDisk) 2855 2704 *pusDisk = usDisk; 2705 // stop scanning 2856 2706 return (NO_ERROR); 2857 2707 } … … 2868 2718 * This gets called from doshGetPartitionsList. 2869 2719 * 2870 * Returns 0 upon errors. 2720 * Returns: 2721 * 2722 * -- ERROR_INVALID_PARAMETER: BMInfo is NULL. 2871 2723 * 2872 2724 * Based on code (C) Dmitry A. Steklenev. … … 2877 2729 APIRET GetPrimaryPartitions(PARTITIONINFO **pppiFirst, 2878 2730 PARTITIONINFO **pppiThis, 2879 PUSHORT posCount, // in/out: partition count2880 PCHAR pcLetter, // in/out: drive letter counter2881 UINT BmDisk, // in: physical disk (1, 2, 3, ...) of boot manager or null2882 PAR_INFO* BmInfo,// in: info returned by doshGetBootManager or NULL2883 UINT iDisk) // in: system's physical disk count2731 PUSHORT posCount, // in/out: partition count 2732 PCHAR pcLetter, // in/out: drive letter counter 2733 UINT BmDisk, // in: physical disk (1, 2, 3, ...) of boot manager or null 2734 PAR_INFO* pBmInfo, // in: info returned by doshGetBootManager or NULL 2735 UINT iDisk) // in: system's physical disk count 2884 2736 { 2885 2737 APIRET arc = NO_ERROR; 2886 2738 2887 if (! BmInfo)2739 if (!pBmInfo) 2888 2740 arc = ERROR_INVALID_PARAMETER; 2889 2741 else … … 2892 2744 memset(&MName, 0, sizeof(MName)); 2893 2745 2894 // read boot manager name table 2746 // read boot manager name table; 2747 // this is in the boot manager primary partition 2748 // at sector offset 3 (?!?) 2895 2749 if (!(arc = doshReadSector(BmDisk, 2896 2750 &MName, 2897 BmInfo->bBeginHead, 2898 GetCyl(BmInfo->rBeginSecCyl), 2899 GetSec(BmInfo->rBeginSecCyl) + 3))) 2751 // head, cylinder, sector of bmgr primary partition: 2752 pBmInfo->bBeginHead, 2753 GetCyl(pBmInfo->rBeginSecCyl), 2754 GetSec(pBmInfo->rBeginSecCyl) + 3))) 2900 2755 { 2756 // got bmgr name table: 2901 2757 MBR_INFO MBoot; // Master Boot 2902 2758 USHORT i; 2903 2759 2904 2760 // read master boot record of this disk 2905 if (!(arc = doshReadSector(iDisk, &MBoot, 0, 0, 1))) 2761 if (!(arc = doshReadSector(iDisk, 2762 &MBoot, 2763 0, // head 2764 0, // cylinder 2765 1))) // sector 2906 2766 { 2907 2767 for (i = 0; … … 2915 2775 ) 2916 2776 { 2917 BOOL fBootable = ( (BmInfo)2918 && (MName[(iDisk-1) * 4 + i].bootable & 0x01)2777 BOOL fBootable = ( (pBmInfo) 2778 && (MName[(iDisk-1) * 4 + i].bootable & 0x01) 2919 2779 ); 2920 2780 // store this partition … … 3079 2939 3080 2940 /* 2941 *@@ CleanPartitionInfos: 2942 * 2943 *@@added V0.9.9 (2001-04-07) [umoeller] 2944 */ 2945 2946 VOID CleanPartitionInfos(PPARTITIONINFO ppiThis) 2947 { 2948 while (ppiThis) 2949 { 2950 PPARTITIONINFO ppiNext = ppiThis->pNext; 2951 free(ppiThis); 2952 ppiThis = ppiNext; 2953 } 2954 } 2955 2956 /* 3081 2957 *@@ doshGetPartitionsList: 3082 2958 * this returns lots of information about the … … 3093 2969 * free the resources allocated by this function. 3094 2970 * 3095 * The linked list starts out with all the primary 3096 * partitions, followed by the logical drives in 3097 * the extended partitions. This function attempts 3098 * to guess the correct drive letters and stores 3099 * these with the PARTITIONINFO items, but there's 3100 * no guarantee that this is correct. We correctly 3101 * ignore Linux partitions here and give all primary 3102 * partitions the C: letter, but I have no idea 3103 * what happens with NTFS partitions, since I have 3104 * none. 2971 * What this function returns depends on whether 2972 * LVM is installed. 2973 * 2974 * -- If LVM.DLL is found on the LIBPATH, this opens 2975 * the LVM engine and returns the info from the 2976 * LVM engine in the PARTITIONINFO structures. 2977 * The partitions are then sorted by disk in 2978 * ascending order. 2979 * 2980 * -- Otherwise, we parse the partition tables 2981 * manually. The linked list then starts out with 2982 * all the primary partitions, followed by the 2983 * logical drives in the extended partitions. 2984 * This function attempts to guess the correct drive 2985 * letters and stores these with the PARTITIONINFO 2986 * items, but there's no guarantee that this is 2987 * correct. We correctly ignore Linux partitions here 2988 * and give all primary partitions the C: letter, but 2989 * I have no idea what happens with NTFS partitions, 2990 * since I have none. 3105 2991 * 3106 2992 * If an error != NO_ERROR is returned, *pusContext … … 3113 2999 * -- 3: secondary partitions error 3114 3000 * 3001 * -- 0: something else. 3002 * 3115 3003 * Based on code (C) Dmitry A. Steklenev. 3116 3004 * 3117 3005 *@@added V0.9.0 [umoeller] 3118 */ 3119 3120 APIRET doshGetPartitionsList(PPARTITIONINFO *ppPartitionInfo, // out: partition info array 3121 PUSHORT pusPartitionCount, // out: count of items in **ppPartitionInfo 3006 *@@changed V0.9.9 (2001-04-07) [umoeller]: added transparent LVM support; changed prototype 3007 *@@changed V0.9.9 (2001-04-07) [umoeller]: added memory leaks on errors 3008 */ 3009 3010 APIRET doshGetPartitionsList(PPARTITIONSLIST *ppList, 3122 3011 PUSHORT pusContext) // out: error context 3123 3012 { 3124 3013 APIRET arc = NO_ERROR; 3125 PAR_INFO BmInfo; // BootManager partition 3126 USHORT usBmDisk; // BootManager disk 3127 USHORT cDisks = doshQueryDiskCount(); // physical disks count 3128 USHORT i; 3014 3015 PLVMINFO pLVMInfo = NULL; 3129 3016 3130 3017 PARTITIONINFO *pPartitionInfos = NULL, // linked list of all partitions 3131 3018 *ppiTemp = NULL; 3132 USHORT osCount; // bootable partition count 3133 CHAR cLetter = 'C'; // first drive letter 3134 3135 if (cDisks > 8) // Not above 8 disks 3136 cDisks = 8; 3137 3138 // get boot manager disk and info 3139 if ((arc = doshGetBootManager(&usBmDisk, 3140 NULL, 3141 &BmInfo)) != NO_ERROR) 3142 { 3143 *pusContext = 1; 3144 return (arc); 3145 } 3146 // on each disk, read primary partitions 3147 for (i = 1; i <= cDisks; i++) 3148 { 3149 if ((arc = GetPrimaryPartitions(&pPartitionInfos, 3150 &ppiTemp, 3151 &osCount, 3152 &cLetter, 3153 usBmDisk, 3154 usBmDisk ? &BmInfo : 0, 3155 i))) 3019 USHORT cPartitions = 0; // bootable partition count 3020 3021 if (!ppList) 3022 return (ERROR_INVALID_PARAMETER); 3023 3024 if (!(arc = doshQueryLVMInfo(&pLVMInfo))) 3025 { 3026 // LVM installed: 3027 arc = doshReadLVMPartitions(pLVMInfo, // in: LVM info 3028 &pPartitionInfos, // out: partitions array 3029 &cPartitions); // out: partitions count 3030 // copied to output below 3031 3032 if (arc) 3156 3033 { 3157 *pusContext = 2; 3158 return (arc); 3034 // error: start over 3035 doshFreeLVMInfo(pLVMInfo); 3036 CleanPartitionInfos(pPartitionInfos); 3037 pPartitionInfos = NULL; 3038 cPartitions = 0; 3159 3039 } 3160 3040 } 3161 3041 3162 if (usBmDisk) 3163 { 3164 // boot manager found: 3165 // on each disk, read extended partition 3166 // with logical drives 3167 for (i = 1; i <= cDisks; i++) 3042 if (arc) 3043 { 3044 // LVM not installed, or failed: 3045 // parse partitions manually 3046 PAR_INFO BmInfo; // BootManager partition 3047 USHORT usBmDisk; // BootManager disk 3048 USHORT cDisks = doshQueryDiskCount(); // physical disks count 3049 USHORT i; 3050 3051 CHAR cLetter = 'C'; // first drive letter 3052 3053 // start over 3054 arc = NO_ERROR; 3055 3056 if (cDisks > 8) // Not above 8 disks 3057 cDisks = 8; 3058 3059 // get boot manager disk and info 3060 if ((arc = doshGetBootManager(&usBmDisk, 3061 NULL, 3062 &BmInfo)) != NO_ERROR) 3168 3063 { 3169 if ((arc = GetExtendedPartition(&pPartitionInfos,3170 &ppiTemp,3171 &osCount,3172 &cLetter,3173 &BmInfo,3174 i)))3064 *pusContext = 1; 3065 } 3066 else 3067 { 3068 // on each disk, read primary partitions 3069 for (i = 1; i <= cDisks; i++) 3175 3070 { 3176 *pusContext = 3; 3177 return (arc); 3071 if ((arc = GetPrimaryPartitions(&pPartitionInfos, 3072 &ppiTemp, 3073 &cPartitions, 3074 &cLetter, 3075 usBmDisk, 3076 usBmDisk ? &BmInfo : 0, 3077 i))) 3078 { 3079 *pusContext = 2; 3080 } 3081 } 3082 3083 if (!arc && usBmDisk) 3084 { 3085 // boot manager found: 3086 // on each disk, read extended partition 3087 // with logical drives 3088 for (i = 1; i <= cDisks; i++) 3089 { 3090 if ((arc = GetExtendedPartition(&pPartitionInfos, 3091 &ppiTemp, 3092 &cPartitions, 3093 &cLetter, 3094 &BmInfo, 3095 i))) 3096 { 3097 *pusContext = 3; 3098 } 3099 } 3100 } 3101 } // end else if ((arc = doshGetBootManager(&usBmDisk, 3102 } // end else if (!doshQueryLVMInfo(&pLVMInfo)) 3103 3104 if (!arc) 3105 { 3106 // no error so far: 3107 *pusContext = 0; 3108 3109 *ppList = NEW(PARTITIONSLIST); 3110 if (!(*ppList)) 3111 arc = ERROR_NOT_ENOUGH_MEMORY; 3112 else 3113 { 3114 ZERO(*ppList); 3115 3116 (*ppList)->pPartitionInfo = pPartitionInfos; 3117 (*ppList)->cPartitions = cPartitions; 3118 3119 _Pmpf((__FUNCTION__ ": returning %d partitions", cPartitions)); 3120 } 3121 } 3122 3123 if (arc) 3124 CleanPartitionInfos(pPartitionInfos); 3125 3126 _Pmpf((__FUNCTION__ ": exiting, arc = %d", arc)); 3127 3128 return (arc); 3129 } 3130 3131 /* 3132 *@@ doshFreePartitionsList: 3133 * this frees the resources allocated by 3134 * doshGetPartitionsList. 3135 * 3136 *@@added V0.9.0 [umoeller] 3137 */ 3138 3139 APIRET doshFreePartitionsList(PPARTITIONSLIST ppList) 3140 { 3141 if (!ppList) 3142 return (ERROR_INVALID_PARAMETER); 3143 else 3144 { 3145 CleanPartitionInfos(ppList->pPartitionInfo); 3146 doshFreeLVMInfo(ppList->pLVMInfo); 3147 free(ppList); 3148 } 3149 3150 return (NO_ERROR); 3151 } 3152 3153 /******************************************************************** 3154 * 3155 * LVM declarations 3156 * 3157 ********************************************************************/ 3158 3159 /* 3160 *@@category: Helpers\Control program helpers\Partitions info\Quick LVM Interface 3161 * functions for transparently interfacing LVM.DLL. 3162 */ 3163 3164 typedef unsigned char BOOLEAN; 3165 typedef unsigned short int CARDINAL16; 3166 typedef unsigned long CARDINAL32; 3167 typedef unsigned int CARDINAL; 3168 typedef unsigned long DoubleWord; 3169 3170 #ifdef ADDRESS 3171 #undef ADDRESS 3172 #endif 3173 3174 typedef void* ADDRESS; 3175 3176 #pragma pack(1) 3177 3178 #define DISK_NAME_SIZE 20 3179 #define FILESYSTEM_NAME_SIZE 20 3180 #define PARTITION_NAME_SIZE 20 3181 #define VOLUME_NAME_SIZE 20 3182 3183 /* 3184 *@@ Drive_Control_Record: 3185 * invariant for a disk drive. 3186 * 3187 *@@added V0.9.9 (2001-04-07) [umoeller] 3188 */ 3189 3190 typedef struct _Drive_Control_Record 3191 { 3192 CARDINAL32 Drive_Number; // OS/2 Drive Number for this drive. 3193 CARDINAL32 Drive_Size; // The total number of sectors on the drive. 3194 DoubleWord Drive_Serial_Number; // The serial number assigned to this drive. For info. purposes only. 3195 ADDRESS Drive_Handle; // Handle used for operations on the disk that this record corresponds to. 3196 CARDINAL32 Cylinder_Count; // The number of cylinders on the drive. 3197 CARDINAL32 Heads_Per_Cylinder; // The number of heads per cylinder for this drive. 3198 CARDINAL32 Sectors_Per_Track; // The number of sectors per track for this drive. 3199 BOOLEAN Drive_Is_PRM; // Set to TRUE if this drive is a PRM. 3200 BYTE Reserved[3]; // Alignment. 3201 } Drive_Control_Record; 3202 3203 /* 3204 *@@ Drive_Control_Array: 3205 * returned by the Get_Drive_Control_Data function 3206 * 3207 *@@added V0.9.9 (2001-04-07) [umoeller] 3208 */ 3209 3210 typedef struct _Drive_Control_Array 3211 { 3212 Drive_Control_Record * Drive_Control_Data; // An array of drive control records. 3213 CARDINAL32 Count; // The number of entries in the array of drive control records. 3214 } Drive_Control_Array; 3215 3216 /* 3217 *@@ Drive_Information_Record: 3218 * defines the information that can be changed for a specific disk drive. 3219 * 3220 *@@added V0.9.9 (2001-04-07) [umoeller] 3221 */ 3222 3223 typedef struct _Drive_Information_Record 3224 { 3225 CARDINAL32 Total_Available_Sectors; // The number of sectors on the disk which are not currently assigned to a partition. 3226 CARDINAL32 Largest_Free_Block_Of_Sectors; // The number of sectors in the largest contiguous block of available sectors. 3227 BOOLEAN Corrupt_Partition_Table; // If TRUE, then the partitioning information found on the drive is incorrect! 3228 BOOLEAN Unusable; // If TRUE, the drive's MBR is not accessible and the drive can not be partitioned. 3229 BOOLEAN IO_Error; // If TRUE, then the last I/O operation on this drive failed! 3230 BOOLEAN Is_Big_Floppy; // If TRUE, then the drive is a PRM formatted as a big floppy (i.e. the old style removable media support). 3231 char Drive_Name[DISK_NAME_SIZE]; // User assigned name for this disk drive. 3232 } Drive_Information_Record; 3233 3234 /* 3235 *@@ Partition_Information_Record: 3236 * 3237 *@@added V0.9.9 (2001-04-07) [umoeller] 3238 */ 3239 3240 typedef struct _Partition_Information_Record 3241 { 3242 ADDRESS Partition_Handle; 3243 // The handle used to perform operations on this partition. 3244 ADDRESS Volume_Handle; 3245 // If this partition is part of a volume, this will be the handle of 3246 // the volume. If this partition is NOT part of a volume, then this 3247 // handle will be 0. 3248 ADDRESS Drive_Handle; 3249 // The handle for the drive this partition resides on. 3250 DoubleWord Partition_Serial_Number; 3251 // The serial number assigned to this partition. 3252 CARDINAL32 Partition_Start; 3253 // The LBA of the first sector of the partition. 3254 CARDINAL32 True_Partition_Size; 3255 // The total number of sectors comprising the partition. 3256 CARDINAL32 Usable_Partition_Size; 3257 // The size of the partition as reported to the IFSM. This is the 3258 // size of the partition less any LVM overhead. 3259 CARDINAL32 Boot_Limit; 3260 // The maximum number of sectors from this block of free space that 3261 // can be used to create a bootable partition if you allocate from the 3262 // beginning of the block of free space. 3263 BOOLEAN Spanned_Volume; 3264 // TRUE if this partition is part of a multi-partition volume. 3265 BOOLEAN Primary_Partition; 3266 // True or False. Any non-zero value here indicates that this partition 3267 // is a primary partition. Zero here indicates that this partition is 3268 // a "logical drive" - i.e. it resides inside of an extended partition. 3269 BYTE Active_Flag; 3270 // 80 = Partition is marked as being active. 3271 // 0 = Partition is not active. 3272 BYTE OS_Flag; 3273 // This field is from the partition table. It is known as the OS flag, 3274 // the Partition Type Field, Filesystem Type, and various other names. 3275 // Values of interest 3276 // If this field is: (values are in hex) 3277 // 07 = The partition is a compatibility partition formatted for use 3278 // with an installable filesystem, such as HPFS or JFS. 3279 // 00 = Unformatted partition 3280 // 01 = FAT12 filesystem is in use on this partition. 3281 // 04 = FAT16 filesystem is in use on this partition. 3282 // 0A = OS/2 Boot Manager Partition 3283 // 35 = LVM partition 3284 // 84 = OS/2 FAT16 partition which has been relabeled by Boot Manager to "Hide" it. 3285 BYTE Partition_Type; 3286 // 0 = Free Space 3287 // 1 = LVM Partition (Part of an LVM Volume.) 3288 // 2 = Compatibility Partition 3289 // All other values are reserved for future use. 3290 BYTE Partition_Status; 3291 // 0 = Free Space 3292 // 1 = In Use - i.e. already assigned to a volume. 3293 // 2 = Available - i.e. not currently assigned to a volume. 3294 BOOLEAN On_Boot_Manager_Menu; 3295 // Set to TRUE if this partition is not part of a Volume yet is on the 3296 // Boot Manager Menu. 3297 BYTE Reserved; 3298 // Alignment. 3299 char Volume_Drive_Letter; 3300 // The drive letter assigned to the volume that this partition is a part of. 3301 char Drive_Name[DISK_NAME_SIZE]; 3302 // User assigned name for this disk drive. 3303 char File_System_Name[FILESYSTEM_NAME_SIZE]; 3304 // The name of the filesystem in use on this partition, if it is known. 3305 char Partition_Name[PARTITION_NAME_SIZE]; 3306 // The user assigned name for this partition. 3307 char Volume_Name[VOLUME_NAME_SIZE]; 3308 // If this partition is part of a volume, then this will be the 3309 // name of the volume that this partition is a part of. If this 3310 // record represents free space, then the Volume_Name will be 3311 // "FREE SPACE xx", where xx is a unique numeric ID generated by 3312 // LVM.DLL. Otherwise it will be an empty string. 3313 } Partition_Information_Record; 3314 3315 // The following defines are for use with the Partition_Type field in the 3316 // Partition_Information_Record. 3317 #define FREE_SPACE_PARTITION 0 3318 #define LVM_PARTITION 1 3319 #define COMPATIBILITY_PARTITION 2 3320 3321 // The following defines are for use with the Partition_Status field in the 3322 // Partition_Information_Record. 3323 #define PARTITION_IS_IN_USE 1 3324 #define PARTITION_IS_AVAILABLE 2 3325 #define PARTITION_IS_FREE_SPACE 0 3326 3327 /* 3328 *@@ Partition_Information_Array: 3329 * returned by various functions in the LVM Engine. 3330 * 3331 *@@added V0.9.9 (2001-04-07) [umoeller] 3332 */ 3333 3334 typedef struct _Partition_Information_Array 3335 { 3336 Partition_Information_Record * Partition_Array; // An array of Partition_Information_Records. 3337 CARDINAL32 Count; // The number of entries in the Partition_Array. 3338 } Partition_Information_Array; 3339 3340 /* 3341 *@@ Volume_Information_Record: 3342 * variable information for a volume. 3343 * 3344 *@@added V0.9.9 (2001-04-07) [umoeller] 3345 */ 3346 3347 typedef struct _Volume_Information_Record 3348 { 3349 CARDINAL32 Volume_Size; 3350 // The number of sectors comprising the volume. 3351 CARDINAL32 Partition_Count; 3352 // The number of partitions which comprise this volume. 3353 CARDINAL32 Drive_Letter_Conflict; 3354 // 0 indicates that the drive letter preference for this volume is unique. 3355 // 1 indicates that the drive letter preference for this volume 3356 // is not unique, but this volume got its preferred drive letter anyway. 3357 // 2 indicates that the drive letter preference for this volume 3358 // is not unique, and this volume did NOT get its preferred drive letter. 3359 // 4 indicates that this volume is currently "hidden" - i.e. it has 3360 // no drive letter preference at the current time. 3361 BOOLEAN Compatibility_Volume; 3362 // TRUE if this is for a compatibility volume, FALSE otherwise. 3363 BOOLEAN Bootable; 3364 // Set to TRUE if this volume appears on the Boot Manager menu, or if it is 3365 // a compatibility volume and its corresponding partition is the first active 3366 // primary partition on the first drive. 3367 char Drive_Letter_Preference; 3368 // The drive letter that this volume desires to be. 3369 char Current_Drive_Letter; 3370 // The drive letter currently used to access this volume. 3371 // May be different than Drive_Letter_Preference if there was a conflict ( i.e. Drive_Letter_Preference 3372 // is already in use by another volume ). 3373 char Initial_Drive_Letter; 3374 // The drive letter assigned to this volume by the operating system 3375 // when LVM was started. This may be different from the 3376 // Drive_Letter_Preference if there were conflicts, and 3377 // may be different from the Current_Drive_Letter. This 3378 // will be 0x0 if the Volume did not exist when the LVM Engine 3379 // was opened (i.e. it was created during this LVM session). 3380 BOOLEAN New_Volume; 3381 // Set to FALSE if this volume existed before the LVM Engine was 3382 // opened. Set to TRUE if this volume was created after the LVM 3383 // Engine was opened. 3384 BYTE Status; 3385 // 0 = None. 3386 // 1 = Bootable 3387 // 2 = Startable 3388 // 3 = Installable. 3389 BYTE Reserved_1; 3390 char Volume_Name[VOLUME_NAME_SIZE]; 3391 // The user assigned name for this volume. 3392 char File_System_Name[FILESYSTEM_NAME_SIZE]; 3393 // The name of the filesystem in use on this partition, if it 3394 // is known. 3395 } Volume_Information_Record; 3396 3397 #pragma pack() 3398 3399 /******************************************************************** 3400 * 3401 * Quick LVM Interface API 3402 * 3403 ********************************************************************/ 3404 3405 /* 3406 *@@ LVMINFOPRIVATE: 3407 * private structure used by doshQueryLVMInfo. 3408 * This is what the LVMINFO pointer really 3409 * points to. 3410 * 3411 *@@added V0.9.9 (2001-04-07) [umoeller] 3412 */ 3413 3414 typedef struct _LVMINFOPRIVATE 3415 { 3416 LVMINFO LVMInfo; // public structure (dosh.h) 3417 3418 // function pointers resolved from LVM.DLL 3419 3420 void (* _System Open_LVM_Engine)(BOOLEAN Ignore_CHS, 3421 CARDINAL32 *Error_Code); 3422 3423 void (* _System Free_Engine_Memory)(ADDRESS Object); 3424 3425 void (* _System Close_LVM_Engine)(void); 3426 3427 Drive_Control_Array (* _System 3428 Get_Drive_Control_Data)(CARDINAL32 *Error_Code); 3429 3430 Drive_Information_Record (* _System 3431 Get_Drive_Status)(ADDRESS Drive_Handle, 3432 CARDINAL32 *Error_Code); 3433 3434 Partition_Information_Array (* _System 3435 Get_Partitions)(ADDRESS Handle, 3436 CARDINAL32 *Error_Code); 3437 3438 Volume_Information_Record (*_System 3439 Get_Volume_Information)(ADDRESS Volume_Handle, 3440 CARDINAL32 *Error_Code); 3441 3442 } LVMINFOPRIVATE, *PLVMINFOPRIVATE; 3443 3444 #define LVM_ERROR_FIRST 20000 3445 3446 /* 3447 *@@ doshQueryLVMInfo: 3448 * creates an LVMINFO structure if LVM is installed. 3449 * Returns that structure (which the caller must free 3450 * using doshFreeLVMInfo) or NULL if LVM.DLL was not 3451 * found along the LIBPATH. 3452 * 3453 *@@added V0.9.9 (2001-04-07) [umoeller] 3454 */ 3455 3456 APIRET doshQueryLVMInfo(PLVMINFO *ppLVMInfo) 3457 { 3458 APIRET arc = NO_ERROR; 3459 CHAR szError[100]; 3460 PLVMINFOPRIVATE pLVMInfo = NULL; 3461 HMODULE hmodLVM = NULLHANDLE; 3462 3463 if (!(arc = DosLoadModule(szError, 3464 sizeof(szError), 3465 "LVM", 3466 &hmodLVM))) 3467 { 3468 // got LVM.DLL: 3469 pLVMInfo = NEW(LVMINFOPRIVATE); 3470 if (!pLVMInfo) 3471 arc = ERROR_NOT_ENOUGH_MEMORY; 3472 else 3473 { 3474 // array of function pointers to be resolved from LVM.DLL 3475 RESOLVEFUNCTION aFunctions[] = 3476 { 3477 "Open_LVM_Engine", (PFN*)&pLVMInfo->Open_LVM_Engine, 3478 "Free_Engine_Memory", (PFN*)&pLVMInfo->Free_Engine_Memory, 3479 "Close_LVM_Engine", (PFN*)&pLVMInfo->Close_LVM_Engine, 3480 "Get_Drive_Control_Data", (PFN*)&pLVMInfo->Get_Drive_Control_Data, 3481 "Get_Drive_Status", (PFN*)&pLVMInfo->Get_Drive_Status, 3482 "Get_Partitions", (PFN*)&pLVMInfo->Get_Partitions, 3483 "Get_Volume_Information", (PFN*)&pLVMInfo->Get_Volume_Information 3484 }; 3485 ULONG ul; 3486 3487 ZERO(pLVMInfo); 3488 3489 pLVMInfo->LVMInfo.hmodLVM = hmodLVM; 3490 3491 // now resolve function pointers 3492 for (ul = 0; 3493 ul < ARRAYITEMCOUNT(aFunctions); 3494 ul++) 3495 { 3496 PRESOLVEFUNCTION pFuncThis = &aFunctions[ul]; 3497 arc = DosQueryProcAddr(hmodLVM, 3498 0, // ordinal, ignored 3499 (PSZ)pFuncThis->pcszFunctionName, 3500 pFuncThis->ppFuncAddress); 3501 if (!pFuncThis->ppFuncAddress) 3502 arc = ERROR_INVALID_NAME; 3503 3504 if (arc) 3505 break; 3178 3506 } 3179 3507 } 3180 3508 } 3181 3509 3182 *ppPartitionInfo = pPartitionInfos; 3183 *pusPartitionCount = osCount; 3184 3185 return (NO_ERROR); // 0 3186 } 3187 3188 /* 3189 *@@ doshFreePartitionsList: 3190 * this frees the resources allocated by 3191 * doshGetPartitionsList. 3192 * 3193 *@@added V0.9.0 [umoeller] 3194 */ 3195 3196 APIRET doshFreePartitionsList(PPARTITIONINFO pPartitionInfo) 3197 { 3198 PPARTITIONINFO ppiThis = NULL; 3199 ppiThis = pPartitionInfo; 3200 while (ppiThis) 3201 { 3202 PPARTITIONINFO ppiNext = ppiThis->pNext; 3203 free(ppiThis); 3204 ppiThis = ppiNext; 3510 if (arc) 3511 doshFreeLVMInfo((PLVMINFO)pLVMInfo); 3512 else 3513 *ppLVMInfo = (PLVMINFO)pLVMInfo; 3514 3515 return (arc); 3516 } 3517 3518 /* 3519 *@@ doshReadLVMPartitions: 3520 * using the LVMINFO parameter from doshQueryLVMInfo, 3521 * builds an array of PARTITIONINFO structures with 3522 * the data returned from LVM.DLL. 3523 * 3524 *@@added V0.9.9 (2001-04-07) [umoeller] 3525 */ 3526 3527 APIRET doshReadLVMPartitions(PLVMINFO pInfo, // in: LVM info 3528 PPARTITIONINFO *ppPartitionInfo, // out: partitions array 3529 PUSHORT pcPartitions) // out: partitions count 3530 { 3531 APIRET arc = NO_ERROR; 3532 CARDINAL32 Error = 0; 3533 3534 PARTITIONINFO *pPartitionInfos = NULL, // linked list of all partitions 3535 *ppiTemp = NULL; 3536 USHORT cPartitions = 0; // bootable partition count 3537 PLVMINFOPRIVATE pLVMInfo = (PLVMINFOPRIVATE)pInfo; 3538 3539 _Pmpf((__FUNCTION__ ": entering")); 3540 3541 if (!pLVMInfo) 3542 return (ERROR_INVALID_PARAMETER); 3543 3544 // initialize LVM engine 3545 pLVMInfo->Open_LVM_Engine(TRUE, 3546 &Error); 3547 3548 _Pmpf((" Open_LVM_Engine Error: %d")); 3549 3550 if (!Error) 3551 { 3552 Drive_Control_Array DCA = pLVMInfo->Get_Drive_Control_Data(&Error); 3553 // member records to be freed 3554 3555 _Pmpf((" Get_Drive_Control_Data Error: %d, drive count: %d", Error, DCA.Count)); 3556 3557 if ( (!Error) 3558 && (DCA.Count) 3559 ) 3560 { 3561 // DCA.Drive_Control_Data now contains drive information records; 3562 // this must be freed 3563 ULONG ulDisk; 3564 3565 for (ulDisk = 0; 3566 ulDisk < DCA.Count; 3567 ulDisk++) 3568 { 3569 Drive_Control_Record *pDriveControlRecord 3570 = &DCA.Drive_Control_Data[ulDisk]; 3571 ADDRESS hDrive = pDriveControlRecord->Drive_Handle; 3572 3573 Drive_Information_Record pDriveInfoRecord 3574 = pLVMInfo->Get_Drive_Status(hDrive, 3575 &Error); 3576 3577 _Pmpf((" drive %d Get_Drive_Status Error: %d", ulDisk, Error)); 3578 3579 if (!Error) 3580 { 3581 Partition_Information_Array PIA 3582 = pLVMInfo->Get_Partitions(hDrive, 3583 &Error); 3584 3585 _Pmpf((" Get_Partitions Error: %d", Error)); 3586 3587 if (!Error) 3588 { 3589 // PIA.Partition_Array now contains 3590 // Partition_Information_Record; must be freed 3591 3592 // now go thru partitions of this drive 3593 ULONG ulPart; 3594 for (ulPart = 0; 3595 ulPart < PIA.Count; 3596 ulPart++) 3597 { 3598 Partition_Information_Record *pPartition 3599 = &PIA.Partition_Array[ulPart]; 3600 Volume_Information_Record VolumeInfo; 3601 3602 const char *pcszBootName = NULL; // for now 3603 BOOL fBootable = FALSE; 3604 3605 if (pPartition->Volume_Handle) 3606 { 3607 // this partition is part of a volume: 3608 // only then can it be bootable... 3609 // get the volume info 3610 VolumeInfo 3611 = pLVMInfo->Get_Volume_Information(pPartition->Volume_Handle, 3612 &Error); 3613 pcszBootName = VolumeInfo.Volume_Name; 3614 3615 fBootable = (VolumeInfo.Status == 1); 3616 } 3617 3618 3619 if (arc = AppendPartition(&pPartitionInfos, 3620 &ppiTemp, 3621 &cPartitions, 3622 ulDisk + 1, 3623 pcszBootName, 3624 pPartition->Volume_Drive_Letter, 3625 pPartition->OS_Flag, // FS type 3626 pPartition->Primary_Partition, 3627 fBootable, 3628 pPartition->True_Partition_Size)) 3629 break; 3630 } 3631 3632 // clean up partitions 3633 pLVMInfo->Free_Engine_Memory(PIA.Partition_Array); 3634 } 3635 } 3636 else 3637 // error: 3638 break; 3639 } 3640 3641 // clean up drive data 3642 pLVMInfo->Free_Engine_Memory(DCA.Drive_Control_Data); 3643 } 3205 3644 } 3206 return (NO_ERROR); 3207 } 3208 3209 3645 3646 // close LVM 3647 pLVMInfo->Close_LVM_Engine(); 3648 3649 if (Error) 3650 { 3651 // if we got an error, return it with the 3652 // LVM error offset 3653 arc = LVM_ERROR_FIRST + Error; 3654 3655 CleanPartitionInfos(pPartitionInfos); 3656 } 3657 3658 if (!arc) 3659 { 3660 *ppPartitionInfo = pPartitionInfos; 3661 *pcPartitions = cPartitions; 3662 } 3663 3664 _Pmpf((__FUNCTION__ ": exiting, arg = %d", arc)); 3665 3666 return (arc); 3667 } 3668 3669 /* 3670 *@@ doshFreeLVMInfo: 3671 * 3672 *@@added V0.9.9 (2001-04-07) [umoeller] 3673 */ 3674 3675 VOID doshFreeLVMInfo(PLVMINFO pInfo) 3676 { 3677 if (pInfo) 3678 { 3679 if (pInfo->hmodLVM) 3680 DosFreeModule(pInfo->hmodLVM); 3681 3682 free(pInfo); 3683 } 3684 }
Note:
See TracChangeset
for help on using the changeset viewer.