ソースを参照

添加everything的文件搜索引擎

yuzhengyang 8 年 前
コミット
448eeefbe1
25 ファイル変更1665 行追加0 行削除
  1. 36 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Properties/AssemblyInfo.cs
  2. 75 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/QueryEngine/FileAndDirectoryEntry.cs
  3. 140 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/QueryEngine/FileQueryEngine.cs
  4. 41 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/QueryEngine/FrnFilePath.cs
  5. 30 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnControlCode.cs
  6. 50 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnEntry.cs
  7. 14 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnErrorCode.cs
  8. 60 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnJournalData.cs
  9. 231 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnOperator.cs
  10. 30 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnReasonCode.cs
  11. 29 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Constants/Win32ApiConstant.cs
  12. 26 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/BY_HANDLE_FILE_INFORMATION.cs
  13. 15 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/CREATE_USN_JOURNAL_DATA.cs
  14. 17 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/MFT_ENUM_DATA.cs
  15. 17 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/POINT.cs
  16. 20 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/READ_USN_JOURNAL_DATA.cs
  17. 21 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/USN_JOURNAL_DATA.cs
  18. 48 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/USN_RECORD_V2.cs
  19. 556 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Win32Api.cs
  20. 72 0
      Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Y.FileQueryEngine.csproj
  21. 13 0
      Fork.Net/Fork.Net.sln
  22. 38 0
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Helpers/FileHelper.cs
  23. 10 0
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Oreo.FileMan.csproj
  24. 1 0
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Partial/FileTypePartial.cs
  25. 75 0
      Fork.Net/Oreo.Plugins/Oreo.FileMan/Properties/app.manifest

