Quantcast
Channel: Reading MFT
Viewing all articles
Browse latest Browse all 444

Reading MFT

$
0
0

EDIT: SOLUTION: The answer is that MftValidDataLength needs to be divided by MFT record length which is 1024 giving total number of MFT records making progress feedback trivial.

 

Hi,

 

Could someone help me to understand why sum of sizes from enumeration with FSCTL_ENUM_USN_DATA does not add up to MftValidDataLength?

I got 682,885,120 from FSCTL_GET_NTFS_VOLUME_DATA (which I confirmed is correct with fsutil fsinfo ntfsinfo C:) but when adding up outBytesReturned in procedure EnumerateFiles() I am getting only 29,286,240? This is around 23 times less then I would expect. What do I do wrong?

 

 

unsafeprivatevoid EnumerateFiles(IntPtr medBuffer, ref Dictionary<ulong, FileNameAndFrn> files, string[] fileExtensions) {
            IntPtr pData = Marshal.AllocHGlobal(sizeof(UInt64) + 0x10000);
            PInvokeWin32.ZeroMemory(pData, sizeof(UInt64) + 0x10000);uint outBytesReturned = 0;ulong progress = 0;while (false != PInvokeWin32.DeviceIoControl(_changeJournalRootHandle, PInvokeWin32.FSCTL_ENUM_USN_DATA, medBuffer,sizeof(PInvokeWin32.MFT_ENUM_DATA), pData, sizeof(UInt64) + 0x10000, out outBytesReturned,
                                    IntPtr.Zero)) {
                IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64));
                progress += outBytesReturned;
                ...
                Log.InfoFormat("Progress: {0}", progress);
        ...

 

 

By the way c# implementation of FSCTL_GET_NTFS_VOLUME_DATA:

 

//PInvokeWin32.cspublicconst UInt32 FSCTL_GET_NTFS_VOLUME_DATA = 0x00090064;

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        publicstruct NTFS_VOLUME_DATA_BUFFER {public UInt64 VolumeSerialNumber;public UInt64 NumberSectors;public UInt64 TotalClusters;public UInt64 FreeClusters;public UInt64 TotalReserved;public UInt32 BytesPerSector;public UInt32 BytesPerCluster;public UInt32 BytesPerFileRecordSegment;public UInt32 ClustersPerFileRecordSegment;public UInt64 MftValidDataLength;public UInt64 MftStartLcn;public UInt64 Mft2StartLcn;public UInt64 MftZoneStart;public UInt64 MftZoneEnd;
        }//Mft.cs in Mft classunsafeprivate PInvokeWin32.NTFS_VOLUME_DATA_BUFFER GetNtfsInfo() {
            IntPtr pAlloc = IntPtr.Zero;

            PInvokeWin32.NTFS_VOLUME_DATA_BUFFER retValue = new PInvokeWin32.NTFS_VOLUME_DATA_BUFFER();try {
                int q = 96;uint size = 0;
                pAlloc = Marshal.AllocHGlobal((int)q);
                IntPtr pDest = pAlloc;bool fResult = PInvokeWin32.DeviceIoControl(
                    _changeJournalRootHandle,
                    PInvokeWin32.FSCTL_GET_NTFS_VOLUME_DATA,
                    IntPtr.Zero, 
                    0,  
                    pDest,sizeof(PInvokeWin32.NTFS_VOLUME_DATA_BUFFER),  out size,
                    IntPtr.Zero);if (!fResult) {thrownew Exception(Marshal.GetLastWin32Error().ToString());
                }

                retValue.VolumeSerialNumber = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));

                pDest = (IntPtr)((Int64)pDest + 8);
                retValue.NumberSectors = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));

                pDest = (IntPtr)((Int64)pDest + 8);
                retValue.TotalClusters = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));

                pDest = (IntPtr)((Int64)pDest + 8);
                retValue.FreeClusters = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));

                pDest = (IntPtr)((Int64)pDest + 8);
                retValue.TotalReserved = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));

                pDest = (IntPtr)((Int64)pDest + 8);
                retValue.BytesPerSector = (UInt32)Marshal.PtrToStructure(pDest, typeof(UInt32));

                pDest = (IntPtr)((Int64)pDest + 4);
                retValue.BytesPerCluster = (UInt32)Marshal.PtrToStructure(pDest, typeof(UInt32));

                pDest = (IntPtr)((Int64)pDest + 4);
                retValue.BytesPerFileRecordSegment = (UInt32)Marshal.PtrToStructure(pDest, typeof(UInt32));

                pDest = (IntPtr)((Int64)pDest + 4);
                retValue.ClustersPerFileRecordSegment = (UInt32)Marshal.PtrToStructure(pDest, typeof(UInt32));

                pDest = (IntPtr)((Int64)pDest + 4);
                retValue.MftValidDataLength = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));

                pDest = (IntPtr)((Int64)pDest + 8);
                retValue.MftStartLcn = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));

                pDest = (IntPtr)((Int64)pDest + 8);
                retValue.Mft2StartLcn = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));

                pDest = (IntPtr)((Int64)pDest + 8);
                retValue.MftZoneStart = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));

                pDest = (IntPtr)((Int64)pDest + 8);
                retValue.MftZoneEnd = (UInt64)Marshal.PtrToStructure(pDest, typeof(UInt64));return retValue;
            } finally {
                Marshal.FreeHGlobal(pAlloc);
                pAlloc = IntPtr.Zero;
            }
        }// call method used in EnumerateVolume()
PInvokeWin32.NTFS_VOLUME_DATA_BUFFER volInfo;try {
    GetRootFrnEntry();
    GetRootHandle();
    volInfo = GetNtfsInfo();
    Log.InfoFormat("MftValidDataLength: {0}", volInfo.MftValidDataLength);
    ...
} catch (Exception e) {
    Log.Info(e.Message, e);
    ...
} finally {
    ...
}


 




Viewing all articles
Browse latest Browse all 444

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>