VirtualBox

Changeset 69889 in vbox


Ignore:
Timestamp:
Nov 30, 2017 6:28:41 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119354
Message:

iprt/ntfsvfs.cpp: Implemented loading the '$UpCase' table.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp

    r69888 r69889  
    247247    void           *pvBitmap;
    248248    /** @} */
     249
     250    /** Lower to uppercase conversion table for this filesystem.
     251     * This always has 64K valid entries.  */
     252    PRTUTF16        pawcUpcase;
    249253
    250254    /** Root of the MFT record tree (RTFSNTFSMFTREC). */
     
    11631167
    11641168
    1165 
    11661169/**
    11671170 * Destroys a core structure.
     
    15311534        pTable = &pSubRec->Extents;
    15321535    }
     1536}
     1537
     1538
     1539/**
     1540 * Loads, validates and setups the '$UpCase' (NTFS_MFT_IDX_UP_CASE) MFT entry.
     1541 *
     1542 * This is needed for filename lookups, I think.
     1543 *
     1544 * @returns IPRT status code
     1545 * @param   pThis               The NTFS volume instance.  Will set pawcUpcase.
     1546 * @param   pErrInfo            Where to return additional error info.
     1547 */
     1548static int rtFsNtfsVolLoadUpCase(PRTFSNTFSVOL pThis, PRTERRINFO pErrInfo)
     1549{
     1550    PRTFSNTFSCORE pCore;
     1551    int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_UP_CASE, &pCore, pErrInfo);
     1552    if (RT_SUCCESS(rc))
     1553    {
     1554        PRTFSNTFSATTR pDataAttr = rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_DATA);
     1555        if (pDataAttr)
     1556        {
     1557            /*
     1558             * Validate the '$Upcase' MFT record.
     1559             */
     1560            uint32_t const cbMin = 512;
     1561            uint32_t const cbMax = _128K;
     1562            if (!pDataAttr->pAttrHdr->fNonResident)
     1563                rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$UpCasea unnamed DATA attribute is resident!");
     1564            else if (   (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated) < cbMin
     1565                     || (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated) > cbMax)
     1566                rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
     1567                                             "$UpCase unnamed DATA attribute allocated size is out of range: %#RX64, expected at least %#RX32 and no more than %#RX32",
     1568                                             RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated), cbMin, cbMax);
     1569            else if (   (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbData) < cbMin
     1570                     ||   (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbData)
     1571                        > (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbData)
     1572                     || ((uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbData) & 1) )
     1573                rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
     1574                                             "$UpCase unnamed DATA attribute initialized size is out of range: %#RX64, expected at least %#RX32 and no more than %#RX64",
     1575                                             RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbData), cbMin,
     1576                                             RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated) );
     1577            else if (   (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbInitialized) < cbMin
     1578                     ||    (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbInitialized)
     1579                         > (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated)
     1580                     || ((uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbInitialized) & 1) )
     1581                rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
     1582                                             "$UpCase unnamed DATA attribute initialized size is out of range: %#RX64, expected at least %#RX32 and no more than %#RX64",
     1583                                             RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbInitialized), cbMin,
     1584                                             RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated) );
     1585            else if (pDataAttr->pAttrHdr->u.NonRes.uCompressionUnit != 0)
     1586                rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
     1587                                             "$UpCase unnamed DATA attribute is compressed: %#x",
     1588                                             pDataAttr->pAttrHdr->u.NonRes.uCompressionUnit);
     1589            else
     1590            {
     1591                PRTFSNTFSATTR pFilenameAttr = rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_FILENAME);
     1592                if (!pFilenameAttr)
     1593                    rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$UpCase has no FILENAME attribute!");
     1594                else if (pFilenameAttr->pAttrHdr->fNonResident)
     1595                    rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$UpCase FILENAME attribute is non-resident!");
     1596                else if (pFilenameAttr->pAttrHdr->u.Res.cbValue < RT_UOFFSETOF(NTFSATFILENAME, wszFilename[7]))
     1597                    rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
     1598                                                 "$UpCase FILENAME attribute value size is too small: %#x",
     1599                                                 pFilenameAttr->pAttrHdr->u.Res.cbValue);
     1600                else
     1601                {
     1602                    PNTFSATFILENAME pFilename = (PNTFSATFILENAME)(  (uint8_t *)pFilenameAttr->pAttrHdr
     1603                                                                  + pFilenameAttr->pAttrHdr->u.Res.offValue);
     1604                    if (   pFilename->cwcFilename != 7
     1605                        || RTUtf16NICmpAscii(pFilename->wszFilename, "$UpCase", 7) != 0)
     1606                        rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
     1607                                                     "$UpCase FILENAME isn't '$UpCase': '%.*ls'",
     1608                                                     pFilename->cwcFilename, pFilename->wszFilename);
     1609                    else
     1610                    {
     1611                        /*
     1612                         * Allocate memory for the uppercase table and read it.
     1613                         */
     1614                        PRTUTF16 pawcUpcase;
     1615                        pThis->pawcUpcase = pawcUpcase = (PRTUTF16)RTMemAlloc(_64K * sizeof(pThis->pawcUpcase[0]));
     1616                        if (pawcUpcase)
     1617                        {
     1618                            for (size_t i = 0; i < _64K; i++)
     1619                                pawcUpcase[i] = (uint16_t)i;
     1620
     1621                            rc = rtFsNtfsAttr_Read(pDataAttr, 0, pawcUpcase, pDataAttr->pAttrHdr->u.NonRes.cbData);
     1622                            if (RT_SUCCESS(rc))
     1623                            {
     1624                                /*
     1625                                 * Check the data.
     1626                                 */
     1627                                for (size_t i = 1; i < _64K; i++)
     1628                                    if (pawcUpcase[i] == 0)
     1629                                    {
     1630                                        rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT,
     1631                                                                     "$UpCase entry %#x is zero!", i);
     1632                                        break;
     1633                                    }
     1634
     1635                                /*
     1636                                 * While we still have the $UpCase file open, check it against the allocation bitmap.
     1637                                 */
     1638                                if (RT_SUCCESS(rc))
     1639                                    rc = rtFsNtfsVolCheckBitmap(pThis, pDataAttr, "$UpCase", pErrInfo);
     1640
     1641                                /* We're done, no need for special success return here though. */
     1642                            }
     1643                            else
     1644                                rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, rc, "Error reading $UpCase data into memory");
     1645                        }
     1646                        else
     1647                            rc = VERR_NO_MEMORY;
     1648                    }
     1649                }
     1650            }
     1651        }
     1652        else
     1653            rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "MFT record #0 has no unnamed DATA attribute!");
     1654        rtFsNtfsCore_Release(pCore);
     1655    }
     1656    else
     1657        rc = RTERRINFO_LOG_REL_SET(pErrInfo, rc, "Error reading $UpCase MFT record");
     1658    return rc;
    15331659}
    15341660
     
    16551781    return rc;
    16561782}
    1657 
    16581783
    16591784
     
    19502075                if (RT_SUCCESS(rc))
    19512076                    rc = rtFsNtfsVolLoadBitmap(pThis, pErrInfo);
     2077                if (RT_SUCCESS(rc))
     2078                    rc = rtFsNtfsVolLoadUpCase(pThis, pErrInfo);
    19522079                RTMemTmpFree(pvBuf);
    19532080                if (RT_SUCCESS(rc))
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette