+#define _MFTREF_IDX(ref) ((ref) & ((1ULL<<48)-1))
+#define _MFTREF_SEQ(ref) ((ref) >> 48)
+
+void NTFS_int_DumpIndex(tNTFS_Attrib *Allocation, Uint AttribID)
+{
+ ENTER("pAllocation xAttribID", Allocation, AttribID);
+ if(!Allocation) {
+ LEAVE('-');
+ return ;
+ }
+ Uint32 vcn = 0;
+ size_t block_size = MAX(2048, Allocation->Disk->ClusterSize);
+ char buf[block_size];
+ size_t len;
+ while( (len = NTFS_ReadAttribData(Allocation, vcn*block_size, block_size, buf)) )
+ {
+ struct sNTFS_IndexHeader *hdr = (void*)buf;
+ LOG("VCN %x: Ofs=%x, Size=%x",
+ vcn, hdr->EntriesOffset, hdr->EntriesSize);
+ if( hdr->ThisVCN != vcn ) {
+ Log_Notice("NTFS", "Data error: Index header VCN mismatch (%x!=exp %x)", hdr->ThisVCN, vcn);
+ }
+ size_t ofs = hdr->EntriesOffset + 0x18;
+ while( ofs < hdr->EntriesSize + (hdr->EntriesOffset + 0x18) )
+ {
+ struct sNTFS_IndexEntry *ent = (void*)(buf + ofs);
+ if( ofs + sizeof(*ent) > len )
+ break;
+ LOG("%03x: L=%02x,M=%02x,F=%02x, Ref=%x/%llx", ofs,
+ ent->EntrySize, ent->MessageLen, ent->IndexFlags,
+ _MFTREF_SEQ(ent->MFTReference), _MFTREF_IDX(ent->MFTReference));
+
+ if( ent->EntrySize < sizeof(*ent) ) {
+ Log_Notice("NTFS", "Data error: Index entry size too small");
+ break ;
+ }
+ if( ent->MessageLen + sizeof(*ent) > ent->EntrySize ) {
+ Log_Notice("NTFS", "Data error: Index entry message size > entry size");
+ }
+
+ if( ent->IndexFlags & NTFS_IndexFlag_HasSubNode )
+ {
+ if( ent->EntrySize < sizeof(*ent) + 8 ) {
+ Log_Notice("NTFS", "Data error: Index entry size too small (SubVCN)");
+ }
+ LOG("- SubVCN=%llx", *(Uint64*)((char*)ent + ent->EntrySize - 8));
+ }
+ if( ent->IndexFlags & NTFS_IndexFlag_IsLast )
+ break;
+
+ switch(AttribID)
+ {
+ case 0x30: {
+ struct sNTFS_Attrib_Filename *fname = (void*)(buf + ofs + sizeof(*ent));
+ LOG("- Filename: %i %.*ls",
+ fname->FilenameNamespace,
+ fname->FilenameLength, fname->Filename);
+ break; }
+ }
+
+ ofs += ent->EntrySize;
+ }
+ vcn ++;
+ }
+ LEAVE('-');
+}
+