Move MFTSearch to find file plugin.

This commit is contained in:
qianlifeng
2014-10-27 14:53:44 +08:00
parent c3ecf2d84e
commit 970c9e70e4
13 changed files with 15 additions and 11 deletions

View File

@@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wox.Infrastructure.MFTSearch
{
public class MFTSearchRecord
{
private USNRecord usn;
public MFTSearchRecord(USNRecord usn)
{
this.usn = usn;
}
public string FullPath
{
get { return usn.FullPath; }
}
public bool IsFolder
{
get { return usn.IsFolder; }
}
}
}

View File

@@ -1,275 +0,0 @@
/*
* Thanks to the https://github.com/yiwenshengmei/MyEverything, we can bring MFT search to Wox
*
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace Wox.Infrastructure.MFTSearch
{
public class MFTSearcher
{
private static MFTSearcherCache cache = new MFTSearcherCache();
public static void IndexVolume(string volume)
{
List<USNRecord> files;
List<USNRecord> folders;
EnumerateVolume(volume, out files, out folders);
cache.AddRecord(volume, files, USNRecordType.File);
cache.AddRecord(volume, folders, USNRecordType.Folder);
}
public static void IndexAllVolumes()
{
foreach (DriveInfo drive in DriveInfo.GetDrives())
{
IndexVolume(drive.Name.Replace("\\", ""));
}
}
public static long IndexedFileCount
{
get { return cache.FileCount; }
}
public static long IndexedFolderCount
{
get { return cache.FolderCount; }
}
public static List<MFTSearchRecord> Search(string item)
{
if (string.IsNullOrEmpty(item)) return new List<MFTSearchRecord>();
List<USNRecord> found = cache.FindByName(item);
found.ForEach(x => FillPath(x.VolumeName, x, cache));
return found.ConvertAll(o => new MFTSearchRecord(o));
}
private static void AddVolumeRootRecord(string volumeName, ref List<USNRecord> folders)
{
string rightVolumeName = string.Concat("\\\\.\\", volumeName);
rightVolumeName = string.Concat(rightVolumeName, Path.DirectorySeparatorChar);
IntPtr hRoot = PInvokeWin32.CreateFile(rightVolumeName,
0,
PInvokeWin32.FILE_SHARE_READ | PInvokeWin32.FILE_SHARE_WRITE,
IntPtr.Zero,
PInvokeWin32.OPEN_EXISTING,
PInvokeWin32.FILE_FLAG_BACKUP_SEMANTICS,
IntPtr.Zero);
if (hRoot.ToInt32() != PInvokeWin32.INVALID_HANDLE_VALUE)
{
PInvokeWin32.BY_HANDLE_FILE_INFORMATION fi = new PInvokeWin32.BY_HANDLE_FILE_INFORMATION();
bool bRtn = PInvokeWin32.GetFileInformationByHandle(hRoot, out fi);
if (bRtn)
{
UInt64 fileIndexHigh = (UInt64)fi.FileIndexHigh;
UInt64 indexRoot = (fileIndexHigh << 32) | fi.FileIndexLow;
folders.Add(new USNRecord
{
FRN = indexRoot,
Name = volumeName,
ParentFrn = 0,
IsVolumeRoot = true,
IsFolder = true,
VolumeName = volumeName
});
}
else
{
throw new IOException("GetFileInformationbyHandle() returned invalid handle",
new Win32Exception(Marshal.GetLastWin32Error()));
}
PInvokeWin32.CloseHandle(hRoot);
}
else
{
throw new IOException("Unable to get root frn entry", new Win32Exception(Marshal.GetLastWin32Error()));
}
}
private static void EnumerateVolume(string volumeName, out List<USNRecord> files, out List<USNRecord> flds)
{
files = new List<USNRecord>();
flds = new List<USNRecord>();
IntPtr medBuffer = IntPtr.Zero;
IntPtr pVolume = IntPtr.Zero;
try
{
AddVolumeRootRecord(volumeName, ref flds);
pVolume = GetVolumeJournalHandle(volumeName);
EnableVomuleJournal(pVolume);
SetupMFTEnumInBuffer(ref medBuffer, pVolume);
EnumerateFiles(volumeName, pVolume, medBuffer, ref files, ref flds);
}
catch (Exception e)
{
Console.WriteLine(e.Message, e);
Exception innerException = e.InnerException;
while (innerException != null)
{
Console.WriteLine(innerException.Message, innerException);
innerException = innerException.InnerException;
}
throw new ApplicationException("Error in EnumerateVolume()", e);
}
finally
{
if (pVolume.ToInt32() != PInvokeWin32.INVALID_HANDLE_VALUE)
{
PInvokeWin32.CloseHandle(pVolume);
if (medBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(medBuffer);
}
}
}
}
internal static IntPtr GetVolumeJournalHandle(string volumeName)
{
string vol = string.Concat("\\\\.\\", volumeName);
IntPtr pVolume = PInvokeWin32.CreateFile(vol,
PInvokeWin32.GENERIC_READ | PInvokeWin32.GENERIC_WRITE,
PInvokeWin32.FILE_SHARE_READ | PInvokeWin32.FILE_SHARE_WRITE,
IntPtr.Zero,
PInvokeWin32.OPEN_EXISTING,
0,
IntPtr.Zero);
if (pVolume.ToInt32() == PInvokeWin32.INVALID_HANDLE_VALUE)
{
throw new IOException(string.Format("CreateFile(\"{0}\") returned invalid handle", volumeName),
new Win32Exception(Marshal.GetLastWin32Error()));
}
else
{
return pVolume;
}
}
unsafe private static void EnableVomuleJournal(IntPtr pVolume)
{
UInt64 MaximumSize = 0x800000;
UInt64 AllocationDelta = 0x100000;
UInt32 cb;
PInvokeWin32.CREATE_USN_JOURNAL_DATA cujd;
cujd.MaximumSize = MaximumSize;
cujd.AllocationDelta = AllocationDelta;
int sizeCujd = Marshal.SizeOf(cujd);
IntPtr cujdBuffer = Marshal.AllocHGlobal(sizeCujd);
PInvokeWin32.ZeroMemory(cujdBuffer, sizeCujd);
Marshal.StructureToPtr(cujd, cujdBuffer, true);
bool fOk = PInvokeWin32.DeviceIoControl(pVolume, PInvokeWin32.FSCTL_CREATE_USN_JOURNAL,
cujdBuffer, sizeCujd, IntPtr.Zero, 0, out cb, IntPtr.Zero);
if (!fOk)
{
throw new IOException("DeviceIoControl() returned false", new Win32Exception(Marshal.GetLastWin32Error()));
}
}
unsafe internal static bool QueryUSNJournal(IntPtr pVolume, out PInvokeWin32.USN_JOURNAL_DATA ujd, out uint bytesReturned)
{
bool bOK = PInvokeWin32.DeviceIoControl(
pVolume, PInvokeWin32.FSCTL_QUERY_USN_JOURNAL,
IntPtr.Zero,
0,
out ujd,
sizeof(PInvokeWin32.USN_JOURNAL_DATA),
out bytesReturned,
IntPtr.Zero
);
return bOK;
}
unsafe private static void SetupMFTEnumInBuffer(ref IntPtr medBuffer, IntPtr pVolume)
{
uint bytesReturned = 0;
PInvokeWin32.USN_JOURNAL_DATA ujd = new PInvokeWin32.USN_JOURNAL_DATA();
bool bOk = QueryUSNJournal(pVolume, out ujd, out bytesReturned);
if (bOk)
{
PInvokeWin32.MFT_ENUM_DATA med;
med.StartFileReferenceNumber = 0;
med.LowUsn = 0;
med.HighUsn = ujd.NextUsn;
int sizeMftEnumData = Marshal.SizeOf(med);
medBuffer = Marshal.AllocHGlobal(sizeMftEnumData);
PInvokeWin32.ZeroMemory(medBuffer, sizeMftEnumData);
Marshal.StructureToPtr(med, medBuffer, true);
}
else
{
throw new IOException("DeviceIoControl() returned false", new Win32Exception(Marshal.GetLastWin32Error()));
}
}
unsafe private static void EnumerateFiles(string volumeName, IntPtr pVolume, IntPtr medBuffer, ref List<USNRecord> files, ref List<USNRecord> folders)
{
IntPtr pData = Marshal.AllocHGlobal(sizeof(UInt64) + 0x10000);
PInvokeWin32.ZeroMemory(pData, sizeof(UInt64) + 0x10000);
uint outBytesReturned = 0;
while (false != PInvokeWin32.DeviceIoControl(pVolume, 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));
while (outBytesReturned > 60)
{
PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(pUsnRecord);
if (usn.IsFolder)
{
folders.Add(new USNRecord
{
Name = usn.FileName,
ParentFrn = usn.ParentFRN,
FRN = usn.FRN,
IsFolder = true,
VolumeName = volumeName
});
}
else
{
files.Add(new USNRecord
{
Name = usn.FileName,
ParentFrn = usn.ParentFRN,
FRN = usn.FRN,
IsFolder = false,
VolumeName = volumeName
});
}
pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usn.RecordLength);
outBytesReturned -= usn.RecordLength;
}
Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0));
}
Marshal.FreeHGlobal(pData);
}
internal static void FillPath(string volume, USNRecord record, MFTSearcherCache db)
{
if (record == null) return;
var fdSource = db.GetFolderSource(volume);
string fullpath = record.Name;
FindRecordPath(record, ref fullpath, fdSource);
record.FullPath = fullpath;
}
private static void FindRecordPath(USNRecord curRecord, ref string fullpath, Dictionary<ulong, USNRecord> fdSource)
{
if (curRecord.IsVolumeRoot) return;
USNRecord nextRecord = null;
if (!fdSource.TryGetValue(curRecord.ParentFrn, out nextRecord))
return;
fullpath = string.Format("{0}{1}{2}", nextRecord.Name, Path.DirectorySeparatorChar, fullpath);
FindRecordPath(nextRecord, ref fullpath, fdSource);
}
}
}

View File

@@ -1,132 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Wox.Infrastructure.MFTSearch
{
internal class MFTSearcherCache
{
private Dictionary<string, Dictionary<ulong, USNRecord>> _volumes_files = new Dictionary<string, Dictionary<ulong, USNRecord>>();
private Dictionary<string, Dictionary<ulong, USNRecord>> _volumes_folders = new Dictionary<string, Dictionary<ulong, USNRecord>>();
public MFTSearcherCache() { }
public bool ContainsVolume(string volume)
{
return _volumes_files.ContainsKey(volume) && _volumes_folders.ContainsKey(volume);
}
public void AddRecord(string volume, List<USNRecord> r, USNRecordType type)
{
if (type == USNRecordType.File)
{
CheckHashTableKey(_volumes_files, volume);
r.ForEach(x => _volumes_files[volume].Add(x.FRN, x));
}
else
{
CheckHashTableKey(_volumes_folders, volume);
r.ForEach(x => _volumes_folders[volume].Add(x.FRN, x));
}
}
public void AddRecord(string volume, USNRecord record, USNRecordType type)
{
if (type == USNRecordType.File)
{
CheckHashTableKey(_volumes_files, volume);
_volumes_files[volume].Add(record.FRN, record);
}
else
{
CheckHashTableKey(_volumes_folders, volume);
_volumes_folders[volume].Add(record.FRN, record);
}
}
private void CheckHashTableKey(Dictionary<string, Dictionary<ulong, USNRecord>> hashtable, string key)
{
if (!hashtable.ContainsKey(key))
hashtable.Add(key, new Dictionary<ulong, USNRecord>());
}
public bool DeleteRecord(string volume, ulong frn)
{
bool result = false;
result = DeleteRecordHashTableItem(_volumes_files, volume, frn);
if (!result) result = DeleteRecordHashTableItem(_volumes_folders, volume, frn);
return result;
}
private bool DeleteRecordHashTableItem(Dictionary<string, Dictionary<ulong, USNRecord>> hashtable, string volume, ulong frn)
{
if (hashtable.ContainsKey(volume) && hashtable[volume].ContainsKey(frn))
{
hashtable[volume].Remove(frn);
return true;
}
else
{
return false;
}
}
public void UpdateRecord(string volume, USNRecord record, USNRecordType type)
{
if (type == USNRecordType.File)
RealUpdateRecord(volume, _volumes_files, record);
else
RealUpdateRecord(volume, _volumes_folders, record);
}
private bool RealUpdateRecord(string volume, Dictionary<string, Dictionary<ulong, USNRecord>> source, USNRecord record)
{
if (source.ContainsKey(volume) && source[volume].ContainsKey(record.FRN))
{
source[volume][record.FRN] = record;
return true;
}
else
{
return false;
}
}
public List<USNRecord> FindByName(string filename)
{
filename = filename.ToLower();
var fileQuery = from filesInVolumeDic in _volumes_files.Values
from eachFilePair in filesInVolumeDic
where eachFilePair.Value.Name.ToLower().Contains(filename)
select eachFilePair.Value;
var folderQuery = from fldsInVolumeDic in _volumes_folders.Values
from eachFldPair in fldsInVolumeDic
where eachFldPair.Value.Name.ToLower().Contains(filename)
select eachFldPair.Value;
List<USNRecord> result = new List<USNRecord>();
result.AddRange(fileQuery);
result.AddRange(folderQuery);
return result;
}
public USNRecord FindByFrn(string volume, ulong frn)
{
if ((!_volumes_files.ContainsKey(volume)) || (!_volumes_folders.ContainsKey(volume)))
throw new Exception(string.Format("DB not contain the volume: {0}", volume));
USNRecord result = null;
_volumes_files[volume].TryGetValue(frn, out result);
if (result != null) return result;
_volumes_folders[volume].TryGetValue(frn, out result);
return result;
}
public long FileCount
{
get { return _volumes_files.Sum(x => x.Value.Count); }
}
public long FolderCount
{
get { return _volumes_folders.Sum(x => x.Value.Count); }
}
public Dictionary<ulong, USNRecord> GetFolderSource(string volume)
{
Dictionary<ulong, USNRecord> result = null;
_volumes_folders.TryGetValue(volume, out result);
return result;
}
}
}

View File

@@ -1,165 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Wox.Infrastructure.MFTSearch {
public class PInvokeWin32
{
public const UInt32 GENERIC_READ = 0x80000000;
public const UInt32 GENERIC_WRITE = 0x40000000;
public const UInt32 FILE_SHARE_READ = 0x00000001;
public const UInt32 FILE_SHARE_WRITE = 0x00000002;
public const UInt32 FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
public const UInt32 OPEN_EXISTING = 3;
public const UInt32 FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
public const Int32 INVALID_HANDLE_VALUE = -1;
public const UInt32 FSCTL_QUERY_USN_JOURNAL = 0x000900f4;
public const UInt32 FSCTL_ENUM_USN_DATA = 0x000900b3;
public const UInt32 FSCTL_CREATE_USN_JOURNAL = 0x000900e7;
public const UInt32 FSCTL_READ_USN_JOURNAL = 0x000900bb;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes,
uint dwCreationDisposition, uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetFileInformationByHandle(IntPtr hFile,
out BY_HANDLE_FILE_INFORMATION lpFileInformation);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeviceIoControl(IntPtr hDevice,
UInt32 dwIoControlCode,
IntPtr lpInBuffer, Int32 nInBufferSize,
out USN_JOURNAL_DATA lpOutBuffer, Int32 nOutBufferSize,
out uint lpBytesReturned, IntPtr lpOverlapped);
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeviceIoControl(IntPtr hDevice,
UInt32 dwIoControlCode,
IntPtr lpInBuffer, Int32 nInBufferSize,
IntPtr lpOutBuffer, Int32 nOutBufferSize,
out uint lpBytesReturned, IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
public static extern void ZeroMemory(IntPtr ptr, Int32 size);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BY_HANDLE_FILE_INFORMATION {
public uint FileAttributes;
public FILETIME CreationTime;
public FILETIME LastAccessTime;
public FILETIME LastWriteTime;
public uint VolumeSerialNumber;
public uint FileSizeHigh;
public uint FileSizeLow;
public uint NumberOfLinks;
public uint FileIndexHigh;
public uint FileIndexLow;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct FILETIME {
public uint DateTimeLow;
public uint DateTimeHigh;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USN_JOURNAL_DATA {
public UInt64 UsnJournalID;
public Int64 FirstUsn;
public Int64 NextUsn;
public Int64 LowestValidUsn;
public Int64 MaxUsn;
public UInt64 MaximumSize;
public UInt64 AllocationDelta;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MFT_ENUM_DATA {
public UInt64 StartFileReferenceNumber;
public Int64 LowUsn;
public Int64 HighUsn;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CREATE_USN_JOURNAL_DATA {
public UInt64 MaximumSize;
public UInt64 AllocationDelta;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct READ_USN_JOURNAL_DATA {
public Int64 StartUsn;
public UInt32 ReasonMask;
public UInt32 ReturnOnlyOnClose;
public UInt64 Timeout;
public UInt64 BytesToWaitFor;
public UInt64 UsnJournalID;
}
public class USN_RECORD {
public UInt32 RecordLength;
public UInt16 MajorVersion;
public UInt16 MinorVersion;
public UInt64 FRN; // 8
public UInt64 ParentFRN; // 16
public Int64 Usn; // Need be care
public UInt64 TimeStamp; // Need Be care
public UInt32 Reason;
public UInt32 SourceInfo;
public UInt32 SecurityId;
public UInt32 FileAttributes; // 52
public UInt16 FileNameLength;
public UInt16 FileNameOffset;
public string FileName = string.Empty;
private const int RecordLength_OFFSET = 0;
private const int MajorVersion_OFFSET = 4;
private const int MinorVersion_OFFSET = 6;
private const int FileReferenceNumber_OFFSET = 8;
private const int ParentFileReferenceNumber_OFFSET = 16;
private const int Usn_OFFSET = 24;
private const int TimeStamp_OFFSET = 32;
private const int Reason_OFFSET = 40;
private const int SourceInfo_OFFSET = 44;
private const int SecurityId_OFFSET = 48;
private const int FileAttributes_OFFSET = 52;
private const int FileNameLength_OFFSET = 56;
private const int FileNameOffset_OFFSET = 58;
private const int FileName_OFFSET = 60;
public USN_RECORD(IntPtr p) {
this.RecordLength = (UInt32)Marshal.ReadInt32(p, RecordLength_OFFSET);
this.MajorVersion = (UInt16)Marshal.ReadInt16(p, MajorVersion_OFFSET);
this.MinorVersion = (UInt16)Marshal.ReadInt16(p, MinorVersion_OFFSET);
this.FRN = (UInt64)Marshal.ReadInt64(p, FileReferenceNumber_OFFSET);
this.ParentFRN = (UInt64)Marshal.ReadInt64(p, ParentFileReferenceNumber_OFFSET);
this.Usn = Marshal.ReadInt64(p, Usn_OFFSET);
this.TimeStamp = (UInt64)Marshal.ReadInt64(p, TimeStamp_OFFSET);
this.Reason = (UInt32)Marshal.ReadInt32(p, Reason_OFFSET);
this.SourceInfo = (UInt32)Marshal.ReadInt32(p, SourceInfo_OFFSET);
this.SecurityId = (UInt32)Marshal.ReadInt32(p, SecurityId_OFFSET);
this.FileAttributes = (UInt32)Marshal.ReadInt32(p, FileAttributes_OFFSET);
this.FileNameLength = (UInt16)Marshal.ReadInt16(p, FileNameLength_OFFSET);
this.FileNameOffset = (UInt16)Marshal.ReadInt16(p, FileNameOffset_OFFSET);
this.FileName = Marshal.PtrToStringUni(new IntPtr(p.ToInt32() + this.FileNameOffset), this.FileNameLength / sizeof(char));
}
public bool IsFolder {
get { return 0 != (FileAttributes & PInvokeWin32.FILE_ATTRIBUTE_DIRECTORY); }
}
}
}
}

View File

@@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Wox.Infrastructure.MFTSearch
{
internal class USNChangeReason
{
public static Dictionary<string, UInt32> USN_REASONS = new Dictionary<string, UInt32> {
{"USN_REASON_DATA_OVERWRITE", 0x00000001},
{"USN_REASON_DATA_EXTEND", 0x00000002},
{"USN_REASON_DATA_TRUNCATION", 0x00000004},
{"USN_REASON_NAMED_DATA_OVERWRITE", 0x00000010},
{"USN_REASON_NAMED_DATA_EXTEND", 0x00000020},
{"USN_REASON_NAMED_DATA_TRUNCATION", 0x00000040},
{"USN_REASON_FILE_CREATE", 0x00000100},
{"USN_REASON_FILE_DELETE", 0x00000200},
{"USN_REASON_EA_CHANGE", 0x00000400},
{"USN_REASON_SECURITY_CHANGE", 0x00000800},
{"USN_REASON_RENAME_OLD_NAME", 0x00001000},
{"USN_REASON_RENAME_NEW_NAME", 0x00002000},
{"USN_REASON_INDEXABLE_CHANGE", 0x00004000},
{"USN_REASON_BASIC_INFO_CHANGE", 0x00008000},
{"USN_REASON_HARD_LINK_CHANGE", 0x00010000},
{"USN_REASON_COMPRESSION_CHANGE", 0x00020000},
{"USN_REASON_ENCRYPTION_CHANGE", 0x00040000},
{"USN_REASON_OBJECT_ID_CHANGE", 0x00080000},
{"USN_REASON_REPARSE_POINT_CHANGE", 0x00100000},
{"USN_REASON_STREAM_CHANGE", 0x00200000},
{"USN_REASON_TRANSACTED_CHANGE", 0x00400000},
{"USN_REASON_CLOSE", 0x80000000}
};
public static string ReasonPrettyFormat(UInt32 rsn)
{
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (var rsnPair in USN_REASONS)
{
if ((rsnPair.Value & rsn) != 0)
sb.Append(rsnPair.Key + " ");
}
sb.Append("]");
return sb.ToString();
}
}
}

View File

@@ -1,33 +0,0 @@
using System;
namespace Wox.Infrastructure.MFTSearch
{
public class USNRecord
{
public string Name { get; set; }
public ulong FRN { get; set; }
public UInt64 ParentFrn { get; set; }
public string FullPath { get; set; }
public bool IsVolumeRoot { get; set; }
public bool IsFolder { get; set; }
public string VolumeName { get; set; }
public override string ToString()
{
return string.IsNullOrEmpty(FullPath) ? Name : FullPath;
}
public static USNRecord ParseUSN(string volume, PInvokeWin32.USN_RECORD usn)
{
return new USNRecord
{
FRN = usn.FRN,
Name = usn.FileName,
ParentFrn = usn.ParentFRN,
IsFolder = usn.IsFolder,
VolumeName = volume
};
}
}
}

View File

@@ -1,8 +0,0 @@
namespace Wox.Infrastructure.MFTSearch
{
internal enum USNRecordType
{
File,
Folder
}
}

View File

@@ -1,158 +0,0 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Runtime.InteropServices;
//using System.Threading;
//using System.Diagnostics;
//using System.IO;
//using Wox.Infrastructure.MFTSearch;
//namespace MyEverything
//{
// internal class VolumeMonitor
// {
// public Action<USNRecord> RecordAddedEvent;
// public Action<USNRecord> RecordDeletedEvent;
// public Action<USNRecord, USNRecord> RecordRenameEvent;
// public void Monitor(List<string> volumes, MFTSearcherCache db)
// {
// foreach (var volume in volumes)
// {
// if (string.IsNullOrEmpty(volume)) throw new InvalidOperationException("Volume cant't be null or empty string.");
// if (!db.ContainsVolume(volume)) throw new InvalidOperationException(string.Format("Volume {0} must be scaned first."));
// Thread th = new Thread(new ParameterizedThreadStart(MonitorThread));
// th.Start(new Dictionary<string, object> { { "Volume", volume }, { "MFTSearcherCache", db } });
// }
// }
// private PInvokeWin32.READ_USN_JOURNAL_DATA SetupInputData4JournalRead(string volume, uint reason)
// {
// IntPtr pMonitorVolume = MFTSearcher.GetVolumeJournalHandle(volume);
// uint bytesReturned = 0;
// PInvokeWin32.USN_JOURNAL_DATA ujd = new PInvokeWin32.USN_JOURNAL_DATA();
// Wox.Infrastructure.MFTSearch.MFTSearcher.QueryUSNJournal(pMonitorVolume, out ujd, out bytesReturned);
// // 构建输入参数
// PInvokeWin32.READ_USN_JOURNAL_DATA rujd = new PInvokeWin32.READ_USN_JOURNAL_DATA();
// rujd.StartUsn = ujd.NextUsn;
// rujd.ReasonMask = reason;
// rujd.ReturnOnlyOnClose = 1;
// rujd.Timeout = 0;
// rujd.BytesToWaitFor = 1;
// rujd.UsnJournalID = ujd.UsnJournalID;
// return rujd;
// }
// private void MonitorThread(object param)
// {
// MFTSearcherCache db = (param as Dictionary<string, object>)["MFTSearcherCache"] as MFTSearcherCache;
// string volume = (param as Dictionary<string, object>)["Volume"] as string;
// IntPtr pbuffer = Marshal.AllocHGlobal(0x1000);
// PInvokeWin32.READ_USN_JOURNAL_DATA rujd = SetupInputData4JournalRead(volume, 0xFFFFFFFF);
// UInt32 cbRead;
// IntPtr prujd;
// while (true)
// {
// prujd = Marshal.AllocHGlobal(Marshal.SizeOf(rujd));
// PInvokeWin32.ZeroMemory(prujd, Marshal.SizeOf(rujd));
// Marshal.StructureToPtr(rujd, prujd, true);
// Debug.WriteLine(string.Format("\nMoniting on {0}......", volume));
// IntPtr pVolume = Wox.Infrastructure.MFTSearch.MFTSearcher.GetVolumeJournalHandle(volume);
// bool fok = PInvokeWin32.DeviceIoControl(pVolume,
// PInvokeWin32.FSCTL_READ_USN_JOURNAL,
// prujd, Marshal.SizeOf(typeof(PInvokeWin32.READ_USN_JOURNAL_DATA)),
// pbuffer, 0x1000, out cbRead, IntPtr.Zero);
// IntPtr pRealData = new IntPtr(pbuffer.ToInt32() + Marshal.SizeOf(typeof(Int64)));
// uint offset = 0;
// if (fok)
// {
// while (offset + Marshal.SizeOf(typeof(Int64)) < cbRead)
// {
// PInvokeWin32.USN_RECORD usn = new PInvokeWin32.USN_RECORD(new IntPtr(pRealData.ToInt32() + (int)offset));
// ProcessUSN(usn, volume, db);
// offset += usn.RecordLength;
// }
// }
// Marshal.FreeHGlobal(prujd);
// rujd.StartUsn = Marshal.ReadInt64(pbuffer);
// }
// }
// private void ProcessUSN(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
// {
// var dbCached = db.FindByFrn(volume, usn.FRN);
// Wox.Infrastructure.MFTSearch.MFTSearcher.FillPath(volume, dbCached, db);
// Debug.WriteLine(string.Format("------USN[frn={0}]------", usn.FRN));
// Debug.WriteLine(string.Format("FileName={0}, USNChangeReason={1}", usn.FileName, USNChangeReason.ReasonPrettyFormat(usn.Reason)));
// Debug.WriteLine(string.Format("FileName[Cached]={0}", dbCached == null ? "NoCache" : dbCached.FullPath));
// Debug.WriteLine("--------------------------------------");
// if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_RENAME_NEW_NAME"]))
// ProcessRenameNewName(usn, volume, db);
// if ((usn.Reason & USNChangeReason.USN_REASONS["USN_REASON_FILE_CREATE"]) != 0)
// ProcessFileCreate(usn, volume, db);
// if (MaskEqual(usn.Reason, USNChangeReason.USN_REASONS["USN_REASON_FILE_DELETE"]))
// ProcessFileDelete(usn, volume, db);
// }
// private void ProcessFileDelete(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
// {
// var cached = db.FindByFrn(volume, usn.FRN);
// if (cached == null)
// {
// return;
// }
// else
// {
// Wox.Infrastructure.MFTSearch.MFTSearcher.FillPath(volume, cached, db);
// var deleteok = db.DeleteRecord(volume, usn.FRN);
// Debug.WriteLine(string.Format(">>>> File {0} deleted {1}.", cached.FullPath, deleteok ? "successful" : "fail"));
// if (RecordDeletedEvent != null)
// RecordDeletedEvent(cached);
// }
// }
// private void ProcessRenameNewName(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
// {
// USNRecord newRecord = USNRecord.ParseUSN(volume, usn);
// //string fullpath = newRecord.Name;
// //db.FindRecordPath(newRecord, ref fullpath, db.GetFolderSource(volume));
// //newRecord.FullPath = fullpath;
// var oldRecord = db.FindByFrn(volume, usn.FRN);
// Wox.Infrastructure.MFTSearch.MFTSearcher.FillPath(volume, oldRecord, db);
// Wox.Infrastructure.MFTSearch.MFTSearcher.FillPath(volume, newRecord, db);
// Debug.WriteLine(string.Format(">>>> RenameFile {0} to {1}", oldRecord.FullPath, newRecord.FullPath));
// db.UpdateRecord(volume, newRecord,
// usn.IsFolder ? USNRecordType.Folder : USNRecordType.File);
// if (RecordRenameEvent != null) RecordRenameEvent(oldRecord, newRecord);
// if (newRecord.FullPath.Contains("$RECYCLE.BIN"))
// {
// Debug.WriteLine(string.Format(">>>> Means {0} moved to recycle.", oldRecord.FullPath));
// }
// }
// private void ProcessFileCreate(PInvokeWin32.USN_RECORD usn, string volume, MFTSearcherCache db)
// {
// USNRecord record = USNRecord.ParseUSN(volume, usn);
// //string fullpath = record.Name;
// //db.FindRecordPath(record, ref fullpath, db.GetFolderSource(volume));
// //record.FullPath = fullpath;
// db.AddRecord(volume, record, usn.IsFolder ? USNRecordType.Folder : USNRecordType.File);
// Wox.Infrastructure.MFTSearch.MFTSearcher.FillPath(volume, record, db);
// Debug.WriteLine(string.Format(">>>> NewFile: {0}", record.FullPath));
// if (RecordAddedEvent != null)
// RecordAddedEvent(record);
// }
// private bool MaskEqual(uint target, uint compare)
// {
// return (target & compare) != 0;
// }
// }
//}

View File

@@ -31,7 +31,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
@@ -57,14 +57,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Logger\Log.cs" />
<Compile Include="MFTSearch\MFTSearcher.cs" />
<Compile Include="MFTSearch\MFTSearcherCache.cs" />
<Compile Include="MFTSearch\MFTSearchRecord.cs" />
<Compile Include="MFTSearch\USNRecord.cs" />
<Compile Include="MFTSearch\USNRecordType.cs" />
<Compile Include="MFTSearch\PInvokeWin32.cs" />
<Compile Include="MFTSearch\USNChangeReason.cs" />
<Compile Include="MFTSearch\VolumeMonitor.cs" />
<Compile Include="PeHeaderReader.cs" />
<Compile Include="Storage\UserSettings\CustomizedPluginConfig.cs" />
<Compile Include="Storage\UserSettings\FolderLink.cs" />