+ 36 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的一般信息由以下
+// 控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("Y.FileQueryEngine")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Y.FileQueryEngine")]
+[assembly: AssemblyCopyright("Copyright ©  2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//将 ComVisible 设置为 false 将使此程序集中的类型
+//对 COM 组件不可见。  如果需要从 COM 访问此程序集中的类型,
+//请将此类型的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("497f570c-8398-458d-970c-dfa3dd9fe746")]
+
+// 程序集的版本信息由下列四个值组成: 
+//
+//      主版本
+//      次版本
+//      生成号
+//      修订号
+//
+//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”: :
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 75 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/QueryEngine/FileAndDirectoryEntry.cs

@@ -0,0 +1,75 @@
+using System;
+using Y.FileQueryEngine.UsnOperation;
+
+namespace Y.FileQueryEngine.QueryEngine
+{
+    public class FileAndDirectoryEntry
+    {
+        protected UInt64 fileReferenceNumber;
+
+        protected UInt64 parentFileReferenceNumber;
+
+        protected string fileName;
+
+        protected bool isFolder;
+
+        protected string path;
+
+        public UInt64 FileReferenceNumber
+        {
+            get
+            {
+                return this.fileReferenceNumber;
+            }
+        }
+
+        public UInt64 ParentFileReferenceNumber
+        {
+            get
+            {
+                return this.parentFileReferenceNumber;
+            }
+        }
+
+        public string FileName
+        {
+            get
+            {
+                return this.fileName;
+            }
+        }
+
+        public string Path
+        {
+            get
+            {
+                return this.path;
+            }
+        }
+
+        public string FullFileName
+        {
+            get
+            {
+                return string.Concat(this.path, "\\", this.fileName);
+            }
+        }
+
+        public bool IsFolder
+        {
+            get
+            {
+                return this.isFolder;
+            }
+        }
+
+        public FileAndDirectoryEntry(UsnEntry usnEntry, string path)
+        {
+            this.fileReferenceNumber = usnEntry.FileReferenceNumber;
+            this.parentFileReferenceNumber = usnEntry.ParentFileReferenceNumber;
+            this.fileName = usnEntry.FileName;
+            this.isFolder = usnEntry.IsFolder;
+            this.path = path;
+        }
+    }
+}

+ 140 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/QueryEngine/FileQueryEngine.cs

@@ -0,0 +1,140 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.IO;
+using Y.FileQueryEngine.UsnOperation;
+
+namespace Y.FileQueryEngine.QueryEngine
+{
+    public class FileQueryEngine
+    {
+        /// <summary>
+        /// When its values is 1407374883553285(0x5000000000005L), it means this file/folder is under drive root
+        /// </summary>
+        protected const UInt64 ROOT_FILE_REFERENCE_NUMBER = 0x5000000000005L;
+
+        protected static readonly string excludeFolders = string.Join("|",
+            new string[]
+            {
+                "$RECYCLE.BIN",
+                "System Volume Information",
+                "$AttrDef",
+                "$BadClus",
+                "$BitMap",
+                "$Boot",
+                "$LogFile",
+                "$Mft",
+                "$MftMirr",
+                "$Secure",
+                "$TxfLog",
+                "$UpCase",
+                "$Volume",
+                "$Extend"
+            }).ToUpper();
+        /// <summary>
+        /// 获取所有NTFS文件系统的固定磁盘
+        /// </summary>
+        /// <returns></returns>
+        public static IEnumerable<DriveInfo> GetFixedNtfsDrives()
+        {
+            return DriveInfo.GetDrives()
+                .Where(d => d.DriveType == DriveType.Fixed && d.DriveFormat.ToUpper() == "NTFS");
+        }
+        /// <summary>
+        /// 获取所有NTFS文件系统的磁盘
+        /// </summary>
+        /// <returns></returns>
+        public static IEnumerable<DriveInfo> GetReadyNtfsDrives()
+        {
+            return DriveInfo.GetDrives()
+                .Where(d => d.IsReady && d.DriveFormat.ToUpper() == "NTFS");
+        }
+
+        public static List<FileAndDirectoryEntry> GetAllFiles(DriveInfo drive)
+        {
+            List<FileAndDirectoryEntry> result = new List<FileAndDirectoryEntry>();
+            var usnOperator = new UsnOperator(drive);
+            var usnEntries = usnOperator.GetEntries().Where(e => !excludeFolders.Contains(e.FileName.ToUpper()));
+            var folders = usnEntries.Where(e => e.IsFolder).ToArray();
+            List<FrnFilePath> paths = GetFolderPath(folders, drive);
+            result.AddRange(usnEntries.Join(
+                paths,
+                usn => usn.ParentFileReferenceNumber,
+                path => path.FileReferenceNumber,
+                (usn, path) => new FileAndDirectoryEntry(usn, path.Path)));
+            return result;
+        }
+
+        private static List<FrnFilePath> GetFolderPath(UsnEntry[] folders, DriveInfo drive)
+        {
+            Dictionary<UInt64, FrnFilePath> pathDic = new Dictionary<ulong, FrnFilePath>();
+            pathDic.Add(ROOT_FILE_REFERENCE_NUMBER,
+                new FrnFilePath(ROOT_FILE_REFERENCE_NUMBER, null, string.Empty, drive.Name.TrimEnd('\\')));
+
+            foreach (var folder in folders)
+            {
+                pathDic.Add(folder.FileReferenceNumber,
+                    new FrnFilePath(folder.FileReferenceNumber, folder.ParentFileReferenceNumber, folder.FileName));
+            }
+
+            Stack<UInt64> treeWalkStack = new Stack<ulong>();
+
+            foreach (var key in pathDic.Keys)
+            {
+                treeWalkStack.Clear();
+
+                FrnFilePath currentValue = pathDic[key];
+
+                if (string.IsNullOrWhiteSpace(currentValue.Path)
+                    && currentValue.ParentFileReferenceNumber.HasValue
+                    && pathDic.ContainsKey(currentValue.ParentFileReferenceNumber.Value))
+                {
+                    FrnFilePath parentValue = pathDic[currentValue.ParentFileReferenceNumber.Value];
+
+                    while (string.IsNullOrWhiteSpace(parentValue.Path)
+                        && parentValue.ParentFileReferenceNumber.HasValue
+                        && pathDic.ContainsKey(parentValue.ParentFileReferenceNumber.Value))
+                    {
+                        currentValue = parentValue;
+
+                        if (currentValue.ParentFileReferenceNumber.HasValue
+                            && pathDic.ContainsKey(currentValue.ParentFileReferenceNumber.Value))
+                        {
+                            treeWalkStack.Push(key);
+                            parentValue = pathDic[currentValue.ParentFileReferenceNumber.Value];
+                        }
+                        else
+                        {
+                            parentValue = null;
+                            break;
+                        }
+                    }
+
+                    if (parentValue != null)
+                    {
+                        currentValue.Path = BuildPath(currentValue, parentValue);
+
+                        while (treeWalkStack.Count() > 0)
+                        {
+                            UInt64 walkedKey = treeWalkStack.Pop();
+
+                            FrnFilePath walkedNode = pathDic[walkedKey];
+                            FrnFilePath parentNode = pathDic[walkedNode.ParentFileReferenceNumber.Value];
+
+                            walkedNode.Path = BuildPath(walkedNode, parentNode);
+                        }
+                    }
+                }
+            }
+
+            var result = pathDic.Values.Where(p => !string.IsNullOrWhiteSpace(p.Path) && p.Path.StartsWith(drive.Name)).ToList();
+
+            return result;
+        }
+
+        private static string BuildPath(FrnFilePath currentNode, FrnFilePath parentNode)
+        {
+            return string.Concat(new string[] { parentNode.Path, "\\", currentNode.FileName });
+        }
+    }
+}

+ 41 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/QueryEngine/FrnFilePath.cs

@@ -0,0 +1,41 @@
+using System;
+
+namespace Y.FileQueryEngine.QueryEngine
+{
+    internal class FrnFilePath
+    {
+        private UInt64 fileReferenceNumber;
+
+        private UInt64? parentFileReferenceNumber;
+
+        private string fileName;
+
+        private string path;
+
+        public UInt64 FileReferenceNumber { get { return this.fileReferenceNumber; } }
+
+        public UInt64? ParentFileReferenceNumber { get { return this.parentFileReferenceNumber; } }
+
+        public string FileName { get { return this.fileName; } }
+
+        public string Path
+        { 
+            get
+            {
+                return this.path; 
+            }
+            set
+            {
+                this.path = value;
+            }
+        }
+
+        public FrnFilePath(UInt64 fileReferenceNumber, UInt64? parentFileReferenceNumber, string fileName, string path = null)
+        {
+            this.fileReferenceNumber = fileReferenceNumber;
+            this.parentFileReferenceNumber = parentFileReferenceNumber;
+            this.fileName = fileName;
+            this.path = path;
+        }
+    }
+}

+ 30 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnControlCode.cs

@@ -0,0 +1,30 @@
+using System;
+
+namespace Y.FileQueryEngine.UsnOperation
+{
+    internal static class UsnControlCode
+    {
+        private const UInt32 FILE_DEVICE_FILE_SYSTEM = 0x00000009;
+        private const UInt32 METHOD_NEITHER          = 3;
+        private const UInt32 METHOD_BUFFERED         = 0;
+        private const UInt32 FILE_ANY_ACCESS         = 0;
+        private const UInt32 FILE_SPECIAL_ACCESS     = 0;
+        private const UInt32 FILE_READ_ACCESS        = 1;
+        private const UInt32 FILE_WRITE_ACCESS       = 2;
+
+        // FSCTL_QUERY_USN_JOURNAL = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 61, METHOD_BUFFERED, FILE_ANY_ACCESS)
+        public const UInt32 FSCTL_QUERY_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (61 << 2) | METHOD_BUFFERED;
+
+        // FSCTL_ENUM_USN_DATA = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 44,  METHOD_NEITHER, FILE_ANY_ACCESS)
+        public const UInt32 FSCTL_ENUM_USN_DATA = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (44 << 2) | METHOD_NEITHER;
+
+        // FSCTL_CREATE_USN_JOURNAL = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 57,  METHOD_NEITHER, FILE_ANY_ACCESS)
+        public const UInt32 FSCTL_CREATE_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (57 << 2) | METHOD_NEITHER;
+
+        // FSCTL_READ_USN_JOURNAL = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 46,  METHOD_NEITHER, FILE_ANY_ACCESS)
+        public const UInt32 FSCTL_READ_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (46 << 2) | METHOD_NEITHER;
+
+        // FSCTL_DELETE_USN_JOURNAL = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 62, METHOD_BUFFERED, FILE_ANY_ACCESS)
+        public const UInt32 FSCTL_DELETE_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (62 << 2) | METHOD_BUFFERED;
+    }
+}

+ 50 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnEntry.cs

@@ -0,0 +1,50 @@
+using System;
+using Y.FileQueryEngine.Win32.Constants;
+using Y.FileQueryEngine.Win32.Structures;
+
+namespace Y.FileQueryEngine.UsnOperation
+{
+    /// <summary>
+    /// TODO: Update summary.
+    /// </summary>
+    public class UsnEntry
+    {
+        public UInt32 RecordLength { get; private set; }
+        public UInt64 FileReferenceNumber { get; private set; }
+
+        /// <summary>
+        /// Gets the parent file reference number.
+        /// When its values is 1407374883553285(0x5000000000005L), it means this file/folder is under drive root
+        /// </summary>
+        /// <value>
+        /// The parent file reference number.
+        /// </value>
+        public UInt64 ParentFileReferenceNumber { get; private set; }
+        public Int64 Usn { get; private set; }
+        public UInt32 Reason { get; private set; }
+        public UInt32 FileAttributes { get; private set; }
+        public Int32 FileNameLength { get; private set; }
+        public Int32 FileNameOffset { get; private set; }
+        public string FileName { get; private set; }
+        public bool IsFolder
+        {
+            get
+            {
+                return (this.FileAttributes & Win32ApiConstant.FILE_ATTRIBUTE_DIRECTORY) != 0;
+            }
+        }
+
+        public UsnEntry(USN_RECORD_V2 usnRecord)
+        {
+            this.RecordLength = usnRecord.RecordLength;
+            this.FileReferenceNumber = usnRecord.FileReferenceNumber;
+            this.ParentFileReferenceNumber = usnRecord.ParentFileReferenceNumber;
+            this.Usn = usnRecord.Usn;
+            this.Reason = usnRecord.Reason;
+            this.FileAttributes = usnRecord.FileAttributes;
+            this.FileNameLength = usnRecord.FileNameLength;
+            this.FileNameOffset = usnRecord.FileNameOffset;
+            this.FileName = usnRecord.FileName;
+        }
+    }
+}

+ 14 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnErrorCode.cs

@@ -0,0 +1,14 @@
+using System;
+
+namespace Y.FileQueryEngine.UsnOperation
+{
+    [Flags]
+    internal enum UsnErrorCode
+    {
+        SUCCESS                          = 0,
+        ERROR_INVALID_FUNCTION           = 0x1,
+        ERROR_INVALID_PARAMETER          = 0x57,
+        ERROR_JOURNAL_DELETE_IN_PROGRESS = 0x49A,
+        ERROR_JOURNAL_NOT_ACTIVE         = 0x49B
+    }
+}

+ 60 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnJournalData.cs

@@ -0,0 +1,60 @@
+using System;
+using System.IO;
+using Y.FileQueryEngine.Win32.Structures;
+
+namespace Y.FileQueryEngine.UsnOperation
+{
+    internal class UsnJournalData
+    {
+        public DriveInfo Drive { get; private set; }
+        public UInt64 UsnJournalID { get; private set; }
+        public Int64 FirstUsn { get; private set; }
+        public Int64 NextUsn { get; private set; }
+        public Int64 LowestValidUsn { get; private set; }
+        public Int64 MaxUsn { get; private set; }
+        public UInt64 MaximumSize { get; private set; }
+        public UInt64 AllocationDelta { get; private set; }
+
+        public UsnJournalData(DriveInfo drive, USN_JOURNAL_DATA ntfsUsnJournalData)
+        {
+            this.Drive = drive;
+            this.UsnJournalID = ntfsUsnJournalData.UsnJournalID;
+            this.FirstUsn = ntfsUsnJournalData.FirstUsn;
+            this.NextUsn = ntfsUsnJournalData.NextUsn;
+            this.LowestValidUsn = ntfsUsnJournalData.LowestValidUsn;
+            this.MaxUsn = ntfsUsnJournalData.MaxUsn;
+            this.MaximumSize = ntfsUsnJournalData.MaximumSize;
+            this.AllocationDelta = ntfsUsnJournalData.AllocationDelta;
+        }
+
+        // pesudo-code for checking valid USN journal
+        //private bool IsUsnJournalValid()
+        //{
+
+        //    bool isValid = true;
+        //    //
+        //    // is the JournalID from the previous state == JournalID from current state?
+        //    //
+        //    if (_previousUsnState.UsnJournalID == _currentUsnState.UsnJournalID)
+        //    {
+        //        //
+        //        // is the next usn to process still available
+        //        //
+        //        if (_previousUsnState.NextUsn > _currentUsnState.FirstUsn && _previousUsnState.NextUsn < _currentUsnState.NextUsn)
+        //        {
+        //            isValid = true;
+        //        }
+        //        else
+        //        {
+        //            isValid = false;
+        //        }
+        //    }
+        //    else
+        //    {
+        //        isValid = false;
+        //    }
+
+        //    return isValid;
+        //}
+    }
+}

+ 231 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnOperator.cs

@@ -0,0 +1,231 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+using Y.FileQueryEngine.Win32.Structures;
+using Y.FileQueryEngine.Win32;
+using Y.FileQueryEngine.Win32.Constants;
+
+namespace Y.FileQueryEngine.UsnOperation
+{
+    internal class UsnOperator : IDisposable
+    {
+        protected USN_JOURNAL_DATA ntfsUsnJournalData;
+
+        public DriveInfo Drive
+        {
+            get;
+            private set;
+        }
+
+        public string DriveLetter
+        {
+            get
+            {
+                return this.Drive.Name.TrimEnd(new char[] { '\\', ':' });
+            }
+        }
+
+        public IntPtr DriveRootHandle
+        {
+            get;
+            private set;
+        }
+
+        public UsnOperator(DriveInfo drive)
+        {
+            if (string.Compare(drive.DriveFormat, "ntfs", true) != 0)
+            {
+                throw new ArgumentException("USN journal only exists in NTFS drive.");
+            }
+
+            this.Drive = drive;
+            this.DriveRootHandle = this.GetRootHandle();
+            this.ntfsUsnJournalData = new USN_JOURNAL_DATA();
+        }
+
+        public UsnJournalData GetUsnJournal()
+        {
+            UsnErrorCode usnErrorCode = this.QueryUSNJournal();
+
+            UsnJournalData result = null;
+
+            if (usnErrorCode == UsnErrorCode.SUCCESS)
+            {
+                result = new UsnJournalData(this.Drive, this.ntfsUsnJournalData);
+            }
+
+            return result;
+        }
+
+        public bool CreateUsnJournal(UInt64 maximumSize = 0x10000000, UInt64 allocationDelta = 0x100000)
+        {
+            uint bytesReturnedCount;
+
+            var createUsnJournalData = new CREATE_USN_JOURNAL_DATA();
+            createUsnJournalData.MaximumSize = maximumSize;
+            createUsnJournalData.AllocationDelta = allocationDelta;
+
+            int sizeCujd = Marshal.SizeOf(createUsnJournalData);
+
+            IntPtr cujdBuffer = GetHeapGlobalPtr(sizeCujd);
+
+            Marshal.StructureToPtr(createUsnJournalData, cujdBuffer, true);
+
+            bool isSuccess = Win32Api.DeviceIoControl(
+                this.DriveRootHandle,
+                UsnControlCode.FSCTL_CREATE_USN_JOURNAL,
+                cujdBuffer,
+                sizeCujd,
+                IntPtr.Zero,
+                0,
+                out bytesReturnedCount,
+                IntPtr.Zero);
+
+            Marshal.FreeHGlobal(cujdBuffer);
+
+            return isSuccess;
+        }
+
+        public List<UsnEntry> GetEntries()
+        {
+            var result = new List<UsnEntry>();
+
+            UsnErrorCode usnErrorCode = this.QueryUSNJournal();
+
+            if (usnErrorCode == UsnErrorCode.SUCCESS)
+            {
+                MFT_ENUM_DATA mftEnumData = new MFT_ENUM_DATA();
+                mftEnumData.StartFileReferenceNumber = 0;
+                mftEnumData.LowUsn = 0;
+                mftEnumData.HighUsn = this.ntfsUsnJournalData.NextUsn;
+
+                int sizeMftEnumData = Marshal.SizeOf(mftEnumData);
+
+                IntPtr ptrMftEnumData = GetHeapGlobalPtr(sizeMftEnumData);
+
+                Marshal.StructureToPtr(mftEnumData, ptrMftEnumData, true);
+
+                int ptrDataSize = sizeof(UInt64) + 10000;
+
+                IntPtr ptrData = GetHeapGlobalPtr(ptrDataSize);
+
+                uint outBytesCount;
+
+                while (false != Win32Api.DeviceIoControl(
+                    this.DriveRootHandle,
+                    UsnControlCode.FSCTL_ENUM_USN_DATA,
+                    ptrMftEnumData,
+                    sizeMftEnumData,
+                    ptrData,
+                    ptrDataSize,
+                    out outBytesCount,
+                    IntPtr.Zero))
+                {
+                    // ptrData includes following struct:
+                    //typedef struct
+                    //{
+                    //    USN             LastFileReferenceNumber;
+                    //    USN_RECORD_V2   Record[1];
+                    //} *PENUM_USN_DATA;
+
+                    IntPtr ptrUsnRecord = new IntPtr(ptrData.ToInt32() + sizeof(Int64));
+
+                    while (outBytesCount > 60)
+                    {
+                        var usnRecord = new USN_RECORD_V2(ptrUsnRecord);
+
+                        result.Add(new UsnEntry(usnRecord));
+
+                        ptrUsnRecord = new IntPtr(ptrUsnRecord.ToInt32() + usnRecord.RecordLength);
+
+                        outBytesCount -= usnRecord.RecordLength;
+                    }
+
+                    Marshal.WriteInt64(ptrMftEnumData, Marshal.ReadInt64(ptrData, 0));
+                }
+
+                Marshal.FreeHGlobal(ptrData);
+                Marshal.FreeHGlobal(ptrMftEnumData);
+            }
+
+            return result;
+        }
+
+        private static IntPtr GetHeapGlobalPtr(int size)
+        {
+            IntPtr buffer = Marshal.AllocHGlobal(size);
+            Win32Api.ZeroMemory(buffer, size);
+
+            return buffer;
+        }
+
+        private UsnErrorCode QueryUSNJournal()
+        {
+            int sizeUsnJournalData = Marshal.SizeOf(this.ntfsUsnJournalData);
+
+            USN_JOURNAL_DATA tempUsnJournalData;
+
+            uint bytesReturnedCount;
+
+            bool isSuccess = Win32Api.DeviceIoControl(
+                this.DriveRootHandle,
+                UsnControlCode.FSCTL_QUERY_USN_JOURNAL,
+                IntPtr.Zero,
+                0,
+                out tempUsnJournalData,
+                sizeUsnJournalData,
+                out bytesReturnedCount,
+                IntPtr.Zero);
+
+            this.ntfsUsnJournalData = tempUsnJournalData;
+
+            //if (isSuccess)
+            //{
+            //    return tempUsnJournalData;
+            //}
+            //else
+            //{
+            //int win32ErrorCode = Marshal.GetLastWin32Error();
+            //if (Enum.IsDefined(typeof(UsnErrorCode), win32ErrorCode))
+            //{
+            //    var usnErrorCode = (UsnErrorCode)win32ErrorCode;
+            //}
+
+            //    throw new IOException("Drive returned false for Query Usn Journal", new Win32Exception(win32ErrorCode));
+            //}
+
+            return (UsnErrorCode)Marshal.GetLastWin32Error();
+        }
+
+        private IntPtr GetRootHandle()
+        {
+            string volume = string.Format("\\\\.\\{0}:", this.DriveLetter);
+
+            var result = Win32Api.CreateFile(
+                volume,
+                Win32ApiConstant.GENERIC_READ,
+                Win32ApiConstant.FILE_SHARE_READ | Win32ApiConstant.FILE_SHARE_WRITE,
+                IntPtr.Zero,
+                Win32ApiConstant.OPEN_EXISTING,
+                0,
+                IntPtr.Zero);
+
+            if (result.ToInt32() == Win32ApiConstant.INVALID_HANDLE_VALUE)
+            {
+                throw new IOException("Drive returned invalid root handle", new Win32Exception(Marshal.GetLastWin32Error()));
+            }
+
+            return result;
+        }
+
+        public void Dispose()
+        {
+            if (this.DriveRootHandle != null && this.DriveRootHandle.ToInt32() != Win32ApiConstant.INVALID_HANDLE_VALUE)
+            {
+                Win32Api.CloseHandle(this.DriveRootHandle);
+            }
+        }
+    }
+}

+ 30 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/UsnOperation/UsnReasonCode.cs

@@ -0,0 +1,30 @@
+using System;
+
+namespace Y.FileQueryEngine.UsnOperation
+{
+    [Flags]
+    internal enum UsnReasonCode : uint
+    {
+        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_CLOSE                 = 0x80000000
+    }
+}

+ 29 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Constants/Win32ApiConstant.cs

@@ -0,0 +1,29 @@
+using System;
+
+namespace Y.FileQueryEngine.Win32.Constants
+{
+    internal sealed class Win32ApiConstant
+    {
+        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 CREATE_NEW = 1;
+        public const UInt32 CREATE_ALWAYS = 2;
+        public const UInt32 OPEN_EXISTING = 3;
+        public const UInt32 OPEN_ALWAYS = 4;
+        public const UInt32 TRUNCATE_EXISTING = 5;
+
+        public const UInt32 FILE_ATTRIBUTE_NORMAL = 0x80;
+        public const UInt32 FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
+        public const Int32 INVALID_HANDLE_VALUE = -1;
+
+        public static Int32 GWL_EXSTYLE = -20;
+        public static Int32 WS_EX_LAYERED = 0x00080000;
+        public static Int32 WS_EX_TRANSPARENT = 0x00000020;
+
+        public const UInt32 FSCTL_GET_OBJECT_ID = 0x9009c;
+    }
+}

+ 26 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/BY_HANDLE_FILE_INFORMATION.cs

@@ -0,0 +1,26 @@
+using System.Runtime.InteropServices;
+using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
+
+namespace Y.FileQueryEngine.Win32.Structures
+{
+    /// <summary>
+    /// By Handle File Information structure, contains File Attributes(32bits), Creation Time(FILETIME),
+    /// Last Access Time(FILETIME), Last Write Time(FILETIME), Volume Serial Number(32bits),
+    /// File Size High(32bits), File Size Low(32bits), Number of Links(32bits), File Index High(32bits),
+    /// File Index Low(32bits).
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    internal 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;
+    }
+}

+ 15 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/CREATE_USN_JOURNAL_DATA.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Y.FileQueryEngine.Win32.Structures
+{
+    /// <summary>
+    /// Create USN Journal Data structure, contains Maximum Size(64bits) and Allocation Delta(64(bits).
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    internal struct CREATE_USN_JOURNAL_DATA
+    {
+        public UInt64 MaximumSize;
+        public UInt64 AllocationDelta;
+    }
+}

+ 17 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/MFT_ENUM_DATA.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Y.FileQueryEngine.Win32.Structures
+{
+    /// <summary>
+    /// MFT Enum Data structure, contains Start File Reference Number(64bits), Low USN(64bits),
+    /// High USN(64bits).
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    internal struct MFT_ENUM_DATA
+    {
+        public UInt64 StartFileReferenceNumber;
+        public Int64 LowUsn;
+        public Int64 HighUsn;
+    }
+}

+ 17 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/POINT.cs

@@ -0,0 +1,17 @@
+using System.Runtime.InteropServices;
+
+namespace Y.FileQueryEngine.Win32.Structures
+{
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct POINT
+    {
+        public int X;
+        public int Y;
+
+        public POINT(int x, int y)
+        {
+            this.X = x;
+            this.Y = y;
+        }
+    }
+}

+ 20 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/READ_USN_JOURNAL_DATA.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Y.FileQueryEngine.Win32.Structures
+{
+    /// <summary>
+    /// Contains the Start USN(64bits), Reason Mask(32bits), Return Only on Close flag(32bits),
+    /// Time Out(64bits), Bytes To Wait For(64bits), and USN Journal ID(64bits).
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    internal struct READ_USN_JOURNAL_DATA
+    {
+        public Int64 StartUsn;
+        public UInt32 ReasonMask;
+        public UInt32 ReturnOnlyOnClose;
+        public UInt64 Timeout;
+        public UInt64 bytesToWaitFor;
+        public UInt64 UsnJournalId;
+    }
+}

+ 21 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/USN_JOURNAL_DATA.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Y.FileQueryEngine.Win32.Structures
+{
+    /// <summary>
+    /// USN Journal Data structure, contains USN Journal ID(64bits), First USN(64bits), Next USN(64bits),
+    /// Lowest Valid USN(64bits), Max USN(64bits), Maximum Size(64bits) and Allocation Delta(64bits).
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    internal 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;
+    }
+}

