anshdadhich commited on
Commit
aa2084e
·
verified ·
1 Parent(s): b0d361b

Upload FastSeekWpf/Core/MftReader.cs

Browse files
Files changed (1) hide show
  1. FastSeekWpf/Core/MftReader.cs +36 -25
FastSeekWpf/Core/MftReader.cs CHANGED
@@ -33,22 +33,14 @@ public class MftReader : IDisposable
33
  if (_volumeHandle == new IntPtr(-1))
34
  {
35
  int err = Marshal.GetLastWin32Error();
36
- throw new IOException($"Failed to open volume {drive.DevicePath}: {Win32Error(err)}");
37
  }
38
  }
39
 
40
- // ------------------------------------------------------------------
41
- // Primary: direct $MFT file read
42
- // ------------------------------------------------------------------
43
-
44
  public ScanResult? ScanDirect()
45
  {
46
  int? recordSize = ReadMftRecordSize();
47
- if (!recordSize.HasValue)
48
- {
49
- Logger.Log($"[{Drive.Letter}] ReadMftRecordSize failed — cannot do direct scan");
50
- return null;
51
- }
52
 
53
  string mftPath = $"{_drive.Root}$MFT";
54
  Logger.Log($"[{Drive.Letter}] Opening $MFT file: {mftPath}");
@@ -69,8 +61,6 @@ public class MftReader : IDisposable
69
  return null;
70
  }
71
 
72
- Logger.Log($"[{Drive.Letter}] $MFT opened OK, handle=0x{mftHandle:X}");
73
-
74
  try
75
  {
76
  var records = new List<CompactRecord>();
@@ -107,7 +97,6 @@ public class MftReader : IDisposable
107
  {
108
  ParseFileRecord(buffer.AsSpan(offset, recordSize.Value), mftIndex, records, nameData);
109
  }
110
-
111
  mftIndex++;
112
  offset += recordSize.Value;
113
  }
@@ -130,13 +119,37 @@ public class MftReader : IDisposable
130
  }
131
  }
132
 
133
- // ------------------------------------------------------------------
134
- // Fallback: FSCTL_ENUM_USN_DATA
135
- // ------------------------------------------------------------------
136
-
137
  public ScanResult Scan()
138
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  Logger.Log($"[{Drive.Letter}] Starting FSCTL_ENUM_USN_DATA fallback...");
 
 
140
 
141
  var records = new List<CompactRecord>();
142
  var nameData = new List<char>();
@@ -150,8 +163,6 @@ public class MftReader : IDisposable
150
  };
151
 
152
  int enumDataSize = Marshal.SizeOf<MFT_ENUM_DATA_V0>();
153
- Logger.Log($"[{Drive.Letter}] MFT_ENUM_DATA_V0 size = {enumDataSize} bytes");
154
-
155
  IntPtr enumDataPtr = Marshal.AllocHGlobal(enumDataSize);
156
  Marshal.StructureToPtr(enumData, enumDataPtr, false);
157
 
@@ -181,10 +192,14 @@ public class MftReader : IDisposable
181
  }
182
  if (error == 122) // ERROR_INSUFFICIENT_BUFFER
183
  {
184
- Logger.Log($"[{Drive.Letter}] FSCTL_ENUM_USN_DATA: buffer too small ({buffer.Length}), retrying with larger buffer");
185
  buffer = new byte[buffer.Length * 2];
186
  continue;
187
  }
 
 
 
 
188
  Logger.Log($"[{Drive.Letter}] FSCTL_ENUM_USN_DATA failed (iter {iterations}): {Win32Error(error)} (code={error})");
189
  break;
190
  }
@@ -245,10 +260,6 @@ public class MftReader : IDisposable
245
  return new ScanResult(records, nameData);
246
  }
247
 
248
- // ------------------------------------------------------------------
249
- // NTFS helpers
250
- // ------------------------------------------------------------------
251
-
252
  private int? ReadMftRecordSize()
253
  {
254
  Logger.Log($"[{Drive.Letter}] Reading boot sector from volume...");
@@ -265,7 +276,7 @@ public class MftReader : IDisposable
265
 
266
  if (boot[3] != 'N' || boot[4] != 'T' || boot[5] != 'F' || boot[6] != 'S')
267
  {
268
- Logger.Log($"[{Drive.Letter}] Not NTFS (missing signature at offset 3)");
269
  return null;
270
  }
271
 
 
33
  if (_volumeHandle == new IntPtr(-1))
34
  {
35
  int err = Marshal.GetLastWin32Error();
36
+ throw new IOException($"Failed to open volume {drive.DevicePath}: {Win32Error(err)} (code={err})");
37
  }
38
  }
39
 
 
 
 
 
