我需要在我的.net應用程序中使用C#訪問Windows MFT(主文件表)。
我已經搜索了這個,並沒有找到任何好的結果。我一直在搜索過去兩天的信息,但一直未能找到任何相關信息。我們如何通過C#訪問MFT
我不是在尋找確切的代碼來做同樣的事情,我只是尋找一些可以讓我開始的信息。
我一直能弄清楚的是我必須使用P/Invoke。
我想知道我將用於訪問MFT的功能。
如果你能夠提供一些代碼示例,那就太棒了。
我需要在我的.net應用程序中使用C#訪問Windows MFT(主文件表)。
我已經搜索了這個,並沒有找到任何好的結果。我一直在搜索過去兩天的信息,但一直未能找到任何相關信息。我們如何通過C#訪問MFT
我不是在尋找確切的代碼來做同樣的事情,我只是尋找一些可以讓我開始的信息。
我一直能弄清楚的是我必須使用P/Invoke。
我想知道我將用於訪問MFT的功能。
如果你能夠提供一些代碼示例,那就太棒了。
首先,您必須擁有並聲明訪問MFT的足夠權限 - 這本身就是一種痛苦。然後,您必須獲得捲上文件/文件夾的句柄 - 用於最後一步中的調用...即在循環中調用Windows API(稱爲DeviceIOControl)並從返回的API調用中讀取條目 - 這是它自己的特別頭痛。
概念 - 這看起來像:
static void Main(string[ ] args)
{
if (Privileges.HasBackupAndRestorePrivileges)
{
using (var volume = GetVolumeHandle("C:\\"))
{
ReadMft(volume);
}
}
}
如果你把每一種反過來,主張足夠的權限是最不起眼的部分。有一個Windows API來更改正在運行的令牌的權限 - 並使用它來添加必要的權限。以下是我用來聲明這些權限的類的摘錄。你可以聲稱更多的特權 - 但這應該足以閱讀MFT。
您的應用程序需要運行在實際可以獲得必要權限的帳戶下 - 管理員帳戶是好的。另外,備份操作員也可以工作。
public static class Privileges
{
private static int asserted = 0;
private static bool hasBackupPrivileges = false;
public static bool HasBackupAndRestorePrivileges
{
get { return AssertPriveleges(); }
}
/// <remarks>
/// First time this method is called, it attempts to set backup privileges for the current process.
/// Subsequently, it returns the results of that first call.
/// </remarks>
private static bool AssertPriveleges()
{
bool success = false;
var wasAsserted = Interlocked.CompareExchange(ref asserted, 1, 0);
if (wasAsserted == 0) // first time here? come on in!
{
success =
AssertPrivelege(NativeMethods.SE_BACKUP_NAME)
AssertPrivelege(NativeMethods.SE_RESTORE_NAME);
hasBackupPrivileges = success;
}
return hasBackupPrivileges;
}
private static bool AssertPrivelege(string privelege)
{
IntPtr token;
var tokenPrivileges = new NativeMethods.TOKEN_PRIVILEGES();
tokenPrivileges.Privileges = new NativeMethods.LUID_AND_ATTRIBUTES[ 1 ];
var success =
NativeMethods.OpenProcessToken(NativeMethods.GetCurrentProcess(), NativeMethods.TOKEN_ADJUST_PRIVILEGES, out token)
&&
NativeMethods.LookupPrivilegeValue(null, privelege, out tokenPrivileges.Privileges[ 0 ].Luid);
try
{
if (success)
{
tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[ 0 ].Attributes = NativeMethods.SE_PRIVILEGE_ENABLED;
success =
NativeMethods.AdjustTokenPrivileges(token, false, ref tokenPrivileges, Marshal.SizeOf(tokenPrivileges), IntPtr.Zero, IntPtr.Zero)
&&
(Marshal.GetLastWin32Error() == 0);
}
if (!success)
{
Console.WriteLine("Could not assert privilege: " + privelege);
}
}
finally
{
NativeMethods.CloseHandle(token);
}
return success;
}
}
一旦你過了這一關,剩下的就是 - 嗯......還是一個默默無聞的節日。你必須得到一個文件或文件夾的句柄 - 用備份語義。您可能會在您之後的捲上的任何舊文件上打開FileStream,並且FileStream將有一個可用於後續調用的句柄。這不完全是我的應用程序 - 但我的應用程序必須做的事情,這個答案不必做。
internal static SafeFileHandle GetVolumeHandle(string pathToVolume, NativeMethods.EFileAccess access = NativeMethods.EFileAccess.AccessSystemSecurity | NativeMethods.EFileAccess.GenericRead | NativeMethods.EFileAccess.ReadControl)
{
var attributes = (uint) NativeMethods.EFileAttributes.BackupSemantics;
var handle = NativeMethods.CreateFile(pathToVolume, access, 7U, IntPtr.Zero, (uint) NativeMethods.ECreationDisposition.OpenExisting, attributes, IntPtr.Zero);
if (handle.IsInvalid)
{
throw new IOException("Bad path");
}
return handle;
}
對於ReadMft - 有一個相當複雜的Windows API函數 - DeviceIoControl的 - 即取緩衝器與史詩各種輸入,並返回含心態彎曲多種輸出緩衝器。這是一種用於查詢有關各種設備信息的全能API,而包含MFT的卷是一個設備。
要讀取MFT,可以使用設備IO控制代碼FSCTL_ENUM_USN_DATA調用DeviceIOControl - 它將爲MFT中的每個記錄返回一個USN記錄。每次調用都有很多記錄 - 每次調用後,都會使用前一次調用返回的第一個信息參數化循環中的下一個調用。
順便說一句 - 我改名爲我的代碼中的Windows API調用,使它們看起來更像.Net。我不確定我將來會這樣做。
特別說明這裏:每個文件都有一條記錄 - 無論有多少硬鏈接 - 您必須進行額外的調用來枚舉硬鏈接。
文件系統層次結構編碼在您從調用中返回的結構的FileReferenceNumber和ParentFileReferenceNumber中。你名義上將這些usn記錄保存到列表中,按照FileReferenceNumber排序併爲ParentFileReferenceNumber創建一個二級索引 - 或者類似的東西。爲了說明的目的,這段代碼只是轉儲MFT條目。
本示例使用不安全的代碼 - 並修復包含輸入和輸出的緩衝區的位置。有不同的方式來解決這個問題 - 但這是很好的和快樂的。如果你使用這個,你必須在你的項目設置中允許不安全的代碼。
public unsafe static bool ReadMft(SafeHandle volume)
{
var outputBufferSize = 1024 * 1024;
var input = new NativeMethods.MFTEnumDataV0();
var usnRecord = new NativeMethods.UsnRecordV2();
var outputBuffer = new byte[ outputBufferSize ];
var okay = true;
var doneReading = false;
try
{
fixed (byte* pOutput = outputBuffer)
{
input.StartFileReferenceNumber = 0;
input.LowUsn = 0;
input.HighUsn = long.MaxValue;
using (var stream = new MemoryStream(outputBuffer, true))
{
while (!doneReading)
{
var bytesRead = 0U;
okay = NativeMethods.DeviceIoControl
(
volume.DangerousGetHandle(),
NativeMethods.DeviceIOControlCode.FsctlEnumUsnData,
(byte*) &input.StartFileReferenceNumber,
(uint) Marshal.SizeOf(input),
pOutput,
(uint) outputBufferSize,
out bytesRead,
IntPtr.Zero
);
if (!okay)
{
var error = Marshal.GetLastWin32Error();
okay = error == NativeMethods.ERROR_HANDLE_EOF;
if (!okay)
{
Console.WriteLine("Crap! Windows error " + error.ToString());
break;
}
else
{
doneReading = true;
}
}
input.StartFileReferenceNumber = stream.ReadULong();
while (stream.Position < bytesRead)
{
usnRecord.Read(stream);
//-->>>>>>>>>>>>>>>>>
//--> just an example of reading out the record...
Console.WriteLine("FRN:" + usnRecord.FileReferenceNumber.ToString());
Console.WriteLine("Parent FRN:" + usnRecord.ParentFileReferenceNumber.ToString());
Console.WriteLine("File name:" + usnRecord.FileName);
Console.WriteLine("Attributes: " + (NativeMethods.EFileAttributes) usnRecord.FileAttributes);
Console.WriteLine("Timestamp:" + usnRecord.TimeStamp);
//-->>>>>>>>>>>>>>>>>>>
}
stream.Seek(0, SeekOrigin.Begin);
}
}
}
}
catch (Exception ex)
{
Console.Write(ex);
okay = false;
}
return okay;
}
我做了什麼大概的那種俗氣給自己節省了大量的工作 - 我加僞序列化方法爲windows API的結構 - 使他們能夠讀出自己流的。例如,usnRecord用來讀取在上述代碼緩衝器是windows API結構 - 但實現了串行化接口:
[StructLayout(LayoutKind.Sequential)]
internal struct UsnRecordV2: IBinarySerialize
{
public uint RecordLength;
public ushort MajorVersion;
public ushort MinorVersion;
public ulong FileReferenceNumber;
public ulong ParentFileReferenceNumber;
public long Usn;
public long TimeStamp;
public UsnReason Reason;
public uint SourceInfo;
public uint SecurityId;
public uint FileAttributes;
public ushort FileNameLength;
public ushort FileNameOffset;
public string FileName;
/// <remarks>
/// Note how the read advances to the FileNameOffset and reads only FileNameLength bytes.
/// </remarks>
public void Read(Stream stream)
{
var startOfRecord = stream.Position;
RecordLength = stream.ReadUInt();
MajorVersion = stream.ReadUShort();
MinorVersion = stream.ReadUShort();
FileReferenceNumber = stream.ReadULong();
ParentFileReferenceNumber = stream.ReadULong();
Usn = stream.ReadLong();
TimeStamp = stream.ReadLong();
Reason = (UsnReason) stream.ReadUInt();
SourceInfo = stream.ReadUInt();
SecurityId = stream.ReadUInt();
FileAttributes = stream.ReadUInt();
FileNameLength = stream.ReadUShort();
FileNameOffset = stream.ReadUShort();
stream.Position = startOfRecord + FileNameOffset;
FileName = Encoding.Unicode.GetString(stream.ReadBytes(FileNameLength));
stream.Position = startOfRecord + RecordLength;
}
/// <summary>We never write instances of this structure</summary>
void IBinarySerialize.Write(Stream stream)
{
throw new NotImplementedException();
}
}
...其中IBinarySerialze是:
public interface IBinarySerialize
{
/// <summary>Reads an object's data from a <see cref="Stream"/></summary>
void Read(Stream stream);
/// <summary>Writes an objects serializable content to a <see cref="Stream"/></summary>
void Write(Stream stream);
}
有流結構中使用的擴展方法。基本上,他們從BinaryReader中解除。爲什麼?因爲在.Net 3.5中 - 我必須先寫這個--BBCL BinaryReader會關閉你把它包裹起來的流 - 而且我有很多地方只是無法忍受。
internal static class StreamingExtensions
{
public static ushort ReadUShort(this Stream stream)
{
return BitConverter.ToUInt16(ReadBytes(stream, 2), 0);
}
public static uint ReadUInt(this Stream stream)
{
return BitConverter.ToUInt32(ReadBytes(stream, 4), 0);
}
public static long ReadLong(this Stream stream)
{
return BitConverter.ToInt64(ReadBytes(stream, 8), 0);
}
public static ulong ReadULong(this Stream stream)
{
return BitConverter.ToUInt64(ReadBytes(stream, 8), 0);
}
public static byte[ ] ReadBytes(this Stream stream, int length, bool throwIfIncomplete = false)
{
var bytes = new byte[ length ];
var bytesRead = 0;
var offset = 0;
if (length > 0)
{
while (offset < length)
{
bytesRead = stream.Read(bytes, offset, length - offset);
if (bytesRead == 0)
{
if (throwIfIncomplete) throw new InvalidOperationException("incomplete");
break;
}
offset += bytesRead;
}
}
return bytes;
}
}
爲了完整起見,下面是本地方法,枚舉,常量和噪聲。大部分來自PInvoke.net,但是再次......許多這些東西的名稱都是.net-ified。對純粹主義者抱歉。
internal class NativeMethods
{
internal const int ERROR_HANDLE_EOF = 38;
//--> Privilege constants....
internal const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
internal const string SE_BACKUP_NAME = "SeBackupPrivilege";
internal const string SE_RESTORE_NAME = "SeRestorePrivilege";
internal const string SE_SECURITY_NAME = "SeSecurityPrivilege";
internal const string SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege";
internal const string SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege";
internal const string SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege";
internal const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege";
internal const string SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege";
internal const string SE_TIME_ZONE_NAME = "SeTimeZonePrivilege";
internal const string SE_TCB_NAME = "SeTcbPrivilege";
internal const string SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege";
internal const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege";
//--> For starting a process in session 1 from session 0...
internal const int TOKEN_DUPLICATE = 0x0002;
internal const uint MAXIMUM_ALLOWED = 0x2000000;
internal const int CREATE_NEW_CONSOLE = 0x00000010;
internal const uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
internal const int TOKEN_QUERY = 0x00000008;
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
[DllImport("kernel32.dll")]
internal static extern IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, Int32 BufferLength, IntPtr PreviousState, IntPtr ReturnLength);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe extern bool DeviceIoControl(IntPtr hDevice, DeviceIOControlCode controlCode, byte* lpInBuffer, uint nInBufferSize, byte* lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern SafeFileHandle CreateFile(string lpFileName, EFileAccess dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr hObject);
[Flags]
internal enum EMethod: uint
{
Buffered = 0,
InDirect = 1,
OutDirect = 2,
Neither = 3
}
[Flags]
internal enum EFileAccess: uint
{
GenericRead = 0x80000000,
GenericWrite = 0x40000000,
GenericExecute = 0x20000000,
GenericAll = 0x10000000,
Delete = 0x10000,
ReadControl = 0x20000,
WriteDAC = 0x40000,
WriteOwner = 0x80000,
Synchronize = 0x100000,
StandardRightsRequired = 0xF0000,
StandardRightsRead = ReadControl,
StandardRightsWrite = ReadControl,
StandardRightsExecute = ReadControl,
StandardRightsAll = 0x1F0000,
SpecificRightsAll = 0xFFFF,
AccessSystemSecurity = 0x1000000,
MaximumAllowed = 0x2000000
}
[Flags]
internal enum EFileDevice: uint
{
Beep = 0x00000001,
CDRom = 0x00000002,
CDRomFileSytem = 0x00000003,
Controller = 0x00000004,
Datalink = 0x00000005,
Dfs = 0x00000006,
Disk = 0x00000007,
DiskFileSystem = 0x00000008,
FileSystem = 0x00000009,
InPortPort = 0x0000000a,
Keyboard = 0x0000000b,
Mailslot = 0x0000000c,
MidiIn = 0x0000000d,
MidiOut = 0x0000000e,
Mouse = 0x0000000f,
MultiUncProvider = 0x00000010,
NamedPipe = 0x00000011,
Network = 0x00000012,
NetworkBrowser = 0x00000013,
NetworkFileSystem = 0x00000014,
Null = 0x00000015,
ParallelPort = 0x00000016,
PhysicalNetcard = 0x00000017,
Printer = 0x00000018,
Scanner = 0x00000019,
SerialMousePort = 0x0000001a,
SerialPort = 0x0000001b,
Screen = 0x0000001c,
Sound = 0x0000001d,
Streams = 0x0000001e,
Tape = 0x0000001f,
TapeFileSystem = 0x00000020,
Transport = 0x00000021,
Unknown = 0x00000022,
Video = 0x00000023,
VirtualDisk = 0x00000024,
WaveIn = 0x00000025,
WaveOut = 0x00000026,
Port8042 = 0x00000027,
NetworkRedirector = 0x00000028,
Battery = 0x00000029,
BusExtender = 0x0000002a,
Modem = 0x0000002b,
Vdm = 0x0000002c,
MassStorage = 0x0000002d,
Smb = 0x0000002e,
Ks = 0x0000002f,
Changer = 0x00000030,
Smartcard = 0x00000031,
Acpi = 0x00000032,
Dvd = 0x00000033,
FullscreenVideo = 0x00000034,
DfsFileSystem = 0x00000035,
DfsVolume = 0x00000036,
Serenum = 0x00000037,
Termsrv = 0x00000038,
Ksec = 0x00000039,
// From Windows Driver Kit 7
Fips = 0x0000003A,
Infiniband = 0x0000003B,
Vmbus = 0x0000003E,
CryptProvider = 0x0000003F,
Wpd = 0x00000040,
Bluetooth = 0x00000041,
MtComposite = 0x00000042,
MtTransport = 0x00000043,
Biometric = 0x00000044,
Pmi = 0x00000045
}
internal enum EFileIOCtlAccess: uint
{
Any = 0,
Special = Any,
Read = 1,
Write = 2
}
internal enum DeviceIOControlCode: uint
{
FsctlEnumUsnData = (EFileDevice.FileSystem << 16) | (44 << 2) | EMethod.Neither | (EFileIOCtlAccess.Any << 14),
FsctlReadUsnJournal = (EFileDevice.FileSystem << 16) | (46 << 2) | EMethod.Neither | (EFileIOCtlAccess.Any << 14),
FsctlReadFileUsnData = (EFileDevice.FileSystem << 16) | (58 << 2) | EMethod.Neither | (EFileIOCtlAccess.Any << 14),
FsctlQueryUsnJournal = (EFileDevice.FileSystem << 16) | (61 << 2) | EMethod.Buffered | (EFileIOCtlAccess.Any << 14),
FsctlCreateUsnJournal = (EFileDevice.FileSystem << 16) | (57 << 2) | EMethod.Neither | (EFileIOCtlAccess.Any << 14)
}
/// <summary>Control structure used to interrogate MFT data using DeviceIOControl from the user volume</summary>
[StructLayout(LayoutKind.Sequential)]
internal struct MFTEnumDataV0
{
public ulong StartFileReferenceNumber;
public long LowUsn;
public long HighUsn;
}
/// <summary>A structure resurned form USN queries</summary>
/// <remarks>
/// FileName is synthetic...composed during a read of the structure and is not technically
/// part of the Win32 API's definition...although the actual FileName is contained
/// "somewhere" in the structure's trailing bytes, according to FileNameLength and FileNameOffset.
///
/// Alignment boundaries are enforced, and so, the RecordLength
/// may be somewhat larger than the accumulated lengths of the members plus the FileNameLength.
/// </remarks>
[StructLayout(LayoutKind.Sequential)]
internal struct UsnRecordV2: IBinarySerialize
{
public uint RecordLength;
public ushort MajorVersion;
public ushort MinorVersion;
public ulong FileReferenceNumber;
public ulong ParentFileReferenceNumber;
public long Usn;
public long TimeStamp;
public UsnReason Reason;
public uint SourceInfo;
public uint SecurityId;
public uint FileAttributes;
public ushort FileNameLength;
public ushort FileNameOffset;
public string FileName;
/// <remarks>Note how the read advances to the FileNameOffset and reads only FileNameLength bytes</remarks>
public void Read(Stream stream)
{
var startOfRecord = stream.Position;
RecordLength = stream.ReadUInt();
MajorVersion = stream.ReadUShort();
MinorVersion = stream.ReadUShort();
FileReferenceNumber = stream.ReadULong();
ParentFileReferenceNumber = stream.ReadULong();
Usn = stream.ReadLong();
TimeStamp = stream.ReadLong();
Reason = (UsnReason) stream.ReadUInt();
SourceInfo = stream.ReadUInt();
SecurityId = stream.ReadUInt();
FileAttributes = stream.ReadUInt();
FileNameLength = stream.ReadUShort();
FileNameOffset = stream.ReadUShort();
stream.Position = startOfRecord + FileNameOffset;
FileName = Encoding.Unicode.GetString(stream.ReadBytes(FileNameLength));
stream.Position = startOfRecord + RecordLength;
}
void IBinarySerialize.Write(Stream stream)
{
throw new NotImplementedException();
}
}
/// <summary>Structure returned from USN query that describes the state of the journal</summary>
[StructLayout(LayoutKind.Sequential)]
internal struct UsnJournalDataV1: IBinarySerialize
{
public ulong UsnJournalId;
public long FirstUsn;
public long NextUsn;
public long LowestValidUsn;
public long MaxUsn;
public ulong MaximumSize;
public ulong AllocationDelta;
public ushort MinSupportedMajorVersion;
public ushort MaxSupportedMajorVersion;
public void Read(Stream stream)
{
UsnJournalId = stream.ReadULong();
FirstUsn = stream.ReadLong();
NextUsn = stream.ReadLong();
LowestValidUsn = stream.ReadLong();
MaxUsn = stream.ReadLong();
MaximumSize = stream.ReadULong();
AllocationDelta = stream.ReadULong();
MinSupportedMajorVersion = stream.ReadUShort();
MaxSupportedMajorVersion = stream.ReadUShort();
}
void IBinarySerialize.Write(Stream stream)
{
throw new NotImplementedException();
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct LUID
{
public UInt32 LowPart;
public Int32 HighPart;
}
[StructLayout(LayoutKind.Sequential)]
internal struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public UInt32 Attributes;
}
internal struct TOKEN_PRIVILEGES
{
public UInt32 PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] // !! think we only need one
public LUID_AND_ATTRIBUTES[ ] Privileges;
}
[Flags]
internal enum EFileAttributes: uint
{
/// <summary/>
None = 0,
//--> these are consistent w/ .Net FileAttributes...
Readonly = 0x00000001,
Hidden = 0x00000002,
System = 0x00000004,
Directory = 0x00000010,
Archive = 0x00000020,
Device = 0x00000040,
Normal = 0x00000080,
Temporary = 0x00000100,
SparseFile = 0x00000200,
ReparsePoint = 0x00000400,
Compressed = 0x00000800,
Offline = 0x00001000,
NotContentIndexed = 0x00002000,
Encrypted = 0x00004000,
//--> additional CreateFile call attributes...
Write_Through = 0x80000000,
Overlapped = 0x40000000,
NoBuffering = 0x20000000,
RandomAccess = 0x10000000,
SequentialScan = 0x08000000,
DeleteOnClose = 0x04000000,
BackupSemantics = 0x02000000,
PosixSemantics = 0x01000000,
OpenReparsePoint = 0x00200000,
OpenNoRecall = 0x00100000,
FirstPipeInstance = 0x00080000
}
/// <summary>Reasons the file changed (from USN journal)</summary>
[Flags]
public enum UsnReason: uint
{
BASIC_INFO_CHANGE = 0x00008000,
CLOSE = 0x80000000,
COMPRESSION_CHANGE = 0x00020000,
DATA_EXTEND = 0x00000002,
DATA_OVERWRITE = 0x00000001,
DATA_TRUNCATION = 0x00000004,
EA_CHANGE = 0x00000400,
ENCRYPTION_CHANGE = 0x00040000,
FILE_CREATE = 0x00000100,
FILE_DELETE = 0x00000200,
HARD_LINK_CHANGE = 0x00010000,
INDEXABLE_CHANGE = 0x00004000,
NAMED_DATA_EXTEND = 0x00000020,
NAMED_DATA_OVERWRITE = 0x00000010,
NAMED_DATA_TRUNCATION = 0x00000040,
OBJECT_ID_CHANGE = 0x00080000,
RENAME_NEW_NAME = 0x00002000,
RENAME_OLD_NAME = 0x00001000,
REPARSE_POINT_CHANGE = 0x00100000,
SECURITY_CHANGE = 0x00000800,
STREAM_CHANGE = 0x00200000,
None = 0x00000000
}
internal enum ECreationDisposition: uint
{
New = 1,
CreateAlways = 2,
OpenExisting = 3,
OpenAlways = 4,
TruncateExisting = 5
}
}
Everything.exe(桌面搜索應用程序)也訪問相同,所以我希望你能找到everything.exe的Source-Code的一些信息。
當Everything.exe首次運行時,它會根據NTFS主文件表中的文件元數據創建捲上每個文件和文件夾的名稱的索引。默認情況下,所有掛載的NTFS卷都被編入索引。[4]一旦創建,該索引就會不斷由NTFS更改日誌中的應用程序更新。[5]一切都在這個索引中搜索匹配用戶搜索表達式的文件名,這可能是目標文件名或正則表達式的一個片段,[6]在輸入搜索詞時顯示中間結果。
該URL不是Everythings源代碼,它只是它的SDK,不包含有關此主題的有價值的信息 – Suchiman
您可以使用Danny Couture用C#編寫的開放源代碼庫https://sourceforge.net/projects/ntfsreader/。
我測試了它,它的性能很好。它可以在不到2秒的時間內解析出超過100000個條目(文件和文件夾)的NTFS驅動器。
檢查http://www.codeproject.com/Articles/9293/Undelete-a-file-in-NTFS,只是捏住你需要的本地功能。 – devshorts
@devshorts感謝您的鏈接,我已經檢查過它,但無法找到相關信息。 –
選中此鏈接 - [MFT](http://code.msdn.microsoft.com/windowsdesktop/CCS-LABS-C-Accessing-the-d317805c/sourcecode?fileId=60931&pathId=14261056)。希望你有一些想法... –