+ 48 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Structures/USN_RECORD_V2.cs

@@ -0,0 +1,48 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Y.FileQueryEngine.Win32.Structures
+{
+    /// <summary>
+    /// Contains the USN Record Length(32bits), USN(64bits), File Reference Number(64bits), 
+    /// Parent File Reference Number(64bits), Reason Code(32bits), File Attributes(32bits),
+    /// File Name Length(32bits), the File Name Offset(32bits) and the File Name.
+    /// </summary>
+    public class USN_RECORD_V2
+    {
+        private const int FR_OFFSET = 8;
+        private const int PFR_OFFSET = 16;
+        private const int USN_OFFSET = 24;
+        private const int REASON_OFFSET = 40;
+        private const int FA_OFFSET = 52;
+        private const int FNL_OFFSET = 56;
+        private const int FN_OFFSET = 58;
+
+        public UInt32 RecordLength { get; private set; }
+        public UInt64 FileReferenceNumber { get; private set; }
+        public UInt64 ParentFileReferenceNumber { get; private set; }
+        public Int64 Usn { get; private set; }
+        public UInt32 Reason { get; private set; }
+        public UInt32 FileAttributes { get; private set; }
+        public Int32 FileNameLength { get; private set; }
+        public Int32 FileNameOffset { get; private set; }
+        public string FileName { get; private set; }
+
+        /// <summary>
+        /// USN Record Constructor
+        /// </summary>
+        /// <param name="usnRecordPtr">Buffer of bytes representing the USN Record</param>
+        public USN_RECORD_V2(IntPtr usnRecordPtr)
+        {
+            this.RecordLength = (UInt32)Marshal.ReadInt32(usnRecordPtr);
+            this.FileReferenceNumber = (UInt64)Marshal.ReadInt64(usnRecordPtr, FR_OFFSET);
+            this.ParentFileReferenceNumber = (UInt64)Marshal.ReadInt64(usnRecordPtr, PFR_OFFSET);
+            this.Usn = Marshal.ReadInt64(usnRecordPtr, USN_OFFSET);
+            this.Reason = (UInt32)Marshal.ReadInt32(usnRecordPtr, REASON_OFFSET);
+            this.FileAttributes = (UInt32)Marshal.ReadInt32(usnRecordPtr, FA_OFFSET);
+            this.FileNameLength = Marshal.ReadInt16(usnRecordPtr, FNL_OFFSET);
+            this.FileNameOffset = Marshal.ReadInt16(usnRecordPtr, FN_OFFSET);
+            this.FileName = Marshal.PtrToStringUni(new IntPtr(usnRecordPtr.ToInt32() + this.FileNameOffset), this.FileNameLength / sizeof(char));
+        }
+    }
+}

