Ignore:
Timestamp:
Apr 8, 2001, 9:17:16 AM (24 years ago)
Author:
umoeller
Message:

misc changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/helpers/dosh2.c

    r55 r56  
    6464
    6565#include "helpers\dosh.h"
     66#include "helpers\ensure.h"
     67#include "helpers\standards.h"
    6668#include "helpers\stringh.h"
    6769
     
    12361238 *@@added V0.9.9 (2001-03-11) [lafaix]
    12371239 *@@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
    12381241 */
    12391242
     
    12421245                                    PULONG pcModules)           // out: array item count
    12431246{
    1244     APIRET      arc = NO_ERROR;
    1245 
    12461247    if (    (pExec)
    12471248         && (pExec->ulOS == EXEOS_OS2)
    12481249       )
    12491250    {
     1251        ENSURE_BEGIN;
    12501252        ULONG       cModules = 0;
    12511253        PFSYSMODULE paModules = NULL;
     
    12551257        {
    12561258            // 32-bit OS/2 executable:
    1257             if (cModules = pExec->pLXHeader->ulImportModTblCnt)
     1259            cModules = pExec->pLXHeader->ulImportModTblCnt;
     1260
     1261            if (cModules)
    12581262            {
    12591263                ULONG cb = sizeof(FSYSMODULE) * cModules; // V0.9.9 (2001-04-03) [umoeller]
     1264                ULONG ulDummy;
    12601265
    12611266                paModules = (PFSYSMODULE)malloc(cb);
    12621267                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++)
    12651279                {
    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
    13111298            }
    13121299        } // end LX
     
    13141301        {
    13151302            // 16-bit OS/2 executable:
    1316             if (cModules = pExec->pNEHeader->usModuleTblEntries)
     1303            cModules = pExec->pNEHeader->usModuleTblEntries;
     1304
     1305            if (cModules)
    13171306            {
    13181307                ULONG cb = sizeof(FSYSMODULE) * cModules;
     
    13201309                paModules = (PFSYSMODULE)malloc(cb);
    13211310                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 ++)
    13241316                {
    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
    13731353            }
    13741354        }
    13751355        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;
    13801363            // 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;
    13901366    }
    13911367    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;
    13951371}
    13961372
     
    14041380APIRET doshExecFreeImportedModules(PFSYSMODULE paModules)
    14051381{
    1406     if (paModules)          // V0.9.9 (2001-04-04) [umoeller]
    1407         free(paModules);
     1382    free(paModules);
    14081383    return (NO_ERROR);
    14091384}
     
    14181393 *@@added V0.9.9 (2001-03-30) [lafaix]
    14191394 *@@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
    14201396 */
    14211397
     
    14241400                        PULONG pcEntries)        // out: entry table entry count; ptr can be NULL
    14251401{
    1426     APIRET arc = NO_ERROR;
    1427 
    14281402    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)
    14411428        {
    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 ++)
    14591453                {
    1460                     switch (bType & 0x7F)
     1454                    ENSURE(DosRead(pExec->hfExe, &bFlag, 1, &ulDummy));
     1455
     1456                    if (bFlag & 0x01)
    14611457                    {
    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++;
    16741606                }
    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;
    16841617}
    16851618
     
    16931626 *@@added V0.9.9 (2001-03-30) [lafaix]
    16941627 *@@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
    16951629 */
    16961630
     
    16991633                        PULONG pcEntries)        // out: entry table entry count; ptr can be NULL
    17001634{
    1701     APIRET arc = NO_ERROR;
    17021635    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++)
    17151661        {
    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)
    17241668            {
    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)
    17331670                {
    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;
    17721674                }
     1675                usCurrent++;
    17731676            }
    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;
    17821704}
    17831705
     
    17871709 *
    17881710 *@@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++
    17891712 */
    17901713
     
    18141737 *@@changed V0.9.9 (2001-04-02) [lafaix]: the first entry is special
    18151738 *@@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
    18161741 */
    18171742
     
    18201745                     PFSYSFUNCTION paFunctions)
    18211746{
    1822     APIRET  arc = NO_ERROR;
    18231747    ULONG   ulDummy;
    18241748
    18251749    USHORT        usOrdinal;
    18261750    PFSYSFUNCTION pFunction;
    1827     BOOL          bFirst = TRUE;
    1828 
    1829     while (!arc)        // V0.9.9 (2001-04-03) [umoeller]
     1751
     1752    while (TRUE)
    18301753    {
    18311754        BYTE   bLen;
     
    18331756        int    i;
    18341757
    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)))
    18391774        {
    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);
    18791778        }
    18801779    }
    18811780
    1882     return (arc);
     1781    ENSURE_OK;
    18831782}
    18841783
     
    19111810 *@@added V0.9.9 (2001-03-11) [lafaix]
    19121811 *@@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
    19131813 */
    19141814
     
    19171817                                      PULONG pcFunctions)           // out: array item count
    19181818{
    1919     APIRET arc = NO_ERROR;
    1920 
    19211819    if (    (pExec)
    19221820         && (pExec->ulOS == EXEOS_OS2)
    19231821       )
    19241822    {
     1823        ENSURE_BEGIN;
    19251824        ULONG         cFunctions = 0;
    19261825        PFSYSFUNCTION paFunctions = NULL;
     
    19361835            // the entry table
    19371836
    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)
    19411843            {
    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)
    19781875        }
    19791876        else if (pExec->ulExeFormat == EXEFORMAT_NE)
     
    19851882            // have to count them in the entry table
    19861883
    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)
    19901890            {
    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));
    20271922            }
    20281923        }
    20291924        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;
    20341932            // 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;
    20441935    }
    20451936    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;
    20491940}
    20501941
     
    20581949APIRET doshExecFreeExportedFunctions(PFSYSFUNCTION paFunctions)
    20591950{
    2060     if (paFunctions)       // V0.9.9 (2001-04-04) [umoeller]
    2061         free(paFunctions);
     1951    free(paFunctions);
     1952
    20621953    return (NO_ERROR);
    20631954}
     
    20911982                              PULONG pcResources)    // out: array item count
    20921983{
    2093     APIRET          arc = NO_ERROR;
    2094 
    20951984    if (    (pExec)
    20961985         && (pExec->ulOS == EXEOS_OS2)
    20971986       )
    20981987    {
     1988        ENSURE_BEGIN;
    20991989        ULONG           cResources = 0;
    21001990        PFSYSRESOURCE   paResources = NULL;
     
    21031993        {
    21041994            // 32-bit OS/2 executable:
    2105             if (cResources = pExec->pLXHeader->ulResTblCnt)
     1995            cResources = pExec->pLXHeader->ulResTblCnt;
     1996
     1997            if (cResources)
    21061998            {
     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
    21072020                ULONG cb = sizeof(FSYSRESOURCE) * cResources;
     2021                ULONG ulDummy;
     2022                int i;
     2023
    21082024                paResources = (PFSYSRESOURCE)malloc(cb);
    21092025                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++)
    21122037                {
    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
    21792052                                      + pExec->pDosExeHeader->ulNewHeaderOfs
    21802053                                      + (   sizeof(ot)
    21812054                                          * (paResources[i].ulFlag - 1));
    21822055
    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
    22142076            } // end if (cResources)
    22152077        } // end if (pExec->ulExeFormat == EXEFORMAT_LX)
     
    22172079        {
    22182080            // 16-bit OS/2 executable:
    2219             if (cResources = pExec->pNEHeader->usResSegmCount)
     2081            cResources = pExec->pNEHeader->usResSegmCount;
     2082
     2083            if (cResources)
    22202084            {
    22212085                #pragma pack(1)     // V0.9.9 (2001-04-02) [umoeller]
     
    22312095
    22322096                ULONG cb = sizeof(FSYSRESOURCE) * cResources;
     2097                ULONG ulDummy;
     2098                int i;
    22332099
    22342100                paResources = (PFSYSRESOURCE)malloc(cb);
    22352101                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++)
    22382115                {
    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                }
    22992145            } // end if (cResources)
    23002146        } // end else if (pExec->ulExeFormat == EXEFORMAT_NE)
    23012147        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;
    23062154            // 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;
    23162157    }
    23172158    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;
    23212162}
    23222163
     
    23302171APIRET doshExecFreeResources(PFSYSRESOURCE paResources)
    23312172{
    2332     if (paResources)        // V0.9.9 (2001-04-04) [umoeller]
    2333         free(paResources);
     2173    free(paResources);
    23342174    return (NO_ERROR);
    23352175}
     
    27122552                       PUSHORT posCount,            // in/out: partition count
    27132553                       BYTE bDisk,                  // in: disk of partition
    2714                        char *pszBootName,           // in: boot partition name
     2554                       const char *pszBootName,     // in: boot partition name
    27152555                       CHAR cLetter,                // in/out: drive letter
    27162556                       BYTE bFsType,                // in: file system type
     
    27202560{
    27212561    APIRET arc = NO_ERROR;
    2722     PPARTITIONINFO ppiNew = (PPARTITIONINFO)malloc(sizeof(PARTITIONINFO));
     2562    PPARTITIONINFO ppiNew = NEW(PARTITIONINFO);
    27232563    if (ppiNew)
    27242564    {
     2565        ZERO(ppiNew);
     2566
    27252567        // store data
    27262568        ppiNew->bDisk = bDisk;
    2727         if (fBootable)
     2569        if ((fBootable) && (pszBootName) )
    27282570        {
    27292571            memcpy(ppiNew->szBootName, pszBootName, 8);
     
    28062648 *@@ doshGetBootManager:
    28072649 *      this goes thru the master boot records on all
    2808  *      disks to find the boot manager partitions.
     2650 *      disks to find the boot manager partition.
    28092651 *
    28102652 *      Returns:
     2653 *
    28112654 *      -- NO_ERROR: boot manager found; in that case,
    28122655 *                   information about the boot manager
     
    28142657 *                   *BmInfo. Any of these pointers can
    28152658 *                   be NULL if you're not interested.
     2659 *
    28162660 *      -- ERROR_NOT_SUPPORTED (50): boot manager not installed.
    28172661 *
     
    28232667APIRET doshGetBootManager(USHORT   *pusDisk,    // out: if != NULL, boot manager disk (1, 2, ...)
    28242668                          USHORT   *pusPart,    // out: if != NULL, index of bmgr primary partition (0-3)
    2825                           PAR_INFO *BmInfo)     // out: if != NULL, boot manager partition info
     2669                          PAR_INFO *pBmInfo)    // out: if != NULL, boot manager partition info
    28262670{
    28272671    APIRET          arc = NO_ERROR;
     
    28392683        // for each disk, read the MBR, which has the
    28402684        // 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
    28432690            return (arc);
    28442691
    2845         // Lookup BootManager partition
     2692        // scan primary partitions for whether
     2693        // BootManager partition exists
    28462694        for (usPrim = 0; usPrim < 4; usPrim++)
    28472695        {
    28482696            if (MBoot.sPrtnInfo[usPrim].bFileSysCode == 0x0A)
    28492697            {
    2850                 if (BmInfo)
    2851                     *BmInfo = MBoot.sPrtnInfo[usPrim];
     2698                // this is boot manager:
     2699                if (pBmInfo)
     2700                    *pBmInfo = MBoot.sPrtnInfo[usPrim];
    28522701                if (pusPart)
    28532702                    *pusPart = usPrim;
    28542703                if (pusDisk)
    28552704                    *pusDisk = usDisk;
     2705                // stop scanning
    28562706                return (NO_ERROR);
    28572707            }
     
    28682718 *      This gets called from doshGetPartitionsList.
    28692719 *
    2870  *      Returns 0 upon errors.
     2720 *      Returns:
     2721 *
     2722 *      -- ERROR_INVALID_PARAMETER: BMInfo is NULL.
    28712723 *
    28722724 *      Based on code (C) Dmitry A. Steklenev.
     
    28772729APIRET GetPrimaryPartitions(PARTITIONINFO **pppiFirst,
    28782730                            PARTITIONINFO **pppiThis,
    2879                             PUSHORT posCount,    // in/out: partition count
    2880                             PCHAR pcLetter,      // in/out: drive letter counter
    2881                             UINT BmDisk,         // in: physical disk (1, 2, 3, ...) of boot manager or null
    2882                             PAR_INFO* BmInfo,    // in: info returned by doshGetBootManager or NULL
    2883                             UINT iDisk)          // in: system's physical disk count
     2731                            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
    28842736{
    28852737    APIRET  arc = NO_ERROR;
    28862738
    2887     if (!BmInfo)
     2739    if (!pBmInfo)
    28882740        arc = ERROR_INVALID_PARAMETER;
    28892741    else
     
    28922744        memset(&MName, 0, sizeof(MName));
    28932745
    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 (?!?)
    28952749        if (!(arc = doshReadSector(BmDisk,
    28962750                                   &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)))
    29002755        {
     2756            // got bmgr name table:
    29012757            MBR_INFO        MBoot;      // Master Boot
    29022758            USHORT          i;
    29032759
    29042760            // 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
    29062766            {
    29072767                for (i = 0;
     
    29152775                       )
    29162776                    {
    2917                         BOOL fBootable = (  (BmInfo)
    2918                                          && (MName[(iDisk-1) * 4 + i].bootable & 0x01)
     2777                        BOOL fBootable = (    (pBmInfo)
     2778                                           && (MName[(iDisk-1) * 4 + i].bootable & 0x01)
    29192779                                         );
    29202780                        // store this partition
     
    30792939
    30802940/*
     2941 *@@ CleanPartitionInfos:
     2942 *
     2943 *@@added V0.9.9 (2001-04-07) [umoeller]
     2944 */
     2945
     2946VOID CleanPartitionInfos(PPARTITIONINFO ppiThis)
     2947{
     2948    while (ppiThis)
     2949    {
     2950        PPARTITIONINFO ppiNext = ppiThis->pNext;
     2951        free(ppiThis);
     2952        ppiThis = ppiNext;
     2953    }
     2954}
     2955
     2956/*
    30812957 *@@ doshGetPartitionsList:
    30822958 *      this returns lots of information about the
     
    30932969 *      free the resources allocated by this function.
    30942970 *
    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.
    31052991 *
    31062992 *      If an error != NO_ERROR is returned, *pusContext
     
    31132999 *      --  3: secondary partitions error
    31143000 *
     3001 *      --  0: something else.
     3002 *
    31153003 *      Based on code (C) Dmitry A. Steklenev.
    31163004 *
    31173005 *@@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
     3010APIRET doshGetPartitionsList(PPARTITIONSLIST *ppList,
    31223011                             PUSHORT pusContext)                // out: error context
    31233012{
    31243013    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;
    31293016
    31303017    PARTITIONINFO   *pPartitionInfos = NULL, // linked list of all partitions
    31313018                    *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)
    31563033        {
    3157             *pusContext = 2;
    3158             return (arc);
     3034            // error: start over
     3035            doshFreeLVMInfo(pLVMInfo);
     3036            CleanPartitionInfos(pPartitionInfos);
     3037            pPartitionInfos = NULL;
     3038            cPartitions = 0;
    31593039        }
    31603040    }
    31613041
    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)
    31683063        {
    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++)
    31753070            {
    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
     3139APIRET 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
     3164typedef unsigned char       BOOLEAN;
     3165typedef unsigned short int  CARDINAL16;
     3166typedef unsigned long       CARDINAL32;
     3167typedef unsigned int        CARDINAL;
     3168typedef unsigned long       DoubleWord;
     3169
     3170#ifdef ADDRESS
     3171#undef ADDRESS
     3172#endif
     3173
     3174typedef 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
     3190typedef 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
     3210typedef 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
     3223typedef 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
     3240typedef 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
     3334typedef 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
     3347typedef 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
     3414typedef 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
     3456APIRET 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;
    31783506            }
    31793507        }
    31803508    }
    31813509
    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
     3527APIRET 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        }
    32053644    }
    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
     3675VOID 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.