Changeset 69902 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Dec 1, 2017 5:58:28 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/ntfsvfs.cpp
r69889 r69902 50 50 /** The maximum bitmap cache size. */ 51 51 #define RTFSNTFS_MAX_BITMAP_CACHE _64K 52 53 /** Makes a combined NTFS version value. 54 * @see RTFSNTFSVOL::uNtfsVersion */ 55 #define RTFSNTFS_MAKE_VERSION(a_uMajor, a_uMinor) RT_MAKE_U16(a_uMinor, a_uMajor) 52 56 53 57 … … 160 164 * This is needed to validate header relative offsets. */ 161 165 uint32_t offAttrHdrInMftRec; 166 /** Number of resident bytes available (can be smaller than cbValue). 167 * Set to zero for non-resident attributes. */ 168 uint32_t cbResident; 169 /** The (uncompressed) attribute size. */ 170 uint64_t cbValue; 162 171 /** Disk space allocation if non-resident. */ 163 172 RTFSNTFSEXTENTS Extents; … … 185 194 } RTFSNTFSCORE; 186 195 196 /** 197 * Pointer to a shared NTFS directory object. 198 */ 199 typedef struct RTFSNTFSDIRSHRD 200 { 201 /** Reference counter. */ 202 uint32_t volatile cRefs; 203 204 /** Pointer to the core object for the directory (referenced). */ 205 PRTFSNTFSCORE pCore; 206 /** Pointer to the index root attribute. */ 207 PRTFSNTFSATTR pIndexRoot; 208 209 /** Pointer to the index allocation attribute, if present. 210 * This and the bitmap may be absent if the whole directory fits into the 211 * root index. */ 212 PRTFSNTFSATTR pIndexAlloc; 213 /** Pointer to the index allocation bitmap attribute, if present. */ 214 PRTFSNTFSATTR pIndexBitmap; 215 216 } RTFSNTFSDIRSHRD; 217 /** Pointer to a shared NTFS directory object. */ 218 typedef RTFSNTFSDIRSHRD *PRTFSNTFSDIRSHRD; 219 187 220 188 221 /** … … 207 240 uint32_t fNtfsFlags; 208 241 242 /** The (logical) sector size. */ 243 uint32_t cbSector; 244 209 245 /** The (logical) cluster size. */ 210 246 uint32_t cbCluster; 211 /** The (logical) sector size. */212 uint32_t cbSector;213 247 /** Max cluster count value that won't overflow a signed 64-bit when 248 * converted to bytes. Inclusive. */ 249 uint64_t iMaxVirtualCluster; 214 250 /** The shift count for converting between bytes and clusters. */ 215 251 uint8_t cClusterShift; 252 216 253 /** Explicit padding. */ 217 uint8_t abReserved[7]; 254 uint8_t abReserved[3]; 255 /** The NTFS version of the volume (RTFSNTFS_MAKE_VERSION). */ 256 uint16_t uNtfsVersion; 257 /** The NTFS_VOLUME_F_XXX. */ 258 uint16_t fVolumeFlags; 218 259 219 260 /** The logical cluster number of the MFT. */ … … 233 274 PRTFSNTFSATTR pMftData; 234 275 276 /** The root directory. */ 277 PRTFSNTFSDIRSHRD pRootDir; 235 278 236 279 /** @name Allocation bitmap and cache. … … 254 297 /** Root of the MFT record tree (RTFSNTFSMFTREC). */ 255 298 AVLU64TREE MftRoot; 299 256 300 } RTFSNTFSVOL; 257 301 … … 915 959 { 916 960 PNTFSATTRIBHDR pAttrHdr = (PNTFSATTRIBHDR)&pbRec[offRec]; 961 962 /* 963 * Validate the attribute data. 964 */ 917 965 uint32_t const cbAttrib = RT_LE2H_U32(pAttrHdr->cbAttrib); 918 966 uint32_t const cbMin = !pAttrHdr->fNonResident ? NTFSATTRIBHDR_SIZE_RESIDENT … … 927 975 "Bad MFT record %#RX64: Attribute (@%#x) is too long (%#x, cbRecUsed=%#x)", 928 976 pRec->TreeNode.Key, offRec, cbAttrib, cbRecUsed); 977 if (cbAttrib & 0x7) 978 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 979 "Bad MFT record %#RX64: Attribute (@%#x) size is misaligned: %#x", 980 pRec->TreeNode.Key, offRec, cbAttrib); 981 if (pAttrHdr->fNonResident) 982 { 983 int64_t const iVcnFirst = RT_LE2H_U64(pAttrHdr->u.NonRes.iVcnFirst); 984 int64_t const iVcnLast = RT_LE2H_U64(pAttrHdr->u.NonRes.iVcnLast); 985 if (iVcnFirst > iVcnLast) 986 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 987 "Bad MFT record %#RX64: Attribute (@%#x): iVcnFirst (%#RX64) is higher than iVcnLast (%#RX64)", 988 pRec->TreeNode.Key, offRec, iVcnFirst, iVcnLast); 989 if (iVcnFirst < 0) 990 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 991 "Bad MFT record %#RX64: Attribute (@%#x): iVcnFirst (%#RX64) is negative", 992 pRec->TreeNode.Key, offRec, iVcnFirst); 993 if ((uint64_t)iVcnLast > pThis->iMaxVirtualCluster) 994 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 995 "Bad MFT record %#RX64: Attribute (@%#x): iVcnLast (%#RX64) is too high, max %RX64 (shift %#x)", 996 pRec->TreeNode.Key, offRec, iVcnLast, pThis->cClusterShift, pThis->iMaxVirtualCluster); 997 uint16_t const offMappingPairs = RT_LE2H_U16(pAttrHdr->u.NonRes.offMappingPairs); 998 if ( (offMappingPairs != 0 && offMappingPairs < cbMin) 999 || offMappingPairs > cbAttrib) 1000 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1001 "Bad MFT record %#RX64: Attribute (@%#x): offMappingPairs (%#x) is out of bounds (cbAttrib=%#x, cbMin=%#x)", 1002 pRec->TreeNode.Key, offRec, offMappingPairs, cbAttrib, cbMin); 1003 if (pAttrHdr->u.NonRes.uCompressionUnit > 16) 1004 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1005 "Bad MFT record %#RX64: Attribute (@%#x): uCompressionUnit (%#x) is too high", 1006 pRec->TreeNode.Key, offRec, pAttrHdr->u.NonRes.uCompressionUnit); 1007 1008 int64_t const cbAllocated = RT_LE2H_U64(pAttrHdr->u.NonRes.cbAllocated); 1009 if (cbAllocated < 0) 1010 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1011 "Bad MFT record %#RX64: Attribute (@%#x): cbAllocated (%#RX64) is negative", 1012 pRec->TreeNode.Key, offRec, cbAllocated, pThis->cbCluster); 1013 if ((uint64_t)cbAllocated & (pThis->cbCluster - 1)) 1014 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1015 "Bad MFT record %#RX64: Attribute (@%#x): cbAllocated (%#RX64) isn't cluster aligned (cbCluster=%#x)", 1016 pRec->TreeNode.Key, offRec, cbAllocated, pThis->cbCluster); 1017 1018 int64_t const cbData = RT_LE2H_U64(pAttrHdr->u.NonRes.cbData); 1019 if (cbData < 0) 1020 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1021 "Bad MFT record %#RX64: Attribute (@%#x): cbData (%#RX64) is negative", 1022 pRec->TreeNode.Key, offRec, cbData, pThis->cbCluster); 1023 1024 int64_t const cbInitialized = RT_LE2H_U64(pAttrHdr->u.NonRes.cbInitialized); 1025 if (cbInitialized < 0) 1026 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1027 "Bad MFT record %#RX64: Attribute (@%#x): cbInitialized (%#RX64) is negative", 1028 pRec->TreeNode.Key, offRec, cbInitialized, pThis->cbCluster); 1029 if (cbMin >= NTFSATTRIBHDR_SIZE_NONRES_COMPRESSED) 1030 { 1031 int64_t const cbCompressed = RT_LE2H_U64(pAttrHdr->u.NonRes.cbCompressed); 1032 if (cbAllocated < 0) 1033 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1034 "Bad MFT record %#RX64: Attribute (@%#x): cbCompressed (%#RX64) is negative", 1035 pRec->TreeNode.Key, offRec, cbCompressed, pThis->cbCluster); 1036 } 1037 } 1038 else 1039 { 1040 uint16_t const offValue = RT_LE2H_U32(pAttrHdr->u.Res.offValue); 1041 if ( offValue > cbAttrib 1042 || offValue < NTFSATTRIBHDR_SIZE_RESIDENT) 1043 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1044 "Bad MFT record %#RX64: Attribute (@%#x): offValue (%#RX16) is out of bounds (cbAttrib=%#RX32, cbValue=%#RX32)", 1045 pRec->TreeNode.Key, offRec, offValue, cbAttrib, RT_LE2H_U32(pAttrHdr->u.Res.cbValue)); 1046 if ((pAttrHdr->fFlags & NTFS_AF_COMPR_FMT_MASK) != NTFS_AF_COMPR_FMT_NONE) 1047 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1048 "Bad MFT record %#RX64: Attribute (@%#x): fFlags (%#RX16) indicate compression of a resident attribute", 1049 pRec->TreeNode.Key, offRec, RT_LE2H_U16(pAttrHdr->fFlags)); 1050 } 1051 1052 if (pAttrHdr->cwcName != 0) 1053 { 1054 uint16_t offName = RT_LE2H_U16(pAttrHdr->offName); 1055 if ( offName < cbMin 1056 || offName >= cbAttrib) 1057 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1058 "Bad MFT record %#RX64: Attribute (@%#x): offName (%#RX16) is out of bounds (cbAttrib=%#RX32, cbMin=%#RX32)", 1059 pRec->TreeNode.Key, offRec, offName, cbAttrib, cbMin); 1060 if (offName + pAttrHdr->cwcName * sizeof(RTUTF16) > cbAttrib) 1061 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1062 "Bad MFT record %#RX64: Attribute (@%#x): offName (%#RX16) + cwcName (%#x) is out of bounds (cbAttrib=%#RX32)", 1063 pRec->TreeNode.Key, offRec, offName, pAttrHdr->cwcName, cbAttrib); 1064 } 1065 1066 /* 1067 * Allocate and initialize a new attribute. 1068 */ 929 1069 PRTFSNTFSATTR pAttrib = (PRTFSNTFSATTR)RTMemAllocZ(sizeof(*pAttrib)); 930 1070 AssertReturn(pAttrib, VERR_NO_MEMORY); … … 932 1072 pAttrib->offAttrHdrInMftRec = offRec; 933 1073 pAttrib->pCore = pCore; 1074 //pAttrib->cbResident = 0; 1075 //pAttrib->cbValue = 0; 934 1076 //pAttrib->Extents.cExtents = 0; 935 1077 //pAttrib->Extents.paExtents = NULL; … … 937 1079 if (pAttrHdr->fNonResident) 938 1080 { 1081 pAttrib->cbValue = RT_LE2H_U64(pAttrHdr->u.NonRes.cbData); 939 1082 int rc = rtFsNtfsAttr_ParseExtents(pAttrib, &pAttrib->Extents, pThis->cClusterShift, 0 /*iVncFirst*/, 940 1083 pThis->cbVolume, pErrInfo, pRec->TreeNode.Key, offRec); … … 945 1088 } 946 1089 } 1090 else 1091 { 1092 pAttrib->cbValue = RT_LE2H_U32(pAttrHdr->u.Res.cbValue); 1093 if ( (uint32_t)pAttrib->cbValue > 0 1094 && RT_LE2H_U16(pAttrHdr->u.Res.offValue) < cbAttrib) 1095 { 1096 pAttrib->cbResident = cbAttrib - RT_LE2H_U16(pAttrHdr->u.Res.offValue); 1097 if (pAttrib->cbResident > (uint32_t)pAttrib->cbValue) 1098 pAttrib->cbResident = (uint32_t)pAttrib->cbValue; 1099 } 1100 } 1101 947 1102 RTListAppend(&pCore->AttribHead, &pAttrib->ListEntry); 948 1103 … … 1280 1435 1281 1436 /** 1437 * Finds a named attribute, case insensitive ASCII variant. 1438 * 1439 * @returns Pointer to the attribute structure if found, NULL if not. 1440 * @param pThis The core object structure to search. 1441 * @param uAttrType The attribute type to find. 1442 * @param pszAttrib The attribute name, predefined 7-bit ASCII name. 1443 * @param cchAttrib The length of the attribute. 1444 */ 1445 static PRTFSNTFSATTR rtFsNtfsCore_FindNamedAttributeAscii(PRTFSNTFSCORE pThis, uint32_t uAttrType, 1446 const char *pszAttrib, size_t cchAttrib) 1447 { 1448 Assert(cchAttrib > 0); 1449 PRTFSNTFSATTR pCurAttr; 1450 RTListForEach(&pThis->AttribHead, pCurAttr, RTFSNTFSATTR, ListEntry) 1451 { 1452 PNTFSATTRIBHDR pAttrHdr = pCurAttr->pAttrHdr; 1453 if ( pAttrHdr->uAttrType == uAttrType 1454 && pAttrHdr->cwcName == cchAttrib 1455 && RTUtf16NICmpAscii(NTFSATTRIBHDR_GET_NAME(pAttrHdr), pszAttrib, cchAttrib) == 0) 1456 return pCurAttr; 1457 } 1458 return NULL; 1459 } 1460 1461 1462 1463 /* 1464 * 1465 * NTFS directory code. 1466 * NTFS directory code. 1467 * NTFS directory code. 1468 * 1469 */ 1470 1471 1472 static int rtFsNtfsVol_NewSharedDirFromCore(PRTFSNTFSVOL pThis, PRTFSNTFSCORE pCore, PRTFSNTFSDIRSHRD *ppSharedDir, 1473 PRTERRINFO pErrInfo, const char *pszWhat) 1474 { 1475 *ppSharedDir = NULL; 1476 1477 /* 1478 * Look for the index root and do some quick checks of it first. 1479 */ 1480 PRTFSNTFSATTR pRootAttr = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME, 1481 NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_INDEX_ROOT); 1482 if (!pRootAttr) 1483 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "%s: Found no INDEX_ROOT attribute named $I30", pszWhat); 1484 if (pRootAttr->pAttrHdr->fNonResident) 1485 return RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, "%s: INDEX_ROOT is is not resident", pszWhat); 1486 1487 1488 #if 1 /* later */ 1489 NOREF(pThis); 1490 #else 1491 /* 1492 * 1493 */ 1494 PRTFSNTFSATTR pAllocAttr = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME, 1495 NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_INDEX_ALLOCATION); 1496 PRTFSNTFSATTR pBitmapAttr = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME, 1497 NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_BITMAP); 1498 #endif 1499 return VINF_SUCCESS; 1500 } 1501 1502 1503 /* 1504 * 1505 * Volume level code. 1506 * Volume level code. 1507 * Volume level code. 1508 * 1509 */ 1510 1511 1512 /** 1282 1513 * Slow path for querying the allocation state of a cluster. 1283 1514 * … … 1538 1769 1539 1770 /** 1771 * Loads, validates and setups the '.' (NTFS_MFT_IDX_ROOT) MFT entry. 1772 * 1773 * @returns IPRT status code 1774 * @param pThis The NTFS volume instance. Will set pawcUpcase. 1775 * @param pErrInfo Where to return additional error info. 1776 */ 1777 static int rtFsNtfsVolLoadRootDir(PRTFSNTFSVOL pThis, PRTERRINFO pErrInfo) 1778 { 1779 /* 1780 * Load it and do some checks. 1781 */ 1782 PRTFSNTFSCORE pCore; 1783 int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_ROOT, &pCore, pErrInfo); 1784 if (RT_SUCCESS(rc)) 1785 { 1786 PRTFSNTFSATTR pFilenameAttr = rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_FILENAME); 1787 if (!pFilenameAttr) 1788 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "RootDir: has no FILENAME attribute!"); 1789 else if (pFilenameAttr->pAttrHdr->fNonResident) 1790 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "RootDir: FILENAME attribute is non-resident!"); 1791 else if (pFilenameAttr->pAttrHdr->u.Res.cbValue < RT_UOFFSETOF(NTFSATFILENAME, wszFilename[1])) 1792 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1793 "RootDir: FILENAME attribute value size is too small: %#x", 1794 pFilenameAttr->pAttrHdr->u.Res.cbValue); 1795 else 1796 { 1797 PNTFSATFILENAME pFilename = (PNTFSATFILENAME)( (uint8_t *)pFilenameAttr->pAttrHdr 1798 + pFilenameAttr->pAttrHdr->u.Res.offValue); 1799 if ( pFilename->cwcFilename != 1 1800 || ( RTUtf16NICmpAscii(pFilename->wszFilename, ".", 1) != 0 1801 && RTUtf16NICmpAscii(pFilename->wszFilename, "$", 1) != 0)) 1802 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1803 "RootDir: FILENAME is not '.' nor '$: '%.*ls'", 1804 pFilename->cwcFilename, pFilename->wszFilename); 1805 else 1806 { 1807 PRTFSNTFSATTR pIndexRoot = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME, 1808 NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_INDEX_ROOT); 1809 PRTFSNTFSATTR pIndexAlloc = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME, 1810 NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_INDEX_ALLOCATION); 1811 PRTFSNTFSATTR pIndexBitmap = rtFsNtfsCore_FindNamedAttributeAscii(pCore, NTFS_AT_FILENAME, 1812 NTFS_DIR_ATTRIBUTE_NAME, NTFS_AT_BITMAP); 1813 if (!pIndexRoot) 1814 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "RootDir: Found no INDEX_ROOT attribute named $I30"); 1815 else if (!pIndexAlloc && pIndexBitmap) 1816 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "RootDir: Found no INDEX_ALLOCATION attribute named $I30"); 1817 else if (!pIndexBitmap && pIndexAlloc) 1818 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "RootDir: Found no BITMAP attribute named $I30"); 1819 if (RT_SUCCESS(rc) && pIndexAlloc) 1820 rc = rtFsNtfsVolCheckBitmap(pThis, pIndexAlloc, "RootDir", pErrInfo); 1821 if (RT_SUCCESS(rc) && pIndexBitmap) 1822 rc = rtFsNtfsVolCheckBitmap(pThis, pIndexBitmap, "RootDir/bitmap", pErrInfo); 1823 if (RT_SUCCESS(rc)) 1824 { 1825 /* 1826 * Load it as a normal directory. 1827 */ 1828 PRTFSNTFSDIRSHRD pSharedDir; 1829 rc = rtFsNtfsVol_NewSharedDirFromCore(pThis, pCore, &pSharedDir, pErrInfo, "RootDir"); 1830 if (RT_SUCCESS(rc)) 1831 { 1832 rtFsNtfsCore_Release(pCore); 1833 pThis->pRootDir = pSharedDir; 1834 return VINF_SUCCESS; 1835 } 1836 } 1837 } 1838 } 1839 rtFsNtfsCore_Release(pCore); 1840 } 1841 else 1842 rc = RTERRINFO_LOG_REL_SET(pErrInfo, rc, "Root dir: Error reading MFT record"); 1843 return rc; 1844 } 1845 1846 1847 /** 1540 1848 * Loads, validates and setups the '$UpCase' (NTFS_MFT_IDX_UP_CASE) MFT entry. 1541 1849 * … … 1561 1869 uint32_t const cbMax = _128K; 1562 1870 if (!pDataAttr->pAttrHdr->fNonResident) 1563 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$UpCase aunnamed DATA attribute is resident!");1871 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$UpCase: unnamed DATA attribute is resident!"); 1564 1872 else if ( (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated) < cbMin 1565 1873 || (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated) > cbMax) 1566 1874 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",1875 "$UpCase: unnamed DATA attribute allocated size is out of range: %#RX64, expected at least %#RX32 and no more than %#RX32", 1568 1876 RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated), cbMin, cbMax); 1569 1877 else if ( (uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbData) < cbMin … … 1572 1880 || ((uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbData) & 1) ) 1573 1881 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",1882 "$UpCase: unnamed DATA attribute initialized size is out of range: %#RX64, expected at least %#RX32 and no more than %#RX64", 1575 1883 RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbData), cbMin, 1576 1884 RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated) ); … … 1580 1888 || ((uint64_t)RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbInitialized) & 1) ) 1581 1889 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",1890 "$UpCase: unnamed DATA attribute initialized size is out of range: %#RX64, expected at least %#RX32 and no more than %#RX64", 1583 1891 RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbInitialized), cbMin, 1584 1892 RT_LE2H_U64(pDataAttr->pAttrHdr->u.NonRes.cbAllocated) ); 1585 1893 else if (pDataAttr->pAttrHdr->u.NonRes.uCompressionUnit != 0) 1586 1894 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1587 "$UpCase unnamed DATA attribute is compressed: %#x",1895 "$UpCase: unnamed DATA attribute is compressed: %#x", 1588 1896 pDataAttr->pAttrHdr->u.NonRes.uCompressionUnit); 1589 1897 else … … 1596 1904 else if (pFilenameAttr->pAttrHdr->u.Res.cbValue < RT_UOFFSETOF(NTFSATFILENAME, wszFilename[7])) 1597 1905 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1598 "$UpCase FILENAME attribute value size is too small: %#x",1906 "$UpCase: FILENAME attribute value size is too small: %#x", 1599 1907 pFilenameAttr->pAttrHdr->u.Res.cbValue); 1600 1908 else … … 1605 1913 || RTUtf16NICmpAscii(pFilename->wszFilename, "$UpCase", 7) != 0) 1606 1914 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1607 "$UpCase FILENAME isn't '$UpCase': '%.*ls'",1915 "$UpCase: FILENAME isn't '$UpCase': '%.*ls'", 1608 1916 pFilename->cwcFilename, pFilename->wszFilename); 1609 1917 else … … 1651 1959 } 1652 1960 else 1653 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, " MFT record #0has no unnamed DATA attribute!");1961 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$UpCase: has no unnamed DATA attribute!"); 1654 1962 rtFsNtfsCore_Release(pCore); 1655 1963 } 1656 1964 else 1657 rc = RTERRINFO_LOG_REL_SET(pErrInfo, rc, " Error reading $UpCase MFT record");1965 rc = RTERRINFO_LOG_REL_SET(pErrInfo, rc, "$UpCase: Error reading the MFT record"); 1658 1966 return rc; 1659 1967 } … … 1691 1999 || (uint64_t)RT_LE2H_U64(pMftBitmap->pAttrHdr->u.NonRes.cbAllocated) > cbMaxBitmap) 1692 2000 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1693 " MFT record #6unnamed DATA attribute allocated size is out of range: %#RX64, expected at least %#RX64 and no more than %#RX64",2001 "$Bitmap: unnamed DATA attribute allocated size is out of range: %#RX64, expected at least %#RX64 and no more than %#RX64", 1694 2002 RT_LE2H_U64(pMftBitmap->pAttrHdr->u.NonRes.cbAllocated), cbMinBitmap, cbMaxBitmap); 1695 2003 else if ( (uint64_t)RT_LE2H_U64(pMftBitmap->pAttrHdr->u.NonRes.cbData) < cbMinBitmap … … 1697 2005 > (uint64_t)RT_LE2H_U64(pMftBitmap->pAttrHdr->u.NonRes.cbData)) 1698 2006 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1699 " MFT record #6unnamed DATA attribute initialized size is out of range: %#RX64, expected at least %#RX64 and no more than %#RX64",2007 "$Bitmap: unnamed DATA attribute initialized size is out of range: %#RX64, expected at least %#RX64 and no more than %#RX64", 1700 2008 RT_LE2H_U64(pMftBitmap->pAttrHdr->u.NonRes.cbData), cbMinBitmap, 1701 2009 RT_LE2H_U64(pMftBitmap->pAttrHdr->u.NonRes.cbAllocated) ); … … 1704 2012 > (uint64_t)RT_LE2H_U64(pMftBitmap->pAttrHdr->u.NonRes.cbAllocated)) 1705 2013 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1706 " MFT record #6unnamed DATA attribute initialized size is out of range: %#RX64, expected at least %#RX64 and no more than %#RX64",2014 "$Bitmap: unnamed DATA attribute initialized size is out of range: %#RX64, expected at least %#RX64 and no more than %#RX64", 1707 2015 RT_LE2H_U64(pMftBitmap->pAttrHdr->u.NonRes.cbInitialized), cbMinBitmap, 1708 2016 RT_LE2H_U64(pMftBitmap->pAttrHdr->u.NonRes.cbAllocated) ); 1709 2017 else if (pMftBitmap->pAttrHdr->u.NonRes.uCompressionUnit != 0) 1710 2018 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1711 " MFT record #6unnamed DATA attribute is compressed: %#x",2019 "$Bitmap: unnamed DATA attribute is compressed: %#x", 1712 2020 pMftBitmap->pAttrHdr->u.NonRes.uCompressionUnit); 1713 2021 else if (pMftBitmap->Extents.cExtents != 1) /* paranoia for now */ 1714 2022 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1715 " MFT record #6unnamed DATA attribute is expected to have a single extent: %u extents",2023 "$Bitmap: unnamed DATA attribute is expected to have a single extent: %u extents", 1716 2024 pMftBitmap->Extents.cExtents); 1717 2025 else if (pMftBitmap->Extents.paExtents[0].off == UINT64_MAX) … … 1726 2034 else if (pFilenameAttr->pAttrHdr->u.Res.cbValue < RT_UOFFSETOF(NTFSATFILENAME, wszFilename[7])) 1727 2035 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1728 " MFT record #6FILENAME attribute value size is too small: %#x",2036 "$Bitmap FILENAME attribute value size is too small: %#x", 1729 2037 pFilenameAttr->pAttrHdr->u.Res.cbValue); 1730 2038 else … … 1735 2043 || RTUtf16NICmpAscii(pFilename->wszFilename, "$Bitmap", 7) != 0) 1736 2044 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 1737 " MFT record #6FILENAME isn't '$Bitmap': '%.*ls'",2045 "$Bitmap: FILENAME isn't '$Bitmap': '%.*ls'", 1738 2046 pFilename->cwcFilename, pFilename->wszFilename); 1739 2047 else … … 1774 2082 } 1775 2083 else 1776 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, " MFT record #0has no unnamed DATA attribute!");2084 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$Bitmap: has no unnamed DATA attribute!"); 1777 2085 rtFsNtfsCore_Release(pCore); 1778 2086 } 1779 2087 else 1780 rc = RTERRINFO_LOG_REL_SET(pErrInfo, rc, "Error reading MFT record #6"); 2088 rc = RTERRINFO_LOG_REL_SET(pErrInfo, rc, "$Bitmap: Error MFT record"); 2089 return rc; 2090 } 2091 2092 2093 /** 2094 * Loads, validates and setups the '$Volume' (NTFS_MFT_IDX_VOLUME) MFT entry. 2095 * 2096 * @returns IPRT status code 2097 * @param pThis The NTFS volume instance. Will set uNtfsVersion 2098 * and fVolumeFlags. 2099 * @param pErrInfo Where to return additional error info. 2100 */ 2101 static int rtFsNtfsVolLoadVolumeInfo(PRTFSNTFSVOL pThis, PRTERRINFO pErrInfo) 2102 { 2103 PRTFSNTFSCORE pCore; 2104 int rc = rtFsNtfsVol_NewCoreForMftIdx(pThis, NTFS_MFT_IDX_VOLUME, &pCore, pErrInfo); 2105 if (RT_SUCCESS(rc)) 2106 { 2107 PRTFSNTFSATTR pVolInfoAttr = rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_VOLUME_INFORMATION); 2108 if (pVolInfoAttr) 2109 { 2110 /* 2111 * Validate the '$Volume' MFT record. 2112 */ 2113 if (pVolInfoAttr->pAttrHdr->fNonResident) 2114 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$Volume unnamed VOLUME_INFORMATION attribute is not resident!"); 2115 else if ( pVolInfoAttr->cbResident != sizeof(NTFSATVOLUMEINFO) 2116 || pVolInfoAttr->cbValue != sizeof(NTFSATVOLUMEINFO)) 2117 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 2118 "$Volume VOLUME_INFORMATION attribute has the wrong size: cbValue=%#RX64, cbResident=%#RX32, expected %#x\n", 2119 pVolInfoAttr->cbValue, pVolInfoAttr->cbResident, sizeof(NTFSATVOLUMEINFO)); 2120 else 2121 { 2122 PRTFSNTFSATTR pFilenameAttr = rtFsNtfsCore_FindUnnamedAttribute(pCore, NTFS_AT_FILENAME); 2123 if (!pFilenameAttr) 2124 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$Volume has no FILENAME attribute!"); 2125 else if (pFilenameAttr->pAttrHdr->fNonResident) 2126 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, "$Volume FILENAME attribute is non-resident!"); 2127 else if (pFilenameAttr->pAttrHdr->u.Res.cbValue < RT_UOFFSETOF(NTFSATFILENAME, wszFilename[7])) 2128 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 2129 "$Volume FILENAME attribute value size is too small: %#x", 2130 pFilenameAttr->pAttrHdr->u.Res.cbValue); 2131 else 2132 { 2133 PNTFSATFILENAME pFilename = (PNTFSATFILENAME)( (uint8_t *)pFilenameAttr->pAttrHdr 2134 + pFilenameAttr->pAttrHdr->u.Res.offValue); 2135 if ( pFilename->cwcFilename != 7 2136 || RTUtf16NICmpAscii(pFilename->wszFilename, "$Volume", 7) != 0) 2137 rc = RTERRINFO_LOG_REL_SET_F(pErrInfo, VERR_VFS_BOGUS_FORMAT, 2138 "$Volume FILENAME isn't '$Volume': '%.*ls'", 2139 pFilename->cwcFilename, pFilename->wszFilename); 2140 else 2141 { 2142 /* 2143 * Look at the information. 2144 */ 2145 PCNTFSATVOLUMEINFO pVolInfo; 2146 pVolInfo = (PCNTFSATVOLUMEINFO)((uint8_t *)pVolInfoAttr->pAttrHdr + pVolInfoAttr->pAttrHdr->u.Res.offValue); 2147 pThis->uNtfsVersion = RTFSNTFS_MAKE_VERSION(pVolInfo->uMajorVersion, pVolInfo->uMinorVersion); 2148 pThis->fVolumeFlags = RT_LE2H_U16(pVolInfo->fFlags); 2149 Log(("NTFS: Version %u.%u, flags=%#x\n", pVolInfo->uMajorVersion, pVolInfo->uMinorVersion, pThis->fVolumeFlags)); 2150 2151 /* We're done, no need for special success return here though. */ 2152 } 2153 } 2154 } 2155 } 2156 else 2157 rc = RTERRINFO_LOG_REL_SET(pErrInfo, VERR_VFS_BOGUS_FORMAT, 2158 "MFT record $Volume has no unnamed VOLUME_INFORMATION attribute!"); 2159 rtFsNtfsCore_Release(pCore); 2160 } 2161 else 2162 rc = RTERRINFO_LOG_REL_SET(pErrInfo, rc, "Error reading $Volume MFT record"); 1781 2163 return rc; 1782 2164 } … … 1958 2340 pThis->cClusterShift = ASMBitFirstSetU32(pThis->cbCluster) - 1; 1959 2341 Log2(("NTFS BPB: cClusterPerSector=%#x => %#x bytes, %u shift\n", cClusterPerSector, pThis->cbCluster, pThis->cClusterShift)); 2342 pThis->iMaxVirtualCluster = (uint64_t)INT64_MAX >> pThis->cClusterShift; 2343 Log2(("NTFS BPB: iMaxVirtualCluster=%#RX64\n", pThis->iMaxVirtualCluster)); 1960 2344 1961 2345 /* NTFS BPB: cSectors. */ … … 2074 2458 rc = rtFsNtfsVolLoadMft(pThis, pErrInfo); 2075 2459 if (RT_SUCCESS(rc)) 2460 rc = rtFsNtfsVolLoadVolumeInfo(pThis, pErrInfo); 2461 if (RT_SUCCESS(rc)) 2076 2462 rc = rtFsNtfsVolLoadBitmap(pThis, pErrInfo); 2077 2463 if (RT_SUCCESS(rc)) 2078 2464 rc = rtFsNtfsVolLoadUpCase(pThis, pErrInfo); 2465 if (RT_SUCCESS(rc)) 2466 rc = rtFsNtfsVolLoadRootDir(pThis, pErrInfo); 2079 2467 RTMemTmpFree(pvBuf); 2080 2468 if (RT_SUCCESS(rc))
Note:
See TracChangeset
for help on using the changeset viewer.