+ 556 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Win32/Win32Api.cs

@@ -0,0 +1,556 @@
+using System;
+using System.Text;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.ComponentModel;
+using Y.FileQueryEngine.Win32.Constants;
+using Y.FileQueryEngine.Win32.Structures;
+
+namespace Y.FileQueryEngine.Win32
+{
+    internal class Win32Api
+    {
+        private const string KERNEL32DLL = "kernel32.dll";
+
+        private const string USER32DLL = "user32.dll";
+
+        #region dll imports
+
+        /// <summary>
+        /// Creates the file specified by 'lpFileName' with desired access, share mode, security attributes,
+        /// creation disposition, flags and attributes.
+        /// </summary>
+        /// <param name="lpFileName">Fully qualified path to a file</param>
+        /// <param name="dwDesiredAccess">Requested access (write, read, read/write, none)</param>
+        /// <param name="dwShareMode">Share mode (read, write, read/write, delete, all, none)</param>
+        /// <param name="lpSecurityAttributes">IntPtr to a 'SECURITY_ATTRIBUTES' structure</param>
+        /// <param name="dwCreationDisposition">Action to take on file or device specified by 'lpFileName' (CREATE_NEW,
+        /// CREATE_ALWAYS, OPEN_ALWAYS, OPEN_EXISTING, TRUNCATE_EXISTING)</param>
+        /// <param name="dwFlagsAndAttributes">File or device attributes and flags (typically FILE_ATTRIBUTE_NORMAL)</param>
+        /// <param name="hTemplateFile">IntPtr to a valid handle to a template file with 'GENERIC_READ' access right</param>
+        /// <returns>IntPtr handle to the 'lpFileName' file or device or 'INVALID_HANDLE_VALUE'</returns>
+        [DllImport(KERNEL32DLL, SetLastError = true)]
+        public static extern IntPtr CreateFile(string lpFileName,
+            uint dwDesiredAccess,
+            uint dwShareMode,
+            IntPtr lpSecurityAttributes,
+            uint dwCreationDisposition,
+            uint dwFlagsAndAttributes,
+            IntPtr hTemplateFile);
+
+        /// <summary>
+        /// Closes the file specified by the IntPtr 'hObject'.
+        /// </summary>
+        /// <param name="hObject">IntPtr handle to a file</param>
+        /// <returns>'true' if successful, otherwise 'false'</returns>
+        [DllImport(KERNEL32DLL, SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool CloseHandle(
+            IntPtr hObject);
+
+        /// <summary>
+        /// Fills the 'BY_HANDLE_FILE_INFORMATION' structure for the file specified by 'hFile'.
+        /// </summary>
+        /// <param name="hFile">Fully qualified name of a file</param>
+        /// <param name="lpFileInformation">Out BY_HANDLE_FILE_INFORMATION argument</param>
+        /// <returns>'true' if successful, otherwise 'false'</returns>
+        [DllImport(KERNEL32DLL, SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool GetFileInformationByHandle(
+            IntPtr hFile,
+            out BY_HANDLE_FILE_INFORMATION lpFileInformation);
+
+        /// <summary>
+        /// Deletes the file specified by 'fileName'.
+        /// </summary>
+        /// <param name="fileName">Fully qualified path to the file to delete</param>
+        /// <returns>'true' if successful, otherwise 'false'</returns>
+        [DllImport(KERNEL32DLL, SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool DeleteFile(
+            string fileName);
+
+        /// <summary>
+        /// Read data from the file specified by 'hFile'.
+        /// </summary>
+        /// <param name="hFile">IntPtr handle to the file to read</param>
+        /// <param name="lpBuffer">IntPtr to a buffer of bytes to receive the bytes read from 'hFile'</param>
+        /// <param name="nNumberOfBytesToRead">Number of bytes to read from 'hFile'</param>
+        /// <param name="lpNumberOfBytesRead">Number of bytes read from 'hFile'</param>
+        /// <param name="lpOverlapped">IntPtr to an 'OVERLAPPED' structure</param>
+        /// <returns>'true' if successful, otherwise 'false'</returns>
+        [DllImport(KERNEL32DLL)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool ReadFile(
+            IntPtr hFile,
+            IntPtr lpBuffer,
+            uint nNumberOfBytesToRead,
+            out uint lpNumberOfBytesRead,
+            IntPtr lpOverlapped);
+
+        /// <summary>
+        /// Writes the 
+        /// </summary>
+        /// <param name="hFile">IntPtr handle to the file to write</param>
+        /// <param name="bytes">IntPtr to a buffer of bytes to write to 'hFile'</param>
+        /// <param name="nNumberOfBytesToWrite">Number of bytes in 'lpBuffer' to write to 'hFile'</param>
+        /// <param name="lpNumberOfBytesWritten">Number of bytes written to 'hFile'</param>
+        /// <param name="overlapped">IntPtr to an 'OVERLAPPED' structure</param>
+        /// <returns>'true' if successful, otherwise 'false'</returns>
+        [DllImport(KERNEL32DLL, SetLastError = true, CharSet = CharSet.Unicode)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool WriteFile(
+            IntPtr hFile,
+            IntPtr bytes,
+            uint nNumberOfBytesToWrite,
+            out uint lpNumberOfBytesWritten,
+            int overlapped);
+
+        /// <summary>
+        /// Writes the data in 'lpBuffer' to the file specified by 'hFile'.
+        /// </summary>
+        /// <param name="hFile">IntPtr handle to file to write</param>
+        /// <param name="lpBuffer">Buffer of bytes to write to file 'hFile'</param>
+        /// <param name="nNumberOfBytesToWrite">Number of bytes in 'lpBuffer' to write to 'hFile'</param>
+        /// <param name="lpNumberOfBytesWritten">Number of bytes written to 'hFile'</param>
+        /// <param name="overlapped">IntPtr to an 'OVERLAPPED' structure</param>
+        /// <returns>'true' if successful, otherwise 'false'</returns>
+        [DllImport(KERNEL32DLL, SetLastError = true, CharSet = CharSet.Unicode)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool WriteFile(
+            IntPtr hFile,
+            byte[] lpBuffer,
+            uint nNumberOfBytesToWrite,
+            out uint lpNumberOfBytesWritten,
+            int overlapped);
+
+        /// <summary>
+        /// Sends the 'dwIoControlCode' to the device specified by 'hDevice'.
+        /// </summary>
+        /// <param name="hDevice">IntPtr handle to the device to receive 'dwIoControlCode'</param>
+        /// <param name="dwIoControlCode">Device IO Control Code to send</param>
+        /// <param name="lpInBuffer">Input buffer if required</param>
+        /// <param name="nInBufferSize">Size of input buffer</param>
+        /// <param name="lpOutBuffer">Output buffer if required</param>
+        /// <param name="nOutBufferSize">Size of output buffer</param>
+        /// <param name="lpBytesReturned">Number of bytes returned in output buffer</param>
+        /// <param name="lpOverlapped">IntPtr to an 'OVERLAPPED' structure</param>
+        /// <returns>'true' if successful, otherwise 'false'</returns>
+        [DllImport(KERNEL32DLL, 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);
+
+        /// <summary>
+        /// Sends the control code 'dwIoControlCode' to the device driver specified by 'hDevice'.
+        /// </summary>
+        /// <param name="hDevice">IntPtr handle to the device to receive 'dwIoControlCode</param>
+        /// <param name="dwIoControlCode">Device IO Control Code to send</param>
+        /// <param name="lpInBuffer">Input buffer if required</param>
+        /// <param name="nInBufferSize">Size of input buffer </param>
+        /// <param name="lpOutBuffer">Output buffer if required</param>
+        /// <param name="nOutBufferSize">Size of output buffer</param>
+        /// <param name="lpBytesReturned">Number of bytes returned</param>
+        /// <param name="lpOverlapped">Pointer to an 'OVERLAPPED' struture</param>
+        /// <returns></returns>
+        [DllImport(KERNEL32DLL, 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);
+
+        /// <summary>
+        /// Sets the number of bytes specified by 'size' of the memory associated with the argument 'ptr' 
+        /// to zero.
+        /// </summary>
+        /// <param name="ptr"></param>
+        /// <param name="size"></param>
+        [DllImport(KERNEL32DLL)]
+        public static extern void ZeroMemory(IntPtr ptr, int size);
+
+        [DllImport(USER32DLL, CharSet = CharSet.Auto)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool GetCursorPos(out POINT pt);
+
+        [DllImport(USER32DLL, CharSet = CharSet.Auto)]
+        public static extern Int32 GetWindowLong(IntPtr hWnd, Int32 nIndex);
+
+        [DllImport(USER32DLL, CharSet = CharSet.Auto)]
+        public static extern Int32 SetWindowLong(IntPtr hWnd, Int32 nIndex, Int32 newVal);
+
+        #endregion
+
+        #region functions
+
+        /// <summary>
+        /// Writes the data in 'text' to the alternate stream ':Description' of the file 'currentFile.
+        /// </summary>
+        /// <param name="currentfile">Fully qualified path to a file</param>
+        /// <param name="text">Data to write to the ':Description' stream</param>
+        public static void WriteAlternateStream(string currentfile, string text)
+        {
+            string AltStreamDesc = currentfile + ":Description";
+            IntPtr txtBuffer = IntPtr.Zero;
+            IntPtr hFile = IntPtr.Zero;
+            DeleteFile(AltStreamDesc);
+            string descText = text.TrimEnd(' ');
+
+            try
+            {
+                hFile = CreateFile(AltStreamDesc, Win32ApiConstant.GENERIC_WRITE, 0, IntPtr.Zero,
+                                       Win32ApiConstant.CREATE_ALWAYS, 0, IntPtr.Zero);
+                if (-1 != hFile.ToInt32())
+                {
+                    txtBuffer = Marshal.StringToHGlobalUni(descText);
+                    uint nBytes, count;
+                    nBytes = (uint)descText.Length;
+                    bool bRtn = WriteFile(hFile, txtBuffer, sizeof(char) * nBytes, out count, 0);
+                    if (!bRtn)
+                    {
+                        if ((sizeof(char) * nBytes) != count)
+                        {
+                            throw new Exception(string.Format("Bytes written {0} should be {1} for file {2}.",
+                                count, sizeof(char) * nBytes, AltStreamDesc));
+                        }
+                        else
+                        {
+                            throw new Exception("WriteFile() returned false");
+                        }
+                    }
+                }
+                else
+                {
+                    throw new Win32Exception(Marshal.GetLastWin32Error());
+                }
+            }
+            catch (Exception exception)
+            {
+                //string msg = string.Format("Exception caught in WriteAlternateStream()\n  '{0}'\n  for file '{1}'.",
+                //    exception.Message, AltStreamDesc);
+                //Console.WriiteLine(msg);
+                throw;
+            }
+            finally
+            {
+                CloseHandle(hFile);
+                hFile = IntPtr.Zero;
+                Marshal.FreeHGlobal(txtBuffer);
+                GC.Collect();
+            }
+        }
+
+        /// <summary>
+        /// Adds the ':Description' alternate stream name to the argument 'currentFile'.
+        /// </summary>
+        /// <param name="currentfile">The file whose alternate stream is to be read</param>
+        /// <returns>A string value representing the value of the alternate stream</returns>
+        public static string ReadAlternateStream(string currentfile)
+        {
+            string AltStreamDesc = currentfile + ":Description";
+            string returnstring = ReadAlternateStreamEx(AltStreamDesc);
+            return returnstring;
+        }
+
+        /// <summary>
+        /// Reads the stream represented by 'currentFile'.
+        /// </summary>
+        /// <param name="currentfile">Fully qualified path including stream</param>
+        /// <returns>Value of the alternate stream as a string</returns>
+        public static string ReadAlternateStreamEx(string currentfile)
+        {
+            string returnstring = string.Empty;
+            IntPtr hFile = IntPtr.Zero;
+            IntPtr buffer = IntPtr.Zero;
+            try
+            {
+                hFile = CreateFile(currentfile, Win32ApiConstant.GENERIC_READ, 0, IntPtr.Zero, Win32ApiConstant.OPEN_EXISTING, 0, IntPtr.Zero);
+                if (-1 != hFile.ToInt32())
+                {
+                    buffer = Marshal.AllocHGlobal(1000 * sizeof(char));
+                    ZeroMemory(buffer, 1000 * sizeof(char));
+                    uint nBytes;
+                    bool bRtn = ReadFile(hFile, buffer, 1000 * sizeof(char), out nBytes, IntPtr.Zero);
+                    if (bRtn)
+                    {
+                        if (nBytes > 0)
+                        {
+                            returnstring = Marshal.PtrToStringAuto(buffer);
+                            //byte[] byteBuffer = new byte[nBytes];
+                            //for (int i = 0; i < nBytes; i++)
+                            //{
+                            //    byteBuffer[i] = Marshal.ReadByte(buffer, i);
+                            //}
+                            //returnstring = Encoding.Unicode.GetString(byteBuffer, 0, (int)nBytes);
+                        }
+                        else
+                        {
+                            throw new Exception("ReadFile() returned true but read zero bytes");
+                        }
+                    }
+                    else
+                    {
+                        if (nBytes <= 0)
+                        {
+                            throw new Exception("ReadFile() read zero bytes.");
+                        }
+                        else
+                        {
+                            throw new Exception("ReadFile() returned false");
+                        }
+                    }
+                }
+                else
+                {
+                    Exception excptn = new Win32Exception(Marshal.GetLastWin32Error());
+                    if (!excptn.Message.Contains("cannot find the file"))
+                    {
+                        throw excptn;
+                    }
+                }
+            }
+            catch (Exception exception)
+            {
+                //string msg = string.Format("Exception caught in ReadAlternateStream(), '{0}'\n  for file '{1}'.",
+                //    exception.Message, currentfile);
+                //Console.WriteLine(msg);
+                //Console.WriteLine(exception.Message);
+                throw;
+            }
+            finally
+            {
+                CloseHandle(hFile);
+                hFile = IntPtr.Zero;
+                if (buffer != IntPtr.Zero)
+                {
+                    Marshal.FreeHGlobal(buffer);
+                }
+                GC.Collect();
+            }
+            return returnstring;
+        }
+
+        /// <summary>
+        /// Read the encrypted alternate stream specified by 'currentFile'.
+        /// </summary>
+        /// <param name="currentfile">Fully qualified path to encrypted alternate stream</param>
+        /// <returns>The un-encrypted value of the alternate stream as a string</returns>
+        public static string ReadAlternateStreamEncrypted(string currentfile)
+        {
+            string returnstring = string.Empty;
+            IntPtr buffer = IntPtr.Zero;
+            IntPtr hFile = IntPtr.Zero;
+            try
+            {
+                hFile = CreateFile(currentfile, Win32ApiConstant.GENERIC_READ, 0, IntPtr.Zero, Win32ApiConstant.OPEN_EXISTING, 0, IntPtr.Zero);
+                if (-1 != hFile.ToInt32())
+                {
+                    buffer = Marshal.AllocHGlobal(1000 * sizeof(char));
+                    ZeroMemory(buffer, 1000 * sizeof(char));
+                    uint nBytes;
+                    bool bRtn = ReadFile(hFile, buffer, 1000 * sizeof(char), out nBytes, IntPtr.Zero);
+                    if (0 != nBytes)
+                    {
+                        returnstring = DecryptLicenseString(buffer, nBytes);
+                    }
+                }
+                else
+                {
+                    Exception excptn = new Win32Exception(Marshal.GetLastWin32Error());
+                    if (!excptn.Message.Contains("cannot find the file"))
+                    {
+                        throw excptn;
+                    }
+                }
+            }
+            catch (Exception exception)
+            {
+                Console.WriteLine("Exception caught in ReadAlternateStreamEncrypted()");
+                Console.WriteLine(exception.Message);
+            }
+            finally
+            {
+                CloseHandle(hFile);
+                hFile = IntPtr.Zero;
+                if (buffer != IntPtr.Zero)
+                {
+                    Marshal.FreeHGlobal(buffer);
+                }
+                GC.Collect();
+            }
+            return returnstring;
+        }
+
+        /// <summary>
+        /// Writes the value of 'LicenseString' as an encrypted stream to the file:stream specified
+        /// by 'currentFile'.
+        /// </summary>
+        /// <param name="currentFile">Fully qualified path to the alternate stream</param>
+        /// <param name="LicenseString">The string value to encrypt and write to the alternate stream</param>
+        public static void WriteAlternateStreamEncrypted(string currentFile, string LicenseString)
+        {
+            RC2CryptoServiceProvider rc2 = null;
+            CryptoStream cs = null;
+            MemoryStream ms = null;
+            uint count = 0;
+            IntPtr buffer = IntPtr.Zero;
+            IntPtr hFile = IntPtr.Zero;
+            try
+            {
+                Encoding enc = Encoding.Unicode;
+
+                byte[] ba = enc.GetBytes(LicenseString);
+                ms = new MemoryStream();
+
+                rc2 = new RC2CryptoServiceProvider();
+                rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0");
+                rc2.IV = GetBytesFromHexString("827d961224d99b2d");
+
+                cs = new CryptoStream(ms, rc2.CreateEncryptor(), CryptoStreamMode.Write);
+                cs.Write(ba, 0, ba.Length);
+                cs.FlushFinalBlock();
+
+                buffer = Marshal.AllocHGlobal(1000 * sizeof(char));
+                ZeroMemory(buffer, 1000 * sizeof(char));
+                uint nBytes = (uint)ms.Length;
+                Marshal.Copy(ms.GetBuffer(), 0, buffer, (int)nBytes);
+
+                DeleteFile(currentFile);
+                hFile = CreateFile(currentFile, Win32ApiConstant.GENERIC_WRITE, 0, IntPtr.Zero,
+                                       Win32ApiConstant.CREATE_ALWAYS, 0, IntPtr.Zero);
+                if (-1 != hFile.ToInt32())
+                {
+                    bool bRtn = WriteFile(hFile, buffer, nBytes, out count, 0);
+                }
+                else
+                {
+                    Exception excptn = new Win32Exception(Marshal.GetLastWin32Error());
+                    if (!excptn.Message.Contains("cannot find the file"))
+                    {
+                        throw excptn;
+                    }
+                }
+            }
+            catch (Exception exception)
+            {
+                Console.WriteLine("WriteAlternateStreamEncrypted()");
+                Console.WriteLine(exception.Message);
+            }
+            finally
+            {
+                CloseHandle(hFile);
+                hFile = IntPtr.Zero;
+                if (cs != null)
+                {
+                    cs.Close();
+                    cs.Dispose();
+                }
+
+                rc2 = null;
+                if (ms != null)
+                {
+                    ms.Close();
+                    ms.Dispose();
+                }
+                if (buffer != IntPtr.Zero)
+                {
+                    Marshal.FreeHGlobal(buffer);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Encrypt the string 'LicenseString' argument and return as a MemoryStream.
+        /// </summary>
+        /// <param name="LicenseString">The string value to encrypt</param>
+        /// <returns>A MemoryStream which contains the encrypted value of 'LicenseString'</returns>
+        private static MemoryStream EncryptLicenseString(string LicenseString)
+        {
+            Encoding enc = Encoding.Unicode;
+
+            byte[] ba = enc.GetBytes(LicenseString);
+            MemoryStream ms = new MemoryStream();
+
+            RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
+            rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0");
+            rc2.IV = GetBytesFromHexString("827d961224d99b2d");
+
+            CryptoStream cs = new CryptoStream(ms, rc2.CreateEncryptor(), CryptoStreamMode.Write);
+            cs.Write(ba, 0, ba.Length);
+
+            cs.Close();
+            cs.Dispose();
+            rc2 = null;
+            return ms;
+        }
+
+        /// <summary>
+        /// Given an IntPtr to a bufer and the number of bytes, decrypt the buffer and return an 
+        /// unencrypted text string.
+        /// </summary>
+        /// <param name="buffer">An IntPtr to the 'buffer' containing the encrypted string</param>
+        /// <param name="nBytes">The number of bytes in 'buffer' to decrypt</param>
+        /// <returns></returns>
+        private static string DecryptLicenseString(IntPtr buffer, uint nBytes)
+        {
+            byte[] ba = new byte[nBytes];
+            for (int i = 0; i < nBytes; i++)
+            {
+                ba[i] = Marshal.ReadByte(buffer, i);
+            }
+            MemoryStream ms = new MemoryStream(ba);
+
+            RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
+            rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0");
+            rc2.IV = GetBytesFromHexString("827d961224d99b2d");
+
+            CryptoStream cs = new CryptoStream(ms, rc2.CreateDecryptor(), CryptoStreamMode.Read);
+            string licenseString = string.Empty;
+            byte[] ba1 = new byte[4096];
+            int irtn = cs.Read(ba1, 0, 4096);
+            Encoding enc = Encoding.Unicode;
+            licenseString = enc.GetString(ba1, 0, irtn);
+
+            cs.Close();
+            cs.Dispose();
+            ms.Close();
+            ms.Dispose();
+            rc2 = null;
+            return licenseString;
+        }
+
+        /// <summary>
+        /// Gets the byte array generated from the value of 'hexString'.
+        /// </summary>
+        /// <param name="hexString">Hexadecimal string</param>
+        /// <returns>Array of bytes generated from 'hexString'.</returns>
+        public static byte[] GetBytesFromHexString(string hexString)
+        {
+            int numHexChars = hexString.Length / 2;
+            byte[] ba = new byte[numHexChars];
+            int j = 0;
+            for (int i = 0; i < ba.Length; i++)
+            {
+                string hex = new string(new char[] { hexString[j], hexString[j + 1] });
+                ba[i] = byte.Parse(hex, System.Globalization.NumberStyles.HexNumber);
+                j = j + 2;
+            }
+            return ba;
+        }
+
+        #endregion
+    }
+}

+ 72 - 0
Fork.Net/Fork.Net.SpeciallyTools/Y.FileQueryEngine/Y.FileQueryEngine.csproj

@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{497F570C-8398-458D-970C-DFA3DD9FE746}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Y.FileQueryEngine</RootNamespace>
+    <AssemblyName>Y.FileQueryEngine</AssemblyName>
+    <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Net.Http" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="QueryEngine\FileQueryEngine.cs" />
+    <Compile Include="QueryEngine\FileAndDirectoryEntry.cs" />
+    <Compile Include="QueryEngine\FrnFilePath.cs" />
+    <Compile Include="UsnOperation\UsnControlCode.cs" />
+    <Compile Include="UsnOperation\UsnEntry.cs" />
+    <Compile Include="UsnOperation\UsnErrorCode.cs" />
+    <Compile Include="UsnOperation\UsnJournalData.cs" />
+    <Compile Include="UsnOperation\UsnOperator.cs" />
+    <Compile Include="UsnOperation\UsnReasonCode.cs" />
+    <Compile Include="Win32\Constants\Win32ApiConstant.cs" />
+    <Compile Include="Win32\Structures\BY_HANDLE_FILE_INFORMATION.cs" />
+    <Compile Include="Win32\Structures\CREATE_USN_JOURNAL_DATA.cs" />
+    <Compile Include="Win32\Structures\MFT_ENUM_DATA.cs" />
+    <Compile Include="Win32\Structures\POINT.cs" />
+    <Compile Include="Win32\Structures\READ_USN_JOURNAL_DATA.cs" />
+    <Compile Include="Win32\Structures\USN_JOURNAL_DATA.cs" />
+    <Compile Include="Win32\Structures\USN_RECORD_V2.cs" />
+    <Compile Include="Win32\Win32Api.cs" />
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 13 - 0
Fork.Net/Fork.Net.sln

@@ -53,6 +53,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test.WpfApplication1", "Tes
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Y.Test", "Test\Y.Test\Y.Test.csproj", "{E1897235-0E04-420D-B6D5-29BEA14DA1FD}"
 EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Fork.Net.SpeciallyTools", "Fork.Net.SpeciallyTools", "{FA0F1046-E0E8-4057-B4B4-CD551844A29B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Y.FileQueryEngine", "Fork.Net.SpeciallyTools\Y.FileQueryEngine\Y.FileQueryEngine.csproj", "{497F570C-8398-458D-970C-DFA3DD9FE746}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -221,6 +225,14 @@ Global
 		{E1897235-0E04-420D-B6D5-29BEA14DA1FD}.Release|Any CPU.Build.0 = Release|Any CPU
 		{E1897235-0E04-420D-B6D5-29BEA14DA1FD}.Release|x86.ActiveCfg = Release|Any CPU
 		{E1897235-0E04-420D-B6D5-29BEA14DA1FD}.Release|x86.Build.0 = Release|Any CPU
+		{497F570C-8398-458D-970C-DFA3DD9FE746}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{497F570C-8398-458D-970C-DFA3DD9FE746}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{497F570C-8398-458D-970C-DFA3DD9FE746}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{497F570C-8398-458D-970C-DFA3DD9FE746}.Debug|x86.Build.0 = Debug|Any CPU
+		{497F570C-8398-458D-970C-DFA3DD9FE746}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{497F570C-8398-458D-970C-DFA3DD9FE746}.Release|Any CPU.Build.0 = Release|Any CPU
+		{497F570C-8398-458D-970C-DFA3DD9FE746}.Release|x86.ActiveCfg = Release|Any CPU
+		{497F570C-8398-458D-970C-DFA3DD9FE746}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -245,5 +257,6 @@ Global
 		{82B0FE94-1339-42C8-953F-E400CF9F1FF2} = {A89FC45A-A907-4487-8719-114530A62684}
 		{9B9BF25E-0ECD-4923-9546-4FDAEF685092} = {A89FC45A-A907-4487-8719-114530A62684}
 		{E1897235-0E04-420D-B6D5-29BEA14DA1FD} = {A89FC45A-A907-4487-8719-114530A62684}
+		{497F570C-8398-458D-970C-DFA3DD9FE746} = {FA0F1046-E0E8-4057-B4B4-CD551844A29B}
 	EndGlobalSection
 EndGlobal

+ 38 - 0
Fork.Net/Oreo.Plugins/Oreo.FileMan/Helpers/FileHelper.cs

@@ -6,6 +6,7 @@ using System.IO;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Y.FileQueryEngine.QueryEngine;
 using Y.Utils.DataUtils.Collections;
 using Y.Utils.IOUtils.FileUtils;
 using Y.Utils.IOUtils.PathUtils;
@@ -16,6 +17,43 @@ namespace Oreo.FileMan.Helpers
     {
         public static void GetAllFileToDb()
         {
+            var drives = FileQueryEngine.GetReadyNtfsDrives();
+            if (ListTool.HasElements(drives))
+            {
+                foreach (var drive in drives)
+                {
+                    var allFiles = FileQueryEngine.GetAllFiles(drive);
+                    if (ListTool.HasElements(allFiles))
+                    {
+                        using (var db = new Muse())
+                        {
+                            int addcount = 0;
+                            foreach (var file in allFiles)
+                            {
+                                if (!db.Set<Files>().Any(x => x.FullPath == file.FullFileName))
+                                {
+                                    var a = db.Set<Files>().Add(
+                                        new Files()
+                                        {
+                                            FullPath = file.FullFileName,
+                                            FileName = file.FileName,
+                                            ExtName = Path.GetExtension(file.FullFileName),
+                                            Size = FileTool.Size(file.FullFileName),
+                                        });
+                                    addcount++;
+                                }
+                                if (addcount >= 1000)
+                                {
+                                    addcount = 0;
+                                    db.SaveChanges();
+                                }
+                            }
+                            int count = db.SaveChanges();
+                        }
+                    }
+                }
+            }
+
             DriveInfo[] allDirves = DriveInfo.GetDrives();
             if (ListTool.HasElements(allDirves))
             {

+ 10 - 0
Fork.Net/Oreo.Plugins/Oreo.FileMan/Oreo.FileMan.csproj

@@ -38,6 +38,9 @@
   <PropertyGroup>
     <ApplicationIcon>Images\Icon\Icon.ico</ApplicationIcon>
   </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationManifest>Properties\app.manifest</ApplicationManifest>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
       <HintPath>..\..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll</HintPath>
@@ -135,6 +138,9 @@
     <EmbeddedResource Include="Views\MainForm.resx">
       <DependentUpon>MainForm.cs</DependentUpon>
     </EmbeddedResource>
+    <None Include="Properties\app.manifest">
+      <SubType>Designer</SubType>
+    </None>
     <None Include="packages.config" />
     <None Include="Properties\Settings.settings">
       <Generator>SettingsSingleFileGenerator</Generator>
@@ -153,6 +159,10 @@
     <Folder Include="Services\" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\Fork.Net.SpeciallyTools\Y.FileQueryEngine\Y.FileQueryEngine.csproj">
+      <Project>{497f570c-8398-458d-970c-dfa3dd9fe746}</Project>
+      <Name>Y.FileQueryEngine</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\Y.Skin\Y.Skin.csproj">
       <Project>{e9a97673-3e27-4a49-90bc-8806411a2f57}</Project>
       <Name>Y.Skin</Name>

+ 1 - 0
Fork.Net/Oreo.Plugins/Oreo.FileMan/Partial/FileTypePartial.cs

@@ -15,6 +15,7 @@ using Y.Utils.IOUtils.PathUtils;
 using Oreo.FileMan.Models;
 using Oreo.FileMan.DatabaseEngine;
 using Oreo.FileMan.Helpers;
+using Y.FileQueryEngine.QueryEngine;
 
 namespace Oreo.FileMan.Partial
 {

+ 75 - 0
Fork.Net/Oreo.Plugins/Oreo.FileMan/Properties/app.manifest

@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+    <security>
+      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+        <!-- UAC 清单选项
+             如果想要更改 Windows 用户帐户控制级别,请使用
+             以下节点之一替换 requestedExecutionLevel 节点。n
+        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
+        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
+        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />
+
+            指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
+            如果你的应用程序需要此虚拟化来实现向后兼容性,则删除此
+            元素。
+        -->
+        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
+           Windows 版本的列表。取消评论适当的元素,Windows 将
+           自动选择最兼容的环境。 -->
+
+      <!-- Windows Vista -->
+      <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
+
+      <!-- Windows 7 -->
+      <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
+
+      <!-- Windows 8 -->
+      <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
+
+      <!-- Windows 8.1 -->
+      <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
+
+      <!-- Windows 10 -->
+      <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
+
+    </application>
+  </compatibility>
+
+  <!-- 指示该应用程序可以感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
+       自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
+       选择加入。选择加入此设置的 Windows 窗体应用程序(目标设定为 .NET Framework 4.6 )还应
+       在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。-->
+  <!--
+  <application xmlns="urn:schemas-microsoft-com:asm.v3">
+    <windowsSettings>
+      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
+    </windowsSettings>
+  </application>
+  -->
+
+  <!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
+  <!--
+  <dependency>
+    <dependentAssembly>
+      <assemblyIdentity
+          type="win32"
+          name="Microsoft.Windows.Common-Controls"
+          version="6.0.0.0"
+          processorArchitecture="*"
+          publicKeyToken="6595b64144ccf1df"
+          language="*"
+        />
+    </dependentAssembly>
+  </dependency>
+  -->
+
+</assembly>