Changeset 69902 in vbox
- Timestamp:
- Dec 1, 2017 5:58:28 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 119378
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/formats/ntfs.h
r69885 r69902 202 202 #define NTFS_AT_SECURITY_DESCRIPTOR RT_H2LE_U32_C(UINT32_C(0x00000050)) 203 203 #define NTFS_AT_VOLUME_NAME RT_H2LE_U32_C(UINT32_C(0x00000060)) 204 /** NTFSATVOLUMEINFO */ 204 205 #define NTFS_AT_VOLUME_INFORMATION RT_H2LE_U32_C(UINT32_C(0x00000070)) 205 206 #define NTFS_AT_DATA RT_H2LE_U32_C(UINT32_C(0x00000080)) 207 /** NTFSATINDEXROOT */ 206 208 #define NTFS_AT_INDEX_ROOT RT_H2LE_U32_C(UINT32_C(0x00000090)) 207 209 #define NTFS_AT_INDEX_ALLOCATION RT_H2LE_U32_C(UINT32_C(0x000000a0)) … … 218 220 /** @name NTFS_AF_XXX - Attribute flags. 219 221 * @{ */ 220 #define NTFS_AF_COMPR_FMT_NONE UINT16_C(0x0000) 221 #define NTFS_AF_COMPR_FMT_LZNT1 UINT16_C(0x0001) /**< See RtlCompressBuffer / COMPRESSION_FORMAT_LZNT1. */ 222 #define NTFS_AF_COMPR_FMT_XPRESS UINT16_C(0x0002) /**< See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */ 223 #define NTFS_AF_COMPR_FMT_XPRESS_HUFF UINT16_C(0x0003) /**< See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */ 224 #define NTFS_AF_COMPR_FMT_MASK UINT16_C(0x00ff) 225 #define NTFS_AF_ENCRYPTED UINT16_C(0x4000) 226 #define NTFS_AF_SPARSE UINT16_C(0x8000) 222 #define NTFS_AF_COMPR_FMT_NONE RT_H2LE_U16_C(UINT16_C(0x0000)) 223 /** See RtlCompressBuffer / COMPRESSION_FORMAT_LZNT1. */ 224 #define NTFS_AF_COMPR_FMT_LZNT1 RT_H2LE_U16_C(UINT16_C(0x0001)) 225 /** See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */ 226 #define NTFS_AF_COMPR_FMT_XPRESS RT_H2LE_U16_C(UINT16_C(0x0002)) 227 /** See RtlCompressBuffer / COMPRESSION_FORMAT_XPRESS_HUFF. */ 228 #define NTFS_AF_COMPR_FMT_XPRESS_HUFF RT_H2LE_U16_C(UINT16_C(0x0003)) 229 #define NTFS_AF_COMPR_FMT_MASK RT_H2LE_U16_C(UINT16_C(0x00ff)) 230 #define NTFS_AF_ENCRYPTED RT_H2LE_U16_C(UINT16_C(0x4000)) 231 #define NTFS_AF_SPARSE RT_H2LE_U16_C(UINT16_C(0x8000)) 227 232 /** @} */ 228 233 … … 294 299 * @note Only set in the first attribute record (iVcnFirst == 0). */ 295 300 int64_t cbData; 296 /** 0x38: The length of the initialized data (rounded to cluster). 301 /** 0x38: The length of the initialized data. (Not necessarily 302 * rounded up to cluster size.) 297 303 * @note Only set in the first attribute record (iVcnFirst == 0). */ 298 304 int64_t cbInitialized; … … 322 328 /** @} */ 323 329 330 /** Get the pointer to the embedded name from an attribute. 331 * @note ASSUMES the caller check that there is a name. */ 332 #define NTFSATTRIBHDR_GET_NAME(a_pAttrHdr) ( (PRTUTF16)((uintptr_t)(a_pAttrHdr) + (a_pAttrHdr)->offName) ) 333 334 335 /** @name NTFS_RES_AF_XXX 336 * @{ */ 337 /** Attribute is referenced in an index. */ 338 #define NTFS_RES_AF_INDEXED UINT8_C(0x01) 339 /** @} */ 324 340 325 341 /** … … 487 503 /** @} */ 488 504 505 506 /** 507 * NTFS volume information (NTFS_AT_VOLUME_INFORMATION). 508 * 509 * This is found in the special NTFS_MFT_IDX_VOLUME file. 510 */ 511 typedef struct NTFSATVOLUMEINFO 512 { 513 /** 0x00: Reserved bytes. */ 514 uint8_t abReserved[8]; 515 /** 0x08: Major NTFS version number. */ 516 uint8_t uMajorVersion; 517 /** 0x09: Minor NTFS version number. */ 518 uint8_t uMinorVersion; 519 /** 0x0a: Volume flags (NTFS_VOLUME_F_XXX) */ 520 uint16_t fFlags; 521 } NTFSATVOLUMEINFO; 522 AssertCompileSize(NTFSATVOLUMEINFO, 12); 523 /** Pointer to NTFS volume information. */ 524 typedef NTFSATVOLUMEINFO *PNTFSATVOLUMEINFO; 525 /** Pointer to const NTFS volume information. */ 526 typedef NTFSATVOLUMEINFO const *PCNTFSATVOLUMEINFO; 527 528 /** @name NTFS_VOLUME_F_XXX 529 * @{ */ 530 #define NTFS_VOLUME_F_DIRTY RT_H2LE_U16_C(0x0001) /**< Volume is dirty. */ 531 #define NTFS_VOLUME_F_RESIZE_LOG_FILE RT_H2LE_U16_C(0x0002) /**< */ 532 #define NTFS_VOLUME_F_UPGRADE_ON_MOUNT RT_H2LE_U16_C(0x0004) /**< */ 533 #define NTFS_VOLUME_F_MOUNTED_ON_NT4 RT_H2LE_U16_C(0x0008) /**< */ 534 #define NTFS_VOLUME_F_DELETE_USN_UNDERWAY RT_H2LE_U16_C(0x0010) /**< */ 535 #define NTFS_VOLUME_F_REPAIR_OBJECT_ID RT_H2LE_U16_C(0x0020) /**< */ 536 #define NTFS_VOLUME_F_CHKDSK_UNDERWAY RT_H2LE_U16_C(0x4000) /**< */ 537 #define NTFS_VOLUME_F_MODIFIED_BY_CHKDSK RT_H2LE_U16_C(0x8000) /**< */ 538 539 #define NTFS_VOLUME_F_KNOWN_MASK RT_H2LE_U16_C(0xc03f) 540 #define NTFS_VOLUME_F_MOUNT_READONLY_MASK RT_H2LE_U16_C(0xc027) 541 /** @} */ 542 543 544 /** The attribute name used by the index attributes on NTFS directories, 545 * ASCII stirng variant. */ 546 #define NTFS_DIR_ATTRIBUTE_NAME "$I30" 547 548 /** 549 * NTFS index header. 550 * 551 * This is used by NTFSATINDEXROOT and NTFSATINDEXALLOC. 552 */ 553 typedef struct NTFSINDEXHEADER 554 { 555 /** 0x00: Offset of the first entry relative to this header. */ 556 uint32_t offFirstEntry; 557 /** 0x04: Size of the index in bytes, including this header. */ 558 uint32_t cbIndex; 559 /** 0x08: Number of bytes allocated for the index (including this header). */ 560 uint32_t cbAllocated; 561 /** 0x0c: Flags (NTFSINDEXHEADER_F_XXX). */ 562 uint8_t fFlags; 563 /** 0x0d: Reserved bytes. */ 564 uint8_t abReserved[3]; 565 } NTFSINDEXHEADER; 566 AssertCompileSize(NTFSINDEXHEADER, 16); 567 /** Pointer to a NTFS index header. */ 568 typedef NTFSINDEXHEADER *PNTFSINDEXHEADER; 569 /** Pointer to a const NTFS index header. */ 570 typedef NTFSINDEXHEADER const *PCNTFSINDEXHEADER; 571 572 /** Index root only: Small enough to fit inside the index root attrib. */ 573 #define NTFSINDEXHEADER_F_ROOT_SMALL UINT8_C(0x00) 574 /** Index root only: Too large to fit inside the index root attrib and/or an 575 * index allocation attribute is present. */ 576 #define NTFSINDEXHEADER_F_ROOT_LARGE UINT8_C(0x01) 577 578 579 /** 580 * NTFS index root (NTFS_AT_INDEX_ROOT). 581 * 582 * This is a generic index structure, but is most prominently used for 583 * implementating directories. 584 */ 585 typedef struct NTFSATINDEXROOT 586 { 587 /** 0x00: The index type (NTFSATINDEXROOT_TYPE_XXX). */ 588 uint32_t uType; 589 /** 0x04: The sorting rules to use (NTFS_COLLATION_XXX). */ 590 uint32_t uCollationRules; 591 /** 0x08: Index buffer size (in bytes). */ 592 uint32_t cbIndexBuffer; 593 /** 0x0c: Number of clusters allocated for each index buffer if 594 * cbIndexBuffer is larger than a cluster, otherwise log2(cbIndexBuffer)? */ 595 uint8_t cClustersPerBuffer; 596 /** 0x0d: Reserved padding or something. */ 597 uint8_t abReserved[3]; 598 /** 0x10: Index header detailing the entries that follows. */ 599 NTFSINDEXHEADER Hdr; 600 /* NTFSINDEXENTRYHDR array typically follows */ 601 } NTFSATINDEXROOT; 602 AssertCompileSize(NTFSATINDEXROOT, 32); 603 /** Pointer to a NTFS index root. */ 604 typedef NTFSATINDEXROOT *PNTFSATINDEXROOT; 605 /** Pointer to a const NTFS index root. */ 606 typedef NTFSATINDEXROOT const *PCNTFSATINDEXROOT; 607 608 /** @name NTFSATINDEXROOT_TYPE_XXX 609 * @{ */ 610 /** View index. */ 611 #define NTFSATINDEXROOT_TYPE_VIEW RT_H2LE_U32_C(UINT32_C(0x00000000)) 612 /** Directory index, NTFSATFILENAME follows NTFSINDEXENTRY. */ 613 #define NTFSATINDEXROOT_TYPE_DIRECTORY RT_H2LE_U32_C(UINT32_C(0x00000030)) 614 /** @} */ 615 616 /** @name NTFS_COLLATION_XXX - index sorting rules 617 * @{ */ 618 /** Little endian binary compare (or plain byte compare if you like). */ 619 #define NTFS_COLLATION_BINARY RT_H2LE_U32_C(UINT32_C(0x00000000)) 620 /** Same as NTFS_COLLATION_UNICODE_STRING. */ 621 #define NTFS_COLLATION_FILENAME RT_H2LE_U32_C(UINT32_C(0x00000001)) 622 /** Compare the uppercased unicode characters. */ 623 #define NTFS_COLLATION_UNICODE_STRING RT_H2LE_U32_C(UINT32_C(0x00000002)) 624 625 /** Single little endian 32-bit unsigned integer value as sort key. */ 626 #define NTFS_COLLATION_UINT32 RT_H2LE_U32_C(UINT32_C(0x00000010)) 627 /** Little endian SID value as sort key. */ 628 #define NTFS_COLLATION_SID RT_H2LE_U32_C(UINT32_C(0x00000011)) 629 /** Two little endian 32-bit unsigned integer values used as sorting key. */ 630 #define NTFS_COLLATION_UINT32_PAIR RT_H2LE_U32_C(UINT32_C(0x00000012)) 631 /** Sequence of little endian 32-bit unsigned integer values used as sorting key. */ 632 #define NTFS_COLLATION_UINT32_SEQ RT_H2LE_U32_C(UINT32_C(0x00000013)) 633 634 /** @} */ 635 636 637 /** 638 * NTFS index entry header. 639 */ 640 typedef struct NTFSINDEXENTRYHDR 641 { 642 union 643 { 644 /** 0x00: Non-View: Reference to the MFT record being indexed here. 645 * This is invalid if NTFSINDEX_EF_LAST is set. */ 646 NTFSMFTREF FileMftRec; 647 /** 0x00: View */ 648 struct 649 { 650 /** 0x00: Offset to the data relative to this header. */ 651 uint16_t offData; 652 /** 0x02: Size of data at offData. */ 653 uint16_t cbData; 654 /** 0x04: Reserved. */ 655 uint32_t uReserved; 656 } View; 657 } u; 658 659 /** 0x08: Size of this entry, 8-byte aligned. */ 660 uint16_t cbEntry; 661 /** 0x0a: Key length (unaligned). */ 662 uint16_t cbKey; 663 /** 0x0c: Entry flags, NTFSINDEX_EF_XXX. */ 664 uint16_t fFlags; 665 /** 0x0d: Entry flags, NTFSINDEX_EF_XXX. */ 666 uint16_t uReserved; 667 } NTFSINDEXENTRYHDR; 668 AssertCompileSize(NTFSINDEXENTRYHDR, 16); 669 /** Pointer to a NTFS index entry header. */ 670 typedef NTFSINDEXENTRYHDR *PNTFSINDEXENTRYHDR; 671 /** Pointer to a const NTFS index entry header. */ 672 typedef NTFSINDEXENTRYHDR const *PCNTFSINDEXENTRYHDR; 673 674 /** @name NTFSINDEX_EF_XXX - NTFSINDEXENTRYHDR::fFlags 675 * @{ */ 676 /** Indicates an internal node, as opposed to a leaf node. */ 677 #define NTFSINDEX_EF_NODE RT_H2LE_U16_C(UINT16_C(0x0001)) 678 /** Last entry in a block, may point to the next node. */ 679 #define NTFSINDEX_EF_LAST RT_H2LE_U16_C(UINT16_C(0x0002)) 680 /** @} */ 681 489 682 /** @} */ 490 683 -
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.