40
  public ScanResult? ScanDirect()
41
  {
42
  int? recordSize = ReadMftRecordSize();
43
+ if (!recordSize.HasValue) return null;
 
 
 
 
44
 
45
  string mftPath = $"{_drive.Root}$MFT";
46
  Logger.Log($"[{Drive.Letter}] Opening $MFT file: {mftPath}");
 
61
  return null;
62
  }
63
 
 
 
64
  try
65
  {
66
  var records = new List<CompactRecord>();
 
97
  {
98
  ParseFileRecord(buffer.AsSpan(offset, recordSize.Value), mftIndex, records, nameData);
99
  }
 
100
  mftIndex++;
101
  offset += recordSize.Value;
102
  }
 
119
  }
120
  }
121
 
 
 
 
 
122
  public ScanResult Scan()
123
  {
124
+ // Diagnostic: test FSCTL_QUERY_USN_JOURNAL first
125
+ Logger.Log($"[{Drive.Letter}] Diagnostic: testing FSCTL_QUERY_USN_JOURNAL...");
126
+ IntPtr journalBuf = Marshal.AllocHGlobal(Marshal.SizeOf<USN_JOURNAL_DATA_V0>());
127
+ try
128
+ {
129
+ bool ok = Win32Api.DeviceIoControl(
130
+ _volumeHandle, Win32Api.FSCTL_QUERY_USN_JOURNAL,
131
+ IntPtr.Zero, 0,
132
+ journalBuf, (uint)Marshal.SizeOf<USN_JOURNAL_DATA_V0>(),
133
+ out uint bytesReturned, IntPtr.Zero);
134
+ if (ok)
135
+ {
136
+ var journalData = Marshal.PtrToStructure<USN_JOURNAL_DATA_V0>(journalBuf);
137
+ Logger.Log($"[{Drive.Letter}] USN journal OK: ID={journalData.UsnJournalID}, NextUsn={journalData.NextUsn}, Active=YES");
138
+ }
139
+ else
140
+ {
141
+ int err = Marshal.GetLastWin32Error();
142
+ Logger.Log($"[{Drive.Letter}] FSCTL_QUERY_USN_JOURNAL failed: {Win32Error(err)} (code={err})");
143
+ }
144
+ }
145
+ finally
146
+ {
147
+ Marshal.FreeHGlobal(journalBuf);
148
+ }
149
+
150
  Logger.Log($"[{Drive.Letter}] Starting FSCTL_ENUM_USN_DATA fallback...");
151
+ Logger.Log($"[{Drive.Letter}] MFT_ENUM_DATA_V0 size = {Marshal.SizeOf<MFT_ENUM_DATA_V0>()} bytes");
152
+ Logger.Log($"[{Drive.Letter}] USN_RECORD_V2 size = {Marshal.SizeOf<USN_RECORD_V2>()} bytes");
153
 
154
  var records = new List<CompactRecord>();
155
  var nameData = new List<char>();
 
163
  };
164
 
165
  int enumDataSize = Marshal.SizeOf<MFT_ENUM_DATA_V0>();
 
 
166
  IntPtr enumDataPtr = Marshal.AllocHGlobal(enumDataSize);
167
  Marshal.StructureToPtr(enumData, enumDataPtr, false);
168
 
 
192
  }
193
  if (error == 122) // ERROR_INSUFFICIENT_BUFFER
194
  {
195
+ Logger.Log($"[{Drive.Letter}] FSCTL_ENUM_USN_DATA: buffer too small ({buffer.Length}), retrying");
196
  buffer = new byte[buffer.Length * 2];
197
  continue;
198
  }
199
+ if (error == 1) // ERROR_INVALID_FUNCTION
200
+ {
201
+ Logger.Log($"[{Drive.Letter}] FSCTL_ENUM_USN_DATA: ERROR_INVALID_FUNCTION — struct/IOCTL mismatch or journal not active");
202
+ }
203
  Logger.Log($"[{Drive.Letter}] FSCTL_ENUM_USN_DATA failed (iter {iterations}): {Win32Error(error)} (code={error})");
204
  break;
205
  }
 
260
  return new ScanResult(records, nameData);
261
  }
262
 
 
 
 
 
263
  private int? ReadMftRecordSize()
264
  {
265
  Logger.Log($"[{Drive.Letter}] Reading boot sector from volume...");
 
276
 
277
  if (boot[3] != 'N' || boot[4] != 'T' || boot[5] != 'F' || boot[6] != 'S')
278
  {
279
+ Logger.Log($"[{Drive.Letter}] Not NTFS (missing signature at offset 3): bytes={boot[3]},{boot[4]},{boot[5]},{boot[6]}");
280
  return null;
281
  }
282