Advertisement
Guest User

NtfsUsnJournal c#

a guest
Aug 8th, 2016
480
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 76.27 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.IO;
  5. using System.Runtime.InteropServices;
  6. using System.Security.Cryptography;
  7. using System.Text;
  8.  
  9. public class NtfsUsnJournal : IDisposable
  10. {
  11.     #region enum(s)
  12.     public enum UsnJournalReturnCode
  13.     {
  14.         INVALID_HANDLE_VALUE = -1,
  15.         USN_JOURNAL_SUCCESS = 0,
  16.         ERROR_INVALID_FUNCTION = 1,
  17.         ERROR_FILE_NOT_FOUND = 2,
  18.         ERROR_PATH_NOT_FOUND = 3,
  19.         ERROR_TOO_MANY_OPEN_FILES = 4,
  20.         ERROR_ACCESS_DENIED = 5,
  21.         ERROR_INVALID_HANDLE = 6,
  22.         ERROR_INVALID_DATA = 13,
  23.         ERROR_HANDLE_EOF = 38,
  24.         ERROR_NOT_SUPPORTED = 50,
  25.         ERROR_INVALID_PARAMETER = 87,
  26.         ERROR_JOURNAL_DELETE_IN_PROGRESS = 1178,
  27.         USN_JOURNAL_NOT_ACTIVE = 1179,
  28.         ERROR_JOURNAL_ENTRY_DELETED = 1181,
  29.         ERROR_INVALID_USER_BUFFER = 1784,
  30.         USN_JOURNAL_INVALID = 17001,
  31.         VOLUME_NOT_NTFS = 17003,
  32.         INVALID_FILE_REFERENCE_NUMBER = 17004,
  33.         USN_JOURNAL_ERROR = 17005
  34.     }
  35.  
  36.     public enum UsnReasonCode
  37.     {
  38.         USN_REASON_DATA_OVERWRITE = 0x00000001,
  39.         USN_REASON_DATA_EXTEND = 0x00000002,
  40.         USN_REASON_DATA_TRUNCATION = 0x00000004,
  41.         USN_REASON_NAMED_DATA_OVERWRITE = 0x00000010,
  42.         USN_REASON_NAMED_DATA_EXTEND = 0x00000020,
  43.         USN_REASON_NAMED_DATA_TRUNCATION = 0x00000040,
  44.         USN_REASON_FILE_CREATE = 0x00000100,
  45.         USN_REASON_FILE_DELETE = 0x00000200,
  46.         USN_REASON_EA_CHANGE = 0x00000400,
  47.         USN_REASON_SECURITY_CHANGE = 0x00000800,
  48.         USN_REASON_RENAME_OLD_NAME = 0x00001000,
  49.         USN_REASON_RENAME_NEW_NAME = 0x00002000,
  50.         USN_REASON_INDEXABLE_CHANGE = 0x00004000,
  51.         USN_REASON_BASIC_INFO_CHANGE = 0x00008000,
  52.         USN_REASON_HARD_LINK_CHANGE = 0x00010000,
  53.         USN_REASON_COMPRESSION_CHANGE = 0x00020000,
  54.         USN_REASON_ENCRYPTION_CHANGE = 0x00040000,
  55.         USN_REASON_OBJECT_ID_CHANGE = 0x00080000,
  56.         USN_REASON_REPARSE_POINT_CHANGE = 0x00100000,
  57.         USN_REASON_STREAM_CHANGE = 0x00200000,
  58.         USN_REASON_CLOSE = -1
  59.     }
  60.  
  61.     #endregion
  62.  
  63.     #region private member variables
  64.  
  65.     private DriveInfo _driveInfo = null;
  66.     private uint _volumeSerialNumber;
  67.     private IntPtr _usnJournalRootHandle;
  68.  
  69.     private bool bNtfsVolume;
  70.  
  71.     #endregion
  72.  
  73.     #region properties
  74.  
  75.     private static TimeSpan _elapsedTime;
  76.     public static TimeSpan ElapsedTime
  77.     {
  78.         get { return _elapsedTime; }
  79.     }
  80.  
  81.     public string VolumeName
  82.     {
  83.         get { return _driveInfo.Name; }
  84.     }
  85.  
  86.     public long AvailableFreeSpace
  87.     {
  88.         get { return _driveInfo.AvailableFreeSpace; }
  89.     }
  90.  
  91.     public long TotalFreeSpace
  92.     {
  93.         get { return _driveInfo.TotalFreeSpace; }
  94.     }
  95.  
  96.     public string Format
  97.     {
  98.         get { return _driveInfo.DriveFormat; }
  99.     }
  100.  
  101.     public DirectoryInfo RootDirectory
  102.     {
  103.         get { return _driveInfo.RootDirectory; }
  104.     }
  105.  
  106.     public long TotalSize
  107.     {
  108.         get { return _driveInfo.TotalSize; }
  109.     }
  110.  
  111.     public string VolumeLabel
  112.     {
  113.         get { return _driveInfo.VolumeLabel; }
  114.     }
  115.  
  116.     public uint VolumeSerialNumber
  117.     {
  118.         get { return _volumeSerialNumber; }
  119.     }
  120.  
  121.     #endregion
  122.  
  123.     #region constructor(s)
  124.  
  125.     /// <summary>
  126.     /// Constructor for NtfsUsnJournal class.  If no exception is thrown, _usnJournalRootHandle and
  127.     /// _volumeSerialNumber can be assumed to be good. If an exception is thrown, the NtfsUsnJournal
  128.     /// object is not usable.
  129.     /// </summary>
  130.     /// <param name="driveInfo">DriveInfo object that provides access to information about a volume</param>
  131.     /// <remarks>
  132.     /// An exception thrown if the volume is not an 'NTFS' volume or
  133.     /// if GetRootHandle() or GetVolumeSerialNumber() functions fail.
  134.     /// Each public method checks to see if the volume is NTFS and if the _usnJournalRootHandle is
  135.     /// valid.  If these two conditions aren't met, then the public function will return a UsnJournalReturnCode
  136.     /// error.
  137.     /// </remarks>
  138.     public NtfsUsnJournal(DriveInfo driveInfo)
  139.     {
  140.         DateTime start = DateTime.Now;
  141.         _driveInfo = driveInfo;
  142.  
  143.         if (0 == string.Compare(_driveInfo.DriveFormat, "ntfs", true))
  144.         {
  145.             bNtfsVolume = true;
  146.  
  147.             IntPtr rootHandle = IntPtr.Zero;
  148.             UsnJournalReturnCode usnRtnCode = GetRootHandle(out rootHandle);
  149.  
  150.             if (usnRtnCode == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
  151.             {
  152.                 _usnJournalRootHandle = rootHandle;
  153.                 usnRtnCode = GetVolumeSerialNumber(_driveInfo, out _volumeSerialNumber);
  154.                 if (usnRtnCode != UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
  155.                 {
  156.                     _elapsedTime = DateTime.Now - start;
  157.                     throw new Win32Exception((int)usnRtnCode);
  158.                 }
  159.             }
  160.             else
  161.             {
  162.                 _elapsedTime = DateTime.Now - start;
  163.                 throw new Win32Exception((int)usnRtnCode);
  164.             }
  165.         }
  166.         else
  167.         {
  168.             _elapsedTime = DateTime.Now - start;
  169.             throw new Exception(string.Format("{0} is not an 'NTFS' volume.", _driveInfo.Name));
  170.         }
  171.         _elapsedTime = DateTime.Now - start;
  172.     }
  173.  
  174.     #endregion
  175.  
  176.     #region public methods
  177.  
  178.     /// <summary>
  179.     /// CreateUsnJournal() creates a usn journal on the volume. If a journal already exists this function
  180.     /// will adjust the MaximumSize and AllocationDelta parameters of the journal if the requested size
  181.     /// is larger.
  182.     /// </summary>
  183.     /// <param name="maxSize">maximum size requested for the UsnJournal</param>
  184.     /// <param name="allocationDelta">when space runs out, the amount of additional
  185.     /// space to allocate</param>
  186.     /// <param name="elapsedTime">The TimeSpan object indicating how much time this function
  187.     /// took</param>
  188.     /// <returns>a UsnJournalReturnCode
  189.     /// USN_JOURNAL_SUCCESS                 CreateUsnJournal() function succeeded.
  190.     /// VOLUME_NOT_NTFS                     volume is not an NTFS volume.
  191.     /// INVALID_HANDLE_VALUE                NtfsUsnJournal object failed initialization.
  192.     /// USN_JOURNAL_NOT_ACTIVE              usn journal is not active on volume.
  193.     /// ERROR_ACCESS_DENIED                 accessing the usn journal requires admin rights, see remarks.
  194.     /// ERROR_INVALID_FUNCTION              error generated by DeviceIoControl() call.
  195.     /// ERROR_FILE_NOT_FOUND                error generated by DeviceIoControl() call.
  196.     /// ERROR_PATH_NOT_FOUND                error generated by DeviceIoControl() call.
  197.     /// ERROR_TOO_MANY_OPEN_FILES           error generated by DeviceIoControl() call.
  198.     /// ERROR_INVALID_HANDLE                error generated by DeviceIoControl() call.
  199.     /// ERROR_INVALID_DATA                  error generated by DeviceIoControl() call.
  200.     /// ERROR_NOT_SUPPORTED                 error generated by DeviceIoControl() call.
  201.     /// ERROR_INVALID_PARAMETER             error generated by DeviceIoControl() call.
  202.     /// ERROR_JOURNAL_DELETE_IN_PROGRESS    usn journal delete is in progress.
  203.     /// ERROR_INVALID_USER_BUFFER           error generated by DeviceIoControl() call.
  204.     /// USN_JOURNAL_ERROR                   unspecified usn journal error.
  205.     /// </returns>
  206.     /// <remarks>
  207.     /// If function returns ERROR_ACCESS_DENIED you need to run application as an Administrator.
  208.     /// </remarks>
  209.     public UsnJournalReturnCode
  210.         CreateUsnJournal(ulong maxSize, ulong allocationDelta)
  211.     {
  212.         UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;
  213.         DateTime startTime = DateTime.Now;
  214.  
  215.         if (bNtfsVolume)
  216.         {
  217.             if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  218.             {
  219.                 usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  220.                 UInt32 cb;
  221.  
  222.                 CREATE_USN_JOURNAL_DATA cujd = new CREATE_USN_JOURNAL_DATA();
  223.                 cujd.MaximumSize = maxSize;
  224.                 cujd.AllocationDelta = allocationDelta;
  225.  
  226.                 int sizeCujd = Marshal.SizeOf(cujd);
  227.                 IntPtr cujdBuffer = Marshal.AllocHGlobal(sizeCujd);
  228.                 ZeroMemory(cujdBuffer, sizeCujd);
  229.                 Marshal.StructureToPtr(cujd, cujdBuffer, true);
  230.  
  231.                 bool fOk = DeviceIoControl(
  232.                     _usnJournalRootHandle,
  233.                     FSCTL_CREATE_USN_JOURNAL,
  234.                     cujdBuffer,
  235.                     sizeCujd,
  236.                     IntPtr.Zero,
  237.                     0,
  238.                     out cb,
  239.                     IntPtr.Zero);
  240.                 if (!fOk)
  241.                 {
  242.                     usnRtnCode = ConvertWin32ErrorToUsnError((GetLastErrorEnum)Marshal.GetLastWin32Error());
  243.                 }
  244.                 Marshal.FreeHGlobal(cujdBuffer);
  245.             }
  246.             else
  247.             {
  248.                 usnRtnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
  249.             }
  250.         }
  251.  
  252.         _elapsedTime = DateTime.Now - startTime;
  253.         return usnRtnCode;
  254.     }
  255.  
  256.     /// <summary>
  257.     /// DeleteUsnJournal() deletes a usn journal on the volume. If no usn journal exists, this
  258.     /// function simply returns success.
  259.     /// </summary>
  260.     /// <param name="journalState">USN_JOURNAL_DATA object for this volume</param>
  261.     /// <param name="elapsedTime">The TimeSpan object indicating how much time this function
  262.     /// took</param>
  263.     /// <returns>a UsnJournalReturnCode
  264.     /// USN_JOURNAL_SUCCESS                 DeleteUsnJournal() function succeeded.
  265.     /// VOLUME_NOT_NTFS                     volume is not an NTFS volume.
  266.     /// INVALID_HANDLE_VALUE                NtfsUsnJournal object failed initialization.
  267.     /// USN_JOURNAL_NOT_ACTIVE              usn journal is not active on volume.
  268.     /// ERROR_ACCESS_DENIED                 accessing the usn journal requires admin rights, see remarks.
  269.     /// ERROR_INVALID_FUNCTION              error generated by DeviceIoControl() call.
  270.     /// ERROR_FILE_NOT_FOUND                error generated by DeviceIoControl() call.
  271.     /// ERROR_PATH_NOT_FOUND                error generated by DeviceIoControl() call.
  272.     /// ERROR_TOO_MANY_OPEN_FILES           error generated by DeviceIoControl() call.
  273.     /// ERROR_INVALID_HANDLE                error generated by DeviceIoControl() call.
  274.     /// ERROR_INVALID_DATA                  error generated by DeviceIoControl() call.
  275.     /// ERROR_NOT_SUPPORTED                 error generated by DeviceIoControl() call.
  276.     /// ERROR_INVALID_PARAMETER             error generated by DeviceIoControl() call.
  277.     /// ERROR_JOURNAL_DELETE_IN_PROGRESS    usn journal delete is in progress.
  278.     /// ERROR_INVALID_USER_BUFFER           error generated by DeviceIoControl() call.
  279.     /// USN_JOURNAL_ERROR                   unspecified usn journal error.
  280.     /// </returns>
  281.     /// <remarks>
  282.     /// If function returns ERROR_ACCESS_DENIED you need to run application as an Administrator.
  283.     /// </remarks>
  284.     public UsnJournalReturnCode
  285.         DeleteUsnJournal(USN_JOURNAL_DATA journalState)
  286.     {
  287.         UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;
  288.         DateTime startTime = DateTime.Now;
  289.  
  290.         if (bNtfsVolume)
  291.         {
  292.             if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  293.             {
  294.                 usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  295.                 UInt32 cb;
  296.  
  297.                 DELETE_USN_JOURNAL_DATA dujd = new DELETE_USN_JOURNAL_DATA();
  298.                 dujd.UsnJournalID = journalState.UsnJournalID;
  299.                 dujd.DeleteFlags = (UInt32)UsnJournalDeleteFlags.USN_DELETE_FLAG_DELETE;
  300.  
  301.                 int sizeDujd = Marshal.SizeOf(dujd);
  302.                 IntPtr dujdBuffer = Marshal.AllocHGlobal(sizeDujd);
  303.                 ZeroMemory(dujdBuffer, sizeDujd);
  304.                 Marshal.StructureToPtr(dujd, dujdBuffer, true);
  305.  
  306.                 bool fOk = DeviceIoControl(
  307.                     _usnJournalRootHandle,
  308.                     FSCTL_DELETE_USN_JOURNAL,
  309.                     dujdBuffer,
  310.                     sizeDujd,
  311.                     IntPtr.Zero,
  312.                     0,
  313.                     out cb,
  314.                     IntPtr.Zero);
  315.  
  316.                 if (!fOk)
  317.                 {
  318.                     usnRtnCode = ConvertWin32ErrorToUsnError((GetLastErrorEnum)Marshal.GetLastWin32Error());
  319.                 }
  320.                 Marshal.FreeHGlobal(dujdBuffer);
  321.             }
  322.             else
  323.             {
  324.                 usnRtnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
  325.             }
  326.         }
  327.  
  328.         _elapsedTime = DateTime.Now - startTime;
  329.         return usnRtnCode;
  330.     }
  331.  
  332.     /// <summary>
  333.     /// GetNtfsVolumeFolders() reads the Master File Table to find all of the folders on a volume
  334.     /// and returns them in a SortedList<UInt64, UsnEntry> folders out parameter.
  335.     /// </summary>
  336.     /// <param name="folders">A SortedList<string, UInt64> list where string is
  337.     /// the filename and UInt64 is the parent folder's file reference number
  338.     /// </param>
  339.     /// <param name="elapsedTime">A TimeSpan object that on return holds the elapsed time
  340.     /// </param>
  341.     /// <returns>
  342.     /// USN_JOURNAL_SUCCESS                 GetNtfsVolumeFolders() function succeeded.
  343.     /// VOLUME_NOT_NTFS                     volume is not an NTFS volume.
  344.     /// INVALID_HANDLE_VALUE                NtfsUsnJournal object failed initialization.
  345.     /// USN_JOURNAL_NOT_ACTIVE              usn journal is not active on volume.
  346.     /// ERROR_ACCESS_DENIED                 accessing the usn journal requires admin rights, see remarks.
  347.     /// ERROR_INVALID_FUNCTION              error generated by DeviceIoControl() call.
  348.     /// ERROR_FILE_NOT_FOUND                error generated by DeviceIoControl() call.
  349.     /// ERROR_PATH_NOT_FOUND                error generated by DeviceIoControl() call.
  350.     /// ERROR_TOO_MANY_OPEN_FILES           error generated by DeviceIoControl() call.
  351.     /// ERROR_INVALID_HANDLE                error generated by DeviceIoControl() call.
  352.     /// ERROR_INVALID_DATA                  error generated by DeviceIoControl() call.
  353.     /// ERROR_NOT_SUPPORTED                 error generated by DeviceIoControl() call.
  354.     /// ERROR_INVALID_PARAMETER             error generated by DeviceIoControl() call.
  355.     /// ERROR_JOURNAL_DELETE_IN_PROGRESS    usn journal delete is in progress.
  356.     /// ERROR_INVALID_USER_BUFFER           error generated by DeviceIoControl() call.
  357.     /// USN_JOURNAL_ERROR                   unspecified usn journal error.
  358.     /// </returns>
  359.     /// <remarks>
  360.     /// If function returns ERROR_ACCESS_DENIED you need to run application as an Administrator.
  361.     /// </remarks>
  362.     public UsnJournalReturnCode
  363.         GetNtfsVolumeFolders(out List<UsnEntry> folders)
  364.     {
  365.         DateTime startTime = DateTime.Now;
  366.         folders = new List<UsnEntry>();
  367.         UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;
  368.  
  369.         if (bNtfsVolume)
  370.         {
  371.             if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  372.             {
  373.                 usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  374.  
  375.                 USN_JOURNAL_DATA usnState = new USN_JOURNAL_DATA();
  376.                 usnRtnCode = QueryUsnJournal(ref usnState);
  377.  
  378.                 if (usnRtnCode == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
  379.                 {
  380.                     //
  381.                     // set up MFT_ENUM_DATA structure
  382.                     //
  383.                     MFT_ENUM_DATA med;
  384.                     med.StartFileReferenceNumber = 0;
  385.                     med.LowUsn = 0;
  386.                     med.HighUsn = usnState.NextUsn;
  387.                     Int32 sizeMftEnumData = Marshal.SizeOf(med);
  388.                     IntPtr medBuffer = Marshal.AllocHGlobal(sizeMftEnumData);
  389.                     ZeroMemory(medBuffer, sizeMftEnumData);
  390.                     Marshal.StructureToPtr(med, medBuffer, true);
  391.  
  392.                     //
  393.                     // set up the data buffer which receives the USN_RECORD data
  394.                     //
  395.                     int pDataSize = sizeof(UInt64) + 10000;
  396.                     IntPtr pData = Marshal.AllocHGlobal(pDataSize);
  397.                     ZeroMemory(pData, pDataSize);
  398.                     uint outBytesReturned = 0;
  399.                     UsnEntry usnEntry = null;
  400.  
  401.                     //
  402.                     // Gather up volume's directories
  403.                     //
  404.                     while (false != DeviceIoControl(
  405.                         _usnJournalRootHandle,
  406.                         FSCTL_ENUM_USN_DATA,
  407.                         medBuffer,
  408.                         sizeMftEnumData,
  409.                         pData,
  410.                         pDataSize,
  411.                         out outBytesReturned,
  412.                         IntPtr.Zero))
  413.                     {
  414.                         IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64));
  415.                         while (outBytesReturned > 60)
  416.                         {
  417.                             usnEntry = new UsnEntry(pUsnRecord);
  418.                             //
  419.                             // check for directory entries
  420.                             //
  421.                             if (usnEntry.IsFolder)
  422.                             {
  423.                                 folders.Add(usnEntry);
  424.                             }
  425.                             pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnEntry.RecordLength);
  426.                             outBytesReturned -= usnEntry.RecordLength;
  427.                         }
  428.                         Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0));
  429.                     }
  430.  
  431.                     Marshal.FreeHGlobal(pData);
  432.                     usnRtnCode = ConvertWin32ErrorToUsnError((GetLastErrorEnum)Marshal.GetLastWin32Error());
  433.                     if (usnRtnCode == UsnJournalReturnCode.ERROR_HANDLE_EOF)
  434.                     {
  435.                         usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  436.                     }
  437.                 }
  438.             }
  439.             else
  440.             {
  441.                 usnRtnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
  442.             }
  443.         }
  444.         folders.Sort();
  445.         _elapsedTime = DateTime.Now - startTime;
  446.         return usnRtnCode;
  447.     }
  448.  
  449.     public UsnJournalReturnCode
  450.         GetFilesMatchingFilter(string filter, out List<UsnEntry> files)
  451.     {
  452.         DateTime startTime = DateTime.Now;
  453.         filter = filter.ToLower();
  454.         files = new List<UsnEntry>();
  455.         string[] fileTypes = filter.Split(' ', ',', ';');
  456.         UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;
  457.  
  458.         if (bNtfsVolume)
  459.         {
  460.             if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  461.             {
  462.                 usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  463.  
  464.                 USN_JOURNAL_DATA usnState = new USN_JOURNAL_DATA();
  465.                 usnRtnCode = QueryUsnJournal(ref usnState);
  466.  
  467.                 if (usnRtnCode == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
  468.                 {
  469.                     //
  470.                     // set up MFT_ENUM_DATA structure
  471.                     //
  472.                     MFT_ENUM_DATA med;
  473.                     med.StartFileReferenceNumber = 0;
  474.                     med.LowUsn = 0;
  475.                     med.HighUsn = usnState.NextUsn;
  476.                     Int32 sizeMftEnumData = Marshal.SizeOf(med);
  477.                     IntPtr medBuffer = Marshal.AllocHGlobal(sizeMftEnumData);
  478.                     ZeroMemory(medBuffer, sizeMftEnumData);
  479.                     Marshal.StructureToPtr(med, medBuffer, true);
  480.  
  481.                     //
  482.                     // set up the data buffer which receives the USN_RECORD data
  483.                     //
  484.                     int pDataSize = sizeof(UInt64) + 10000;
  485.                     IntPtr pData = Marshal.AllocHGlobal(pDataSize);
  486.                     ZeroMemory(pData, pDataSize);
  487.                     uint outBytesReturned = 0;
  488.                     UsnEntry usnEntry = null;
  489.  
  490.                     //
  491.                     // Gather up volume's directories
  492.                     //
  493.                     while (false != DeviceIoControl(
  494.                         _usnJournalRootHandle,
  495.                         FSCTL_ENUM_USN_DATA,
  496.                         medBuffer,
  497.                         sizeMftEnumData,
  498.                         pData,
  499.                         pDataSize,
  500.                         out outBytesReturned,
  501.                         IntPtr.Zero))
  502.                     {
  503.                         IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64));
  504.                         while (outBytesReturned > 60)
  505.                         {
  506.                             usnEntry = new UsnEntry(pUsnRecord);
  507.                             //
  508.                             // check for directory entries
  509.                             //
  510.                             if (usnEntry.IsFile)
  511.                             {
  512.                                 string extension = Path.GetExtension(usnEntry.Name).ToLower();
  513.                                 if (0 == string.Compare(filter, "*"))
  514.                                 {
  515.                                     files.Add(usnEntry);
  516.                                 }
  517.                                 else if (!string.IsNullOrEmpty(extension))
  518.                                 {
  519.                                     foreach (string fileType in fileTypes)
  520.                                     {
  521.                                         if (extension.Contains(fileType))
  522.                                         {
  523.                                             files.Add(usnEntry);
  524.                                         }
  525.                                     }
  526.                                 }
  527.                             }
  528.                             pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnEntry.RecordLength);
  529.                             outBytesReturned -= usnEntry.RecordLength;
  530.                         }
  531.                         Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0));
  532.                     }
  533.  
  534.                     Marshal.FreeHGlobal(pData);
  535.                     usnRtnCode = ConvertWin32ErrorToUsnError((GetLastErrorEnum)Marshal.GetLastWin32Error());
  536.                     if (usnRtnCode == UsnJournalReturnCode.ERROR_HANDLE_EOF)
  537.                     {
  538.                         usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  539.                     }
  540.                 }
  541.             }
  542.             else
  543.             {
  544.                 usnRtnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
  545.             }
  546.         }
  547.         files.Sort();
  548.         _elapsedTime = DateTime.Now - startTime;
  549.         return usnRtnCode;
  550.     }
  551.  
  552.     /// <summary>
  553.     /// Given a file reference number GetPathFromFrn() calculates the full path in the out parameter 'path'.
  554.     /// </summary>
  555.     /// <param name="frn">A 64-bit file reference number</param>
  556.     /// <returns>
  557.     /// USN_JOURNAL_SUCCESS                 GetPathFromFrn() function succeeded.
  558.     /// VOLUME_NOT_NTFS                     volume is not an NTFS volume.
  559.     /// INVALID_HANDLE_VALUE                NtfsUsnJournal object failed initialization.
  560.     /// ERROR_ACCESS_DENIED                 accessing the usn journal requires admin rights, see remarks.
  561.     /// INVALID_FILE_REFERENCE_NUMBER       file reference number not found in Master File Table.
  562.     /// ERROR_INVALID_FUNCTION              error generated by NtCreateFile() or NtQueryInformationFile() call.
  563.     /// ERROR_FILE_NOT_FOUND                error generated by NtCreateFile() or NtQueryInformationFile() call.
  564.     /// ERROR_PATH_NOT_FOUND                error generated by NtCreateFile() or NtQueryInformationFile() call.
  565.     /// ERROR_TOO_MANY_OPEN_FILES           error generated by NtCreateFile() or NtQueryInformationFile() call.
  566.     /// ERROR_INVALID_HANDLE                error generated by NtCreateFile() or NtQueryInformationFile() call.
  567.     /// ERROR_INVALID_DATA                  error generated by NtCreateFile() or NtQueryInformationFile() call.
  568.     /// ERROR_NOT_SUPPORTED                 error generated by NtCreateFile() or NtQueryInformationFile() call.
  569.     /// ERROR_INVALID_PARAMETER             error generated by NtCreateFile() or NtQueryInformationFile() call.
  570.     /// ERROR_INVALID_USER_BUFFER           error generated by NtCreateFile() or NtQueryInformationFile() call.
  571.     /// USN_JOURNAL_ERROR                   unspecified usn journal error.
  572.     /// </returns>
  573.     /// <remarks>
  574.     /// If function returns ERROR_ACCESS_DENIED you need to run application as an Administrator.
  575.     /// </remarks>
  576.  
  577.     public UsnJournalReturnCode
  578.         GetPathFromFileReference(UInt64 frn, out string path)
  579.     {
  580.         DateTime startTime = DateTime.Now;
  581.         path = "Unavailable"
  582.             ;
  583.         UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;
  584.  
  585.         if (bNtfsVolume)
  586.         {
  587.             if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  588.             {
  589.                 if (frn != 0)
  590.                 {
  591.                     usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  592.  
  593.                     long allocSize = 0;
  594.                     UNICODE_STRING unicodeString;
  595.                     OBJECT_ATTRIBUTES objAttributes = new OBJECT_ATTRIBUTES();
  596.                     IO_STATUS_BLOCK ioStatusBlock = new IO_STATUS_BLOCK();
  597.                     IntPtr hFile = IntPtr.Zero;
  598.  
  599.                     IntPtr buffer = Marshal.AllocHGlobal(4096);
  600.                     IntPtr refPtr = Marshal.AllocHGlobal(8);
  601.                     IntPtr objAttIntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(objAttributes));
  602.  
  603.                     //
  604.                     // pointer >> fileid
  605.                     //
  606.                     Marshal.WriteInt64(refPtr, (long)frn);
  607.  
  608.                     unicodeString.Length = 8;
  609.                     unicodeString.MaximumLength = 8;
  610.                     unicodeString.Buffer = refPtr;
  611.                     //
  612.                     // copy unicode structure to pointer
  613.                     //
  614.                     Marshal.StructureToPtr(unicodeString, objAttIntPtr, true);
  615.  
  616.                     //
  617.                     //  InitializeObjectAttributes
  618.                     //
  619.                     objAttributes.Length = Marshal.SizeOf(objAttributes);
  620.                     objAttributes.ObjectName = objAttIntPtr;
  621.                     objAttributes.RootDirectory = _usnJournalRootHandle;
  622.                     objAttributes.Attributes = (int)OBJ_CASE_INSENSITIVE;
  623.  
  624.                     int fOk = NtCreateFile(
  625.                         ref hFile,
  626.                         FileAccess.Read,
  627.                         ref objAttributes,
  628.                         ref ioStatusBlock,
  629.                         ref allocSize,
  630.                         0,
  631.                         FileShare.ReadWrite,
  632.                         FILE_OPEN,
  633.                         FILE_OPEN_BY_FILE_ID | FILE_OPEN_FOR_BACKUP_INTENT,
  634.                         IntPtr.Zero, 0);
  635.                     if (fOk == 0)
  636.                     {
  637.                         fOk = NtQueryInformationFile(
  638.                             hFile,
  639.                             ref ioStatusBlock,
  640.                             buffer,
  641.                             4096,
  642.                             FILE_INFORMATION_CLASS.FileNameInformation);
  643.                         if (fOk == 0)
  644.                         {
  645.                             //
  646.                             // first 4 bytes are the name length
  647.                             //
  648.                             int nameLength = Marshal.ReadInt32(buffer, 0);
  649.                             //
  650.                             // next bytes are the name
  651.                             //
  652.                             path = Marshal.PtrToStringUni(new IntPtr(buffer.ToInt32() + 4), nameLength / 2);
  653.                         }
  654.                     }
  655.                     CloseHandle(hFile);
  656.                     Marshal.FreeHGlobal(buffer);
  657.                     Marshal.FreeHGlobal(objAttIntPtr);
  658.                     Marshal.FreeHGlobal(refPtr);
  659.                 }
  660.             }
  661.         }
  662.         _elapsedTime = DateTime.Now - startTime;
  663.         return usnRtnCode;
  664.     }
  665.  
  666.     /// <summary>
  667.     /// GetUsnJournalState() gets the current state of the USN Journal if it is active.
  668.     /// </summary>
  669.     /// <param name="usnJournalState">
  670.     /// Reference to usn journal data object filled with the current USN Journal state.
  671.     /// </param>
  672.     /// <param name="elapsedTime">The elapsed time for the GetUsnJournalState() function call.</param>
  673.     /// <returns>
  674.     /// USN_JOURNAL_SUCCESS                 GetUsnJournalState() function succeeded.
  675.     /// VOLUME_NOT_NTFS                     volume is not an NTFS volume.
  676.     /// INVALID_HANDLE_VALUE                NtfsUsnJournal object failed initialization.
  677.     /// USN_JOURNAL_NOT_ACTIVE              usn journal is not active on volume.
  678.     /// ERROR_ACCESS_DENIED                 accessing the usn journal requires admin rights, see remarks.
  679.     /// ERROR_INVALID_FUNCTION              error generated by DeviceIoControl() call.
  680.     /// ERROR_FILE_NOT_FOUND                error generated by DeviceIoControl() call.
  681.     /// ERROR_PATH_NOT_FOUND                error generated by DeviceIoControl() call.
  682.     /// ERROR_TOO_MANY_OPEN_FILES           error generated by DeviceIoControl() call.
  683.     /// ERROR_INVALID_HANDLE                error generated by DeviceIoControl() call.
  684.     /// ERROR_INVALID_DATA                  error generated by DeviceIoControl() call.
  685.     /// ERROR_NOT_SUPPORTED                 error generated by DeviceIoControl() call.
  686.     /// ERROR_INVALID_PARAMETER             error generated by DeviceIoControl() call.
  687.     /// ERROR_JOURNAL_DELETE_IN_PROGRESS    usn journal delete is in progress.
  688.     /// ERROR_INVALID_USER_BUFFER           error generated by DeviceIoControl() call.
  689.     /// USN_JOURNAL_ERROR                   unspecified usn journal error.
  690.     /// </returns>
  691.     /// <remarks>
  692.     /// If function returns ERROR_ACCESS_DENIED you need to run application as an Administrator.
  693.     /// </remarks>
  694.     public UsnJournalReturnCode
  695.         GetUsnJournalState(ref USN_JOURNAL_DATA usnJournalState)
  696.     {
  697.         UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;
  698.         DateTime startTime = DateTime.Now;
  699.  
  700.         if (bNtfsVolume)
  701.         {
  702.             if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  703.             {
  704.                 usnRtnCode = QueryUsnJournal(ref usnJournalState);
  705.             }
  706.             else
  707.             {
  708.                 usnRtnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
  709.             }
  710.         }
  711.  
  712.         _elapsedTime = DateTime.Now - startTime;
  713.         return usnRtnCode;
  714.     }
  715.  
  716.     /// <summary>
  717.     /// Given a previous state, GetUsnJournalEntries() determines if the USN Journal is active and
  718.     /// no USN Journal entries have been lost (i.e. USN Journal is valid), then
  719.     /// it loads a SortedList<UInt64, UsnEntry> list and returns it as the out parameter 'usnEntries'.
  720.     /// If GetUsnJournalChanges returns anything but USN_JOURNAL_SUCCESS, the usnEntries list will
  721.     /// be empty.
  722.     /// </summary>
  723.     /// <param name="previousUsnState">The USN Journal state the last time volume
  724.     /// changes were requested.</param>
  725.     /// <param name="newFiles">List of the filenames of all new files.</param>
  726.     /// <param name="changedFiles">List of the filenames of all changed files.</param>
  727.     /// <param name="newFolders">List of the names of all new folders.</param>
  728.     /// <param name="changedFolders">List of the names of all changed folders.</param>
  729.     /// <param name="deletedFiles">List of the names of all deleted files</param>
  730.     /// <param name="deletedFolders">List of the names of all deleted folders</param>
  731.     /// <param name="currentState">Current state of the USN Journal</param>
  732.     /// <returns>
  733.     /// USN_JOURNAL_SUCCESS                 GetUsnJournalChanges() function succeeded.
  734.     /// VOLUME_NOT_NTFS                     volume is not an NTFS volume.
  735.     /// INVALID_HANDLE_VALUE                NtfsUsnJournal object failed initialization.
  736.     /// USN_JOURNAL_NOT_ACTIVE              usn journal is not active on volume.
  737.     /// ERROR_ACCESS_DENIED                 accessing the usn journal requires admin rights, see remarks.
  738.     /// ERROR_INVALID_FUNCTION              error generated by DeviceIoControl() call.
  739.     /// ERROR_FILE_NOT_FOUND                error generated by DeviceIoControl() call.
  740.     /// ERROR_PATH_NOT_FOUND                error generated by DeviceIoControl() call.
  741.     /// ERROR_TOO_MANY_OPEN_FILES           error generated by DeviceIoControl() call.
  742.     /// ERROR_INVALID_HANDLE                error generated by DeviceIoControl() call.
  743.     /// ERROR_INVALID_DATA                  error generated by DeviceIoControl() call.
  744.     /// ERROR_NOT_SUPPORTED                 error generated by DeviceIoControl() call.
  745.     /// ERROR_INVALID_PARAMETER             error generated by DeviceIoControl() call.
  746.     /// ERROR_JOURNAL_DELETE_IN_PROGRESS    usn journal delete is in progress.
  747.     /// ERROR_INVALID_USER_BUFFER           error generated by DeviceIoControl() call.
  748.     /// USN_JOURNAL_ERROR                   unspecified usn journal error.
  749.     /// </returns>
  750.     /// <remarks>
  751.     /// If function returns ERROR_ACCESS_DENIED you need to run application as an Administrator.
  752.     /// </remarks>
  753.     public UsnJournalReturnCode
  754.         GetUsnJournalEntries(USN_JOURNAL_DATA previousUsnState,
  755.         UInt32 reasonMask,
  756.         out List<UsnEntry> usnEntries,
  757.         out USN_JOURNAL_DATA newUsnState)
  758.     {
  759.         DateTime startTime = DateTime.Now;
  760.         usnEntries = new List<UsnEntry>();
  761.         newUsnState = new USN_JOURNAL_DATA();
  762.         UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;
  763.  
  764.         if (bNtfsVolume)
  765.         {
  766.             if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  767.             {
  768.                 //
  769.                 // get current usn journal state
  770.                 //
  771.                 usnRtnCode = QueryUsnJournal(ref newUsnState);
  772.                 if (usnRtnCode == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
  773.                 {
  774.                     bool bReadMore = true;
  775.                     //
  776.                     // sequentially process the usn journal looking for image file entries
  777.                     //
  778.                     int pbDataSize = sizeof(UInt64) * 0x4000;
  779.                     IntPtr pbData = Marshal.AllocHGlobal(pbDataSize);
  780.                     ZeroMemory(pbData, pbDataSize);
  781.                     uint outBytesReturned = 0;
  782.  
  783.                     READ_USN_JOURNAL_DATA rujd = new READ_USN_JOURNAL_DATA();
  784.                     rujd.StartUsn = previousUsnState.NextUsn;
  785.                     rujd.ReasonMask = reasonMask;
  786.                     rujd.ReturnOnlyOnClose = 0;
  787.                     rujd.Timeout = 0;
  788.                     rujd.bytesToWaitFor = 0;
  789.                     rujd.UsnJournalId = previousUsnState.UsnJournalID;
  790.                     int sizeRujd = Marshal.SizeOf(rujd);
  791.  
  792.                     IntPtr rujdBuffer = Marshal.AllocHGlobal(sizeRujd);
  793.                     ZeroMemory(rujdBuffer, sizeRujd);
  794.                     Marshal.StructureToPtr(rujd, rujdBuffer, true);
  795.  
  796.                     UsnEntry usnEntry = null;
  797.  
  798.                     //
  799.                     // read usn journal entries
  800.                     //
  801.                     while (bReadMore)
  802.                     {
  803.                         bool bRtn = DeviceIoControl(
  804.                             _usnJournalRootHandle,
  805.                             FSCTL_READ_USN_JOURNAL,
  806.                             rujdBuffer,
  807.                             sizeRujd,
  808.                             pbData,
  809.                             pbDataSize,
  810.                             out outBytesReturned,
  811.                             IntPtr.Zero);
  812.                         if (bRtn)
  813.                         {
  814.                             IntPtr pUsnRecord = new IntPtr(pbData.ToInt32() + sizeof(UInt64));
  815.                             while (outBytesReturned > 60)   // while there are at least one entry in the usn journal
  816.                             {
  817.                                 usnEntry = new UsnEntry(pUsnRecord);
  818.                                 if (usnEntry.USN >= newUsnState.NextUsn)      // only read until the current usn points beyond the current state's usn
  819.                                 {
  820.                                     bReadMore = false;
  821.                                     break;
  822.                                 }
  823.                                 usnEntries.Add(usnEntry);
  824.  
  825.                                 pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnEntry.RecordLength);
  826.                                 outBytesReturned -= usnEntry.RecordLength;
  827.  
  828.                             }   // end while (outBytesReturned > 60) - closing bracket
  829.  
  830.                         }   // if (bRtn)- closing bracket
  831.                         else
  832.                         {
  833.                             GetLastErrorEnum lastWin32Error = (GetLastErrorEnum)Marshal.GetLastWin32Error();
  834.                             if (lastWin32Error == GetLastErrorEnum.ERROR_HANDLE_EOF)
  835.                             {
  836.                                 usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  837.                             }
  838.                             else
  839.                             {
  840.                                 usnRtnCode = ConvertWin32ErrorToUsnError(lastWin32Error);
  841.                             }
  842.                             break;
  843.                         }
  844.  
  845.                         Int64 nextUsn = Marshal.ReadInt64(pbData, 0);
  846.                         if (nextUsn >= newUsnState.NextUsn)
  847.                         {
  848.                             break;
  849.                         }
  850.                         Marshal.WriteInt64(rujdBuffer, nextUsn);
  851.  
  852.                     }   // end while (bReadMore) - closing bracket
  853.  
  854.                     Marshal.FreeHGlobal(rujdBuffer);
  855.                     Marshal.FreeHGlobal(pbData);
  856.  
  857.                 }   // if (usnRtnCode == UsnJournalReturnCode.USN_JOURNAL_SUCCESS) - closing bracket
  858.  
  859.             }   // if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  860.             else
  861.             {
  862.                 usnRtnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
  863.             }
  864.         }   // if (bNtfsVolume) - closing bracket
  865.  
  866.         _elapsedTime = DateTime.Now - startTime;
  867.         return usnRtnCode;
  868.     }   // GetUsnJournalChanges() - closing bracket
  869.  
  870.     /// <summary>
  871.     /// tests to see if the USN Journal is active on the volume.
  872.     /// </summary>
  873.     /// <returns>true if USN Journal is active
  874.     /// false if no USN Journal on volume</returns>
  875.     public bool
  876.         IsUsnJournalActive()
  877.     {
  878.         DateTime start = DateTime.Now;
  879.         bool bRtnCode = false;
  880.  
  881.         if (bNtfsVolume)
  882.         {
  883.             if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  884.             {
  885.                 USN_JOURNAL_DATA usnJournalCurrentState = new USN_JOURNAL_DATA();
  886.                 UsnJournalReturnCode usnError = QueryUsnJournal(ref usnJournalCurrentState);
  887.                 if (usnError == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
  888.                 {
  889.                     bRtnCode = true;
  890.                 }
  891.             }
  892.         }
  893.         _elapsedTime = DateTime.Now - start;
  894.         return bRtnCode;
  895.     }
  896.  
  897.     /// <summary>
  898.     /// tests to see if there is a USN Journal on this volume and if there is
  899.     /// determines whether any journal entries have been lost.
  900.     /// </summary>
  901.     /// <returns>true if the USN Journal is active and if the JournalId's are the same
  902.     /// and if all the usn journal entries expected by the previous state are available
  903.     /// from the current state.
  904.     /// false if not</returns>
  905.     public bool
  906.         IsUsnJournalValid(USN_JOURNAL_DATA usnJournalPreviousState)
  907.     {
  908.         DateTime start = DateTime.Now;
  909.         bool bRtnCode = false;
  910.  
  911.         if (bNtfsVolume)
  912.         {
  913.             if (_usnJournalRootHandle.ToInt32() != INVALID_HANDLE_VALUE)
  914.             {
  915.                 USN_JOURNAL_DATA usnJournalState = new USN_JOURNAL_DATA();
  916.                 UsnJournalReturnCode usnError = QueryUsnJournal(ref usnJournalState);
  917.  
  918.                 if (usnError == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
  919.                 {
  920.                     if (usnJournalPreviousState.UsnJournalID == usnJournalState.UsnJournalID)
  921.                     {
  922.                         if (usnJournalPreviousState.NextUsn >= usnJournalState.NextUsn)
  923.                         {
  924.                             bRtnCode = true;
  925.                         }
  926.                     }
  927.                 }
  928.             }
  929.         }
  930.         _elapsedTime = DateTime.Now - start;
  931.         return bRtnCode;
  932.     }
  933.  
  934.     #endregion
  935.  
  936.     #region private member functions
  937.     /// <summary>
  938.     /// Converts a Win32 Error to a UsnJournalReturnCode
  939.     /// </summary>
  940.     /// <param name="Win32LastError">The 'last' Win32 error.</param>
  941.     /// <returns>
  942.     /// INVALID_HANDLE_VALUE                error generated by Win32 Api calls.
  943.     /// USN_JOURNAL_SUCCESS                 usn journal function succeeded.
  944.     /// ERROR_INVALID_FUNCTION              error generated by Win32 Api calls.
  945.     /// ERROR_FILE_NOT_FOUND                error generated by Win32 Api calls.
  946.     /// ERROR_PATH_NOT_FOUND                error generated by Win32 Api calls.
  947.     /// ERROR_TOO_MANY_OPEN_FILES           error generated by Win32 Api calls.
  948.     /// ERROR_ACCESS_DENIED                 accessing the usn journal requires admin rights.
  949.     /// ERROR_INVALID_HANDLE                error generated by Win32 Api calls.
  950.     /// ERROR_INVALID_DATA                  error generated by Win32 Api calls.
  951.     /// ERROR_HANDLE_EOF                    error generated by Win32 Api calls.
  952.     /// ERROR_NOT_SUPPORTED                 error generated by Win32 Api calls.
  953.     /// ERROR_INVALID_PARAMETER             error generated by Win32 Api calls.
  954.     /// ERROR_JOURNAL_DELETE_IN_PROGRESS    usn journal delete is in progress.
  955.     /// ERROR_JOURNAL_ENTRY_DELETED         usn journal entry lost, no longer available.
  956.     /// ERROR_INVALID_USER_BUFFER           error generated by Win32 Api calls.
  957.     /// USN_JOURNAL_INVALID                 usn journal is invalid, id's don't match or required entries lost.
  958.     /// USN_JOURNAL_NOT_ACTIVE              usn journal is not active on volume.
  959.     /// VOLUME_NOT_NTFS                     volume is not an NTFS volume.
  960.     /// INVALID_FILE_REFERENCE_NUMBER       bad file reference number - see remarks.
  961.     /// USN_JOURNAL_ERROR                   unspecified usn journal error.
  962.     /// </returns>
  963.     private UsnJournalReturnCode
  964.         ConvertWin32ErrorToUsnError(GetLastErrorEnum Win32LastError)
  965.     {
  966.         UsnJournalReturnCode usnRtnCode;
  967.  
  968.         switch (Win32LastError)
  969.         {
  970.             case GetLastErrorEnum.ERROR_JOURNAL_NOT_ACTIVE:
  971.                 usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_NOT_ACTIVE;
  972.                 break;
  973.             case GetLastErrorEnum.ERROR_SUCCESS:
  974.                 usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  975.                 break;
  976.             case GetLastErrorEnum.ERROR_HANDLE_EOF:
  977.                 usnRtnCode = UsnJournalReturnCode.ERROR_HANDLE_EOF;
  978.                 break;
  979.             default:
  980.                 usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_ERROR;
  981.                 break;
  982.         }
  983.  
  984.         return usnRtnCode;
  985.     }
  986.  
  987.     /// <summary>
  988.     /// Gets a Volume Serial Number for the volume represented by driveInfo.
  989.     /// </summary>
  990.     /// <param name="driveInfo">DriveInfo object representing the volume in question.</param>
  991.     /// <param name="volumeSerialNumber">out parameter to hold the volume serial number.</param>
  992.     /// <returns></returns>
  993.     private UsnJournalReturnCode
  994.         GetVolumeSerialNumber(DriveInfo driveInfo, out uint volumeSerialNumber)
  995.     {
  996.         Console.WriteLine("GetVolumeSerialNumber() function entered for drive '{0}'", driveInfo.Name);
  997.  
  998.         volumeSerialNumber = 0;
  999.         UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  1000.         string pathRoot = string.Concat("\\\\.\\", driveInfo.Name);
  1001.  
  1002.         IntPtr hRoot = CreateFile(pathRoot,
  1003.             0,
  1004.             FILE_SHARE_READ | FILE_SHARE_WRITE,
  1005.             IntPtr.Zero,
  1006.             OPEN_EXISTING,
  1007.             FILE_FLAG_BACKUP_SEMANTICS,
  1008.             IntPtr.Zero);
  1009.  
  1010.         if (hRoot.ToInt32() != INVALID_HANDLE_VALUE)
  1011.         {
  1012.             BY_HANDLE_FILE_INFORMATION fi = new BY_HANDLE_FILE_INFORMATION();
  1013.             bool bRtn = GetFileInformationByHandle(hRoot, out fi);
  1014.  
  1015.             if (bRtn)
  1016.             {
  1017.                 UInt64 fileIndexHigh = (UInt64)fi.FileIndexHigh;
  1018.                 UInt64 indexRoot = (fileIndexHigh << 32) | fi.FileIndexLow;
  1019.                 volumeSerialNumber = fi.VolumeSerialNumber;
  1020.             }
  1021.             else
  1022.             {
  1023.                 usnRtnCode = (UsnJournalReturnCode)Marshal.GetLastWin32Error();
  1024.             }
  1025.  
  1026.             CloseHandle(hRoot);
  1027.         }
  1028.         else
  1029.         {
  1030.             usnRtnCode = (UsnJournalReturnCode)Marshal.GetLastWin32Error();
  1031.         }
  1032.  
  1033.         return usnRtnCode;
  1034.     }
  1035.  
  1036.     private UsnJournalReturnCode
  1037.         GetRootHandle(out IntPtr rootHandle)
  1038.     {
  1039.         //
  1040.         // private functions don't need to check for an NTFS volume or
  1041.         // a valid _usnJournalRootHandle handle
  1042.         //
  1043.         UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  1044.         rootHandle = IntPtr.Zero;
  1045.         string vol = string.Concat("\\\\.\\", _driveInfo.Name.TrimEnd('\\'));
  1046.  
  1047.         rootHandle = CreateFile(vol,
  1048.                 GENERIC_READ | GENERIC_WRITE,
  1049.                 FILE_SHARE_READ | FILE_SHARE_WRITE,
  1050.                 IntPtr.Zero,
  1051.                 OPEN_EXISTING,
  1052.                 0,
  1053.                 IntPtr.Zero);
  1054.  
  1055.         if (rootHandle.ToInt32() == INVALID_HANDLE_VALUE)
  1056.         {
  1057.             usnRtnCode = (UsnJournalReturnCode)Marshal.GetLastWin32Error();
  1058.         }
  1059.  
  1060.         return usnRtnCode;
  1061.     }
  1062.  
  1063.     /// <summary>
  1064.     /// This function queries the usn journal on the volume.
  1065.     /// </summary>
  1066.     /// <param name="usnJournalState">the USN_JOURNAL_DATA object that is associated with this volume</param>
  1067.     /// <returns></returns>
  1068.     private UsnJournalReturnCode
  1069.         QueryUsnJournal(ref USN_JOURNAL_DATA usnJournalState)
  1070.     {
  1071.         //
  1072.         // private functions don't need to check for an NTFS volume or
  1073.         // a valid _usnJournalRootHandle handle
  1074.         //
  1075.         UsnJournalReturnCode usnReturnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
  1076.         int sizeUsnJournalState = Marshal.SizeOf(usnJournalState);
  1077.         UInt32 cb;
  1078.  
  1079.         bool fOk = DeviceIoControl(
  1080.             _usnJournalRootHandle,
  1081.             FSCTL_QUERY_USN_JOURNAL,
  1082.             IntPtr.Zero,
  1083.             0,
  1084.             out usnJournalState,
  1085.             sizeUsnJournalState,
  1086.             out cb,
  1087.             IntPtr.Zero);
  1088.  
  1089.         if (!fOk)
  1090.         {
  1091.             int lastWin32Error = Marshal.GetLastWin32Error();
  1092.             usnReturnCode = ConvertWin32ErrorToUsnError((GetLastErrorEnum)Marshal.GetLastWin32Error());
  1093.         }
  1094.  
  1095.         return usnReturnCode;
  1096.     }
  1097.  
  1098.     #endregion
  1099.  
  1100.     #region IDisposable Members
  1101.  
  1102.     public void Dispose()
  1103.     {
  1104.         CloseHandle(_usnJournalRootHandle);
  1105.     }
  1106.     #endregion
  1107.  
  1108.     #region enums
  1109.     public enum GetLastErrorEnum
  1110.     {
  1111.         INVALID_HANDLE_VALUE = -1,
  1112.         ERROR_SUCCESS = 0,
  1113.         ERROR_INVALID_FUNCTION = 1,
  1114.         ERROR_FILE_NOT_FOUND = 2,
  1115.         ERROR_PATH_NOT_FOUND = 3,
  1116.         ERROR_TOO_MANY_OPEN_FILES = 4,
  1117.         ERROR_ACCESS_DENIED = 5,
  1118.         ERROR_INVALID_HANDLE = 6,
  1119.         ERROR_INVALID_DATA = 13,
  1120.         ERROR_HANDLE_EOF = 38,
  1121.         ERROR_NOT_SUPPORTED = 50,
  1122.         ERROR_INVALID_PARAMETER = 87,
  1123.         ERROR_JOURNAL_DELETE_IN_PROGRESS = 1178,
  1124.         ERROR_JOURNAL_NOT_ACTIVE = 1179,
  1125.         ERROR_JOURNAL_ENTRY_DELETED = 1181,
  1126.         ERROR_INVALID_USER_BUFFER = 1784
  1127.     }
  1128.  
  1129.     public enum UsnJournalDeleteFlags
  1130.     {
  1131.         USN_DELETE_FLAG_DELETE = 1,
  1132.         USN_DELETE_FLAG_NOTIFY = 2
  1133.     }
  1134.  
  1135.     public enum FILE_INFORMATION_CLASS
  1136.     {
  1137.         FileDirectoryInformation = 1,     // 1
  1138.         FileFullDirectoryInformation = 2,     // 2
  1139.         FileBothDirectoryInformation = 3,     // 3
  1140.         FileBasicInformation = 4,         // 4
  1141.         FileStandardInformation = 5,      // 5
  1142.         FileInternalInformation = 6,      // 6
  1143.         FileEaInformation = 7,        // 7
  1144.         FileAccessInformation = 8,        // 8
  1145.         FileNameInformation = 9,          // 9
  1146.         FileRenameInformation = 10,        // 10
  1147.         FileLinkInformation = 11,          // 11
  1148.         FileNamesInformation = 12,         // 12
  1149.         FileDispositionInformation = 13,       // 13
  1150.         FilePositionInformation = 14,      // 14
  1151.         FileFullEaInformation = 15,        // 15
  1152.         FileModeInformation = 16,     // 16
  1153.         FileAlignmentInformation = 17,     // 17
  1154.         FileAllInformation = 18,           // 18
  1155.         FileAllocationInformation = 19,    // 19
  1156.         FileEndOfFileInformation = 20,     // 20
  1157.         FileAlternateNameInformation = 21,     // 21
  1158.         FileStreamInformation = 22,        // 22
  1159.         FilePipeInformation = 23,          // 23
  1160.         FilePipeLocalInformation = 24,     // 24
  1161.         FilePipeRemoteInformation = 25,    // 25
  1162.         FileMailslotQueryInformation = 26,     // 26
  1163.         FileMailslotSetInformation = 27,       // 27
  1164.         FileCompressionInformation = 28,       // 28
  1165.         FileObjectIdInformation = 29,      // 29
  1166.         FileCompletionInformation = 30,    // 30
  1167.         FileMoveClusterInformation = 31,       // 31
  1168.         FileQuotaInformation = 32,         // 32
  1169.         FileReparsePointInformation = 33,      // 33
  1170.         FileNetworkOpenInformation = 34,       // 34
  1171.         FileAttributeTagInformation = 35,      // 35
  1172.         FileTrackingInformation = 36,      // 36
  1173.         FileIdBothDirectoryInformation = 37,   // 37
  1174.         FileIdFullDirectoryInformation = 38,   // 38
  1175.         FileValidDataLengthInformation = 39,   // 39
  1176.         FileShortNameInformation = 40,     // 40
  1177.         FileHardLinkInformation = 46    // 46    
  1178.     }
  1179.  
  1180.     #endregion
  1181.  
  1182.     #region constants
  1183.     public const Int32 INVALID_HANDLE_VALUE = -1;
  1184.  
  1185.     public const UInt32 GENERIC_READ = 0x80000000;
  1186.     public const UInt32 GENERIC_WRITE = 0x40000000;
  1187.     public const UInt32 FILE_SHARE_READ = 0x00000001;
  1188.     public const UInt32 FILE_SHARE_WRITE = 0x00000002;
  1189.     public const UInt32 FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
  1190.  
  1191.     public const UInt32 CREATE_NEW = 1;
  1192.     public const UInt32 CREATE_ALWAYS = 2;
  1193.     public const UInt32 OPEN_EXISTING = 3;
  1194.     public const UInt32 OPEN_ALWAYS = 4;
  1195.     public const UInt32 TRUNCATE_EXISTING = 5;
  1196.  
  1197.     public const UInt32 FILE_ATTRIBUTE_NORMAL = 0x80;
  1198.     public const UInt32 FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
  1199.     public const UInt32 FileNameInformationClass = 9;
  1200.     public const UInt32 FILE_OPEN_FOR_BACKUP_INTENT = 0x4000;
  1201.     public const UInt32 FILE_OPEN_BY_FILE_ID = 0x2000;
  1202.     public const UInt32 FILE_OPEN = 0x1;
  1203.     public const UInt32 OBJ_CASE_INSENSITIVE = 0x40;
  1204.     //public const OBJ_KERNEL_HANDLE = 0x200;
  1205.  
  1206.     // CTL_CODE( DeviceType, Function, Method, Access ) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
  1207.     private const UInt32 FILE_DEVICE_FILE_SYSTEM = 0x00000009;
  1208.     private const UInt32 METHOD_NEITHER = 3;
  1209.     private const UInt32 METHOD_BUFFERED = 0;
  1210.     private const UInt32 FILE_ANY_ACCESS = 0;
  1211.     private const UInt32 FILE_SPECIAL_ACCESS = 0;
  1212.     private const UInt32 FILE_READ_ACCESS = 1;
  1213.     private const UInt32 FILE_WRITE_ACCESS = 2;
  1214.  
  1215.     public const UInt32 USN_REASON_DATA_OVERWRITE = 0x00000001;
  1216.     public const UInt32 USN_REASON_DATA_EXTEND = 0x00000002;
  1217.     public const UInt32 USN_REASON_DATA_TRUNCATION = 0x00000004;
  1218.     public const UInt32 USN_REASON_NAMED_DATA_OVERWRITE = 0x00000010;
  1219.     public const UInt32 USN_REASON_NAMED_DATA_EXTEND = 0x00000020;
  1220.     public const UInt32 USN_REASON_NAMED_DATA_TRUNCATION = 0x00000040;
  1221.     public const UInt32 USN_REASON_FILE_CREATE = 0x00000100;
  1222.     public const UInt32 USN_REASON_FILE_DELETE = 0x00000200;
  1223.     public const UInt32 USN_REASON_EA_CHANGE = 0x00000400;
  1224.     public const UInt32 USN_REASON_SECURITY_CHANGE = 0x00000800;
  1225.     public const UInt32 USN_REASON_RENAME_OLD_NAME = 0x00001000;
  1226.     public const UInt32 USN_REASON_RENAME_NEW_NAME = 0x00002000;
  1227.     public const UInt32 USN_REASON_INDEXABLE_CHANGE = 0x00004000;
  1228.     public const UInt32 USN_REASON_BASIC_INFO_CHANGE = 0x00008000;
  1229.     public const UInt32 USN_REASON_HARD_LINK_CHANGE = 0x00010000;
  1230.     public const UInt32 USN_REASON_COMPRESSION_CHANGE = 0x00020000;
  1231.     public const UInt32 USN_REASON_ENCRYPTION_CHANGE = 0x00040000;
  1232.     public const UInt32 USN_REASON_OBJECT_ID_CHANGE = 0x00080000;
  1233.     public const UInt32 USN_REASON_REPARSE_POINT_CHANGE = 0x00100000;
  1234.     public const UInt32 USN_REASON_STREAM_CHANGE = 0x00200000;
  1235.     public const UInt32 USN_REASON_CLOSE = 0x80000000;
  1236.  
  1237.     public static Int32 GWL_EXSTYLE = -20;
  1238.     public static Int32 WS_EX_LAYERED = 0x00080000;
  1239.     public static Int32 WS_EX_TRANSPARENT = 0x00000020;
  1240.  
  1241.     public const UInt32 FSCTL_GET_OBJECT_ID = 0x9009c;
  1242.  
  1243.     // FSCTL_ENUM_USN_DATA = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 44,  METHOD_NEITHER, FILE_ANY_ACCESS)
  1244.     public const UInt32 FSCTL_ENUM_USN_DATA = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (44 << 2) | METHOD_NEITHER;
  1245.  
  1246.     // FSCTL_READ_USN_JOURNAL = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 46,  METHOD_NEITHER, FILE_ANY_ACCESS)
  1247.     public const UInt32 FSCTL_READ_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (46 << 2) | METHOD_NEITHER;
  1248.  
  1249.     //  FSCTL_CREATE_USN_JOURNAL        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 57,  METHOD_NEITHER, FILE_ANY_ACCESS)
  1250.     public const UInt32 FSCTL_CREATE_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (57 << 2) | METHOD_NEITHER;
  1251.  
  1252.     //  FSCTL_QUERY_USN_JOURNAL         CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 61, METHOD_BUFFERED, FILE_ANY_ACCESS)
  1253.     public const UInt32 FSCTL_QUERY_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (61 << 2) | METHOD_BUFFERED;
  1254.  
  1255.     // FSCTL_DELETE_USN_JOURNAL        CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 62, METHOD_BUFFERED, FILE_ANY_ACCESS)
  1256.     public const UInt32 FSCTL_DELETE_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (62 << 2) | METHOD_BUFFERED;
  1257.  
  1258.     #endregion
  1259.  
  1260.     #region dll imports
  1261.  
  1262.     /// <summary>
  1263.     /// Creates the file specified by 'lpFileName' with desired access, share mode, security attributes,
  1264.     /// creation disposition, flags and attributes.
  1265.     /// </summary>
  1266.     /// <param name="lpFileName">Fully qualified path to a file</param>
  1267.     /// <param name="dwDesiredAccess">Requested access (write, read, read/write, none)</param>
  1268.     /// <param name="dwShareMode">Share mode (read, write, read/write, delete, all, none)</param>
  1269.     /// <param name="lpSecurityAttributes">IntPtr to a 'SECURITY_ATTRIBUTES' structure</param>
  1270.     /// <param name="dwCreationDisposition">Action to take on file or device specified by 'lpFileName' (CREATE_NEW,
  1271.     /// CREATE_ALWAYS, OPEN_ALWAYS, OPEN_EXISTING, TRUNCATE_EXISTING)</param>
  1272.     /// <param name="dwFlagsAndAttributes">File or device attributes and flags (typically FILE_ATTRIBUTE_NORMAL)</param>
  1273.     /// <param name="hTemplateFile">IntPtr to a valid handle to a template file with 'GENERIC_READ' access right</param>
  1274.     /// <returns>IntPtr handle to the 'lpFileName' file or device or 'INVALID_HANDLE_VALUE'</returns>
  1275.     [DllImport("kernel32.dll", SetLastError = true)]
  1276.     public static extern IntPtr
  1277.         CreateFile(string lpFileName,
  1278.         uint dwDesiredAccess,
  1279.         uint dwShareMode,
  1280.         IntPtr lpSecurityAttributes,
  1281.         uint dwCreationDisposition,
  1282.         uint dwFlagsAndAttributes,
  1283.         IntPtr hTemplateFile);
  1284.  
  1285.     /// <summary>
  1286.     /// Closes the file specified by the IntPtr 'hObject'.
  1287.     /// </summary>
  1288.     /// <param name="hObject">IntPtr handle to a file</param>
  1289.     /// <returns>'true' if successful, otherwise 'false'</returns>
  1290.     [DllImport("kernel32.dll", SetLastError = true)]
  1291.     [return: MarshalAs(UnmanagedType.Bool)]
  1292.     public static extern bool
  1293.         CloseHandle(
  1294.         IntPtr hObject);
  1295.  
  1296.     /// <summary>
  1297.     /// Fills the 'BY_HANDLE_FILE_INFORMATION' structure for the file specified by 'hFile'.
  1298.     /// </summary>
  1299.     /// <param name="hFile">Fully qualified name of a file</param>
  1300.     /// <param name="lpFileInformation">Out BY_HANDLE_FILE_INFORMATION argument</param>
  1301.     /// <returns>'true' if successful, otherwise 'false'</returns>
  1302.     [DllImport("kernel32.dll", SetLastError = true)]
  1303.     [return: MarshalAs(UnmanagedType.Bool)]
  1304.     public static extern bool
  1305.         GetFileInformationByHandle(
  1306.         IntPtr hFile,
  1307.         out BY_HANDLE_FILE_INFORMATION lpFileInformation);
  1308.  
  1309.     /// <summary>
  1310.     /// Deletes the file specified by 'fileName'.
  1311.     /// </summary>
  1312.     /// <param name="fileName">Fully qualified path to the file to delete</param>
  1313.     /// <returns>'true' if successful, otherwise 'false'</returns>
  1314.     [DllImport("kernel32.dll", SetLastError = true)]
  1315.     [return: MarshalAs(UnmanagedType.Bool)]
  1316.     public static extern bool DeleteFile(
  1317.         string fileName);
  1318.  
  1319.     /// <summary>
  1320.     /// Read data from the file specified by 'hFile'.
  1321.     /// </summary>
  1322.     /// <param name="hFile">IntPtr handle to the file to read</param>
  1323.     /// <param name="lpBuffer">IntPtr to a buffer of bytes to receive the bytes read from 'hFile'</param>
  1324.     /// <param name="nNumberOfBytesToRead">Number of bytes to read from 'hFile'</param>
  1325.     /// <param name="lpNumberOfBytesRead">Number of bytes read from 'hFile'</param>
  1326.     /// <param name="lpOverlapped">IntPtr to an 'OVERLAPPED' structure</param>
  1327.     /// <returns>'true' if successful, otherwise 'false'</returns>
  1328.     [DllImport("kernel32.dll")]
  1329.     [return: MarshalAs(UnmanagedType.Bool)]
  1330.     public static extern bool ReadFile(
  1331.         IntPtr hFile,
  1332.         IntPtr lpBuffer,
  1333.         uint nNumberOfBytesToRead,
  1334.         out uint lpNumberOfBytesRead,
  1335.         IntPtr lpOverlapped);
  1336.  
  1337.     /// <summary>
  1338.     /// Writes the
  1339.     /// </summary>
  1340.     /// <param name="hFile">IntPtr handle to the file to write</param>
  1341.     /// <param name="bytes">IntPtr to a buffer of bytes to write to 'hFile'</param>
  1342.     /// <param name="nNumberOfBytesToWrite">Number of bytes in 'lpBuffer' to write to 'hFile'</param>
  1343.     /// <param name="lpNumberOfBytesWritten">Number of bytes written to 'hFile'</param>
  1344.     /// <param name="overlapped">IntPtr to an 'OVERLAPPED' structure</param>
  1345.     /// <returns>'true' if successful, otherwise 'false'</returns>
  1346.     [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  1347.     [return: MarshalAs(UnmanagedType.Bool)]
  1348.     public static extern bool WriteFile(
  1349.         IntPtr hFile,
  1350.         IntPtr bytes,
  1351.         uint nNumberOfBytesToWrite,
  1352.         out uint lpNumberOfBytesWritten,
  1353.         int overlapped);
  1354.  
  1355.     /// <summary>
  1356.     /// Writes the data in 'lpBuffer' to the file specified by 'hFile'.
  1357.     /// </summary>
  1358.     /// <param name="hFile">IntPtr handle to file to write</param>
  1359.     /// <param name="lpBuffer">Buffer of bytes to write to file 'hFile'</param>
  1360.     /// <param name="nNumberOfBytesToWrite">Number of bytes in 'lpBuffer' to write to 'hFile'</param>
  1361.     /// <param name="lpNumberOfBytesWritten">Number of bytes written to 'hFile'</param>
  1362.     /// <param name="overlapped">IntPtr to an 'OVERLAPPED' structure</param>
  1363.     /// <returns>'true' if successful, otherwise 'false'</returns>
  1364.     [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  1365.     [return: MarshalAs(UnmanagedType.Bool)]
  1366.     public static extern bool WriteFile(
  1367.         IntPtr hFile,
  1368.         byte[] lpBuffer,
  1369.         uint nNumberOfBytesToWrite,
  1370.         out uint lpNumberOfBytesWritten,
  1371.         int overlapped);
  1372.  
  1373.     /// <summary>
  1374.     /// Sends the 'dwIoControlCode' to the device specified by 'hDevice'.
  1375.     /// </summary>
  1376.     /// <param name="hDevice">IntPtr handle to the device to receive 'dwIoControlCode'</param>
  1377.     /// <param name="dwIoControlCode">Device IO Control Code to send</param>
  1378.     /// <param name="lpInBuffer">Input buffer if required</param>
  1379.     /// <param name="nInBufferSize">Size of input buffer</param>
  1380.     /// <param name="lpOutBuffer">Output buffer if required</param>
  1381.     /// <param name="nOutBufferSize">Size of output buffer</param>
  1382.     /// <param name="lpBytesReturned">Number of bytes returned in output buffer</param>
  1383.     /// <param name="lpOverlapped">IntPtr to an 'OVERLAPPED' structure</param>
  1384.     /// <returns>'true' if successful, otherwise 'false'</returns>
  1385.     [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
  1386.     [return: MarshalAs(UnmanagedType.Bool)]
  1387.     public static extern bool DeviceIoControl(
  1388.         IntPtr hDevice,
  1389.         UInt32 dwIoControlCode,
  1390.         IntPtr lpInBuffer,
  1391.         Int32 nInBufferSize,
  1392.         out USN_JOURNAL_DATA lpOutBuffer,
  1393.         Int32 nOutBufferSize,
  1394.         out uint lpBytesReturned,
  1395.         IntPtr lpOverlapped);
  1396.  
  1397.     /// <summary>
  1398.     /// Sends the control code 'dwIoControlCode' to the device driver specified by 'hDevice'.
  1399.     /// </summary>
  1400.     /// <param name="hDevice">IntPtr handle to the device to receive 'dwIoControlCode</param>
  1401.     /// <param name="dwIoControlCode">Device IO Control Code to send</param>
  1402.     /// <param name="lpInBuffer">Input buffer if required</param>
  1403.     /// <param name="nInBufferSize">Size of input buffer </param>
  1404.     /// <param name="lpOutBuffer">Output buffer if required</param>
  1405.     /// <param name="nOutBufferSize">Size of output buffer</param>
  1406.     /// <param name="lpBytesReturned">Number of bytes returned</param>
  1407.     /// <param name="lpOverlapped">Pointer to an 'OVERLAPPED' struture</param>
  1408.     /// <returns></returns>
  1409.     [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
  1410.     [return: MarshalAs(UnmanagedType.Bool)]
  1411.     public static extern bool DeviceIoControl(
  1412.         IntPtr hDevice,
  1413.         UInt32 dwIoControlCode,
  1414.         IntPtr lpInBuffer,
  1415.         Int32 nInBufferSize,
  1416.         IntPtr lpOutBuffer,
  1417.         Int32 nOutBufferSize,
  1418.         out uint lpBytesReturned,
  1419.         IntPtr lpOverlapped);
  1420.  
  1421.     /// <summary>
  1422.     /// Sets the number of bytes specified by 'size' of the memory associated with the argument 'ptr'
  1423.     /// to zero.
  1424.     /// </summary>
  1425.     /// <param name="ptr"></param>
  1426.     /// <param name="size"></param>
  1427.     [DllImport("kernel32.dll")]
  1428.     public static extern void ZeroMemory(IntPtr ptr, int size);
  1429.  
  1430.     /// <summary>
  1431.     /// Retrieves the cursor's position, in screen coordinates.
  1432.     /// </summary>
  1433.     /// <param name="pt">Pointer to a POINT structure that receives the screen coordinates of the cursor</param>
  1434.     /// <returns>Returns nonzero if successful or zero otherwise. To get extended error information, call GetLastError.</returns>
  1435.     [DllImport("user32.dll", CharSet = CharSet.Auto)]
  1436.     [return: MarshalAs(UnmanagedType.Bool)]
  1437.     public static extern bool GetCursorPos(out POINT pt);
  1438.  
  1439.     /// <summary>
  1440.     /// retrieves information about the specified window. The function also retrieves the 32-bit (long)
  1441.     /// value at the specified offset into the extra window memory.
  1442.     /// </summary>
  1443.     /// <param name="hWnd">Handle to the window and, indirectly, the class to which the window belongs</param>
  1444.     /// <param name="nIndex">the zero-based offset to the value to be retrieved</param>
  1445.     /// <returns>If the function succeeds, the return value is the requested 32-bit value.
  1446.     /// If the function fails, the return value is zero. To get extended error information, call GetLastError
  1447.     ///</returns>
  1448.     [DllImport("user32.dll", CharSet = CharSet.Auto)]
  1449.     public static extern Int32 GetWindowLong(IntPtr hWnd, Int32 nIndex);
  1450.  
  1451.     /// <summary>
  1452.     /// changes an attribute of the specified window. The function also sets the 32-bit (long) value at
  1453.     /// the specified offset into the extra window memory
  1454.     /// </summary>
  1455.     /// <param name="hWnd">Handle to the window and, indirectly, the class to which the window belongs</param>
  1456.     /// <param name="nIndex">the zero-based offset to the value to be set</param>
  1457.     /// <param name="newVal">the replacement value</param>
  1458.     /// <returns>If the function succeeds, the return value is the previous value of the specified 32-bit
  1459.     /// integer. If the function fails, the return value is zero. To get extended error information, call GetLastError.
  1460.     /// </returns>
  1461.     [DllImport("user32.dll", CharSet = CharSet.Auto)]
  1462.     public static extern Int32 SetWindowLong(IntPtr hWnd, Int32 nIndex, Int32 newVal);
  1463.  
  1464.     /// <summary>
  1465.     /// Creates a new file or directory, or opens an existing file, device, directory, or volume
  1466.     /// </summary>
  1467.     /// <param name="handle">A pointer to a variable that receives the file handle if the call is successful (out)</param>
  1468.     /// <param name="access">ACCESS_MASK value that expresses the type of access that the caller requires to the file or directory (in)</param>
  1469.     /// <param name="objectAttributes">A pointer to a structure already initialized with InitializeObjectAttributes (in)</param>
  1470.     /// <param name="ioStatus">A pointer to a variable that receives the final completion status and information about the requested operation (out)</param>
  1471.     /// <param name="allocSize">The initial allocation size in bytes for the file (in)(optional)</param>
  1472.     /// <param name="fileAttributes">file attributes (in)</param>
  1473.     /// <param name="share">type of share access that the caller would like to use in the file (in)</param>
  1474.     /// <param name="createDisposition">what to do, depending on whether the file already exists (in)</param>
  1475.     /// <param name="createOptions">options to be applied when creating or opening the file (in)</param>
  1476.     /// <param name="eaBuffer">Pointer to an EA buffer used to pass extended attributes (in)</param>
  1477.     /// <param name="eaLength">Length of the EA buffer</param>
  1478.     /// <returns>either STATUS_SUCCESS or an appropriate error status. If it returns an error status, the caller can find more information about the cause of the failure by checking the IoStatusBlock</returns>
  1479.     [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)]
  1480.     public static extern int NtCreateFile(
  1481.         ref IntPtr handle,
  1482.         FileAccess access,
  1483.         ref OBJECT_ATTRIBUTES objectAttributes,
  1484.         ref IO_STATUS_BLOCK ioStatus,
  1485.         ref long allocSize,
  1486.         uint fileAttributes,
  1487.         FileShare share,
  1488.         uint createDisposition,
  1489.         uint createOptions,
  1490.         IntPtr eaBuffer,
  1491.         uint eaLength);
  1492.  
  1493.     /// <summary>
  1494.     ///
  1495.     /// </summary>
  1496.     /// <param name="fileHandle"></param>
  1497.     /// <param name="IoStatusBlock"></param>
  1498.     /// <param name="pInfoBlock"></param>
  1499.     /// <param name="length"></param>
  1500.     /// <param name="fileInformation"></param>
  1501.     /// <returns></returns>
  1502.     [DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)]
  1503.     public static extern int NtQueryInformationFile(
  1504.         IntPtr fileHandle,
  1505.         ref IO_STATUS_BLOCK IoStatusBlock,
  1506.         IntPtr pInfoBlock,
  1507.         uint length,
  1508.         FILE_INFORMATION_CLASS fileInformation);
  1509.  
  1510.     #endregion
  1511.  
  1512.     #region structures
  1513.  
  1514.     /// <summary>
  1515.     /// By Handle File Information structure, contains File Attributes(32bits), Creation Time(FILETIME),
  1516.     /// Last Access Time(FILETIME), Last Write Time(FILETIME), Volume Serial Number(32bits),
  1517.     /// File Size High(32bits), File Size Low(32bits), Number of Links(32bits), File Index High(32bits),
  1518.     /// File Index Low(32bits).
  1519.     /// </summary>
  1520.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1521.     public struct BY_HANDLE_FILE_INFORMATION
  1522.     {
  1523.         public uint FileAttributes;
  1524.         public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime;
  1525.         public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime;
  1526.         public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime;
  1527.         public uint VolumeSerialNumber;
  1528.         public uint FileSizeHigh;
  1529.         public uint FileSizeLow;
  1530.         public uint NumberOfLinks;
  1531.         public uint FileIndexHigh;
  1532.         public uint FileIndexLow;
  1533.     }
  1534.  
  1535.     /// <summary>
  1536.     /// USN Journal Data structure, contains USN Journal ID(64bits), First USN(64bits), Next USN(64bits),
  1537.     /// Lowest Valid USN(64bits), Max USN(64bits), Maximum Size(64bits) and Allocation Delta(64bits).
  1538.     /// </summary>
  1539.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1540.     public struct USN_JOURNAL_DATA
  1541.     {
  1542.         public UInt64 UsnJournalID;
  1543.         public Int64 FirstUsn;
  1544.         public Int64 NextUsn;
  1545.         public Int64 LowestValidUsn;
  1546.         public Int64 MaxUsn;
  1547.         public UInt64 MaximumSize;
  1548.         public UInt64 AllocationDelta;
  1549.     }
  1550.  
  1551.     /// <summary>
  1552.     /// MFT Enum Data structure, contains Start File Reference Number(64bits), Low USN(64bits),
  1553.     /// High USN(64bits).
  1554.     /// </summary>
  1555.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1556.     public struct MFT_ENUM_DATA
  1557.     {
  1558.         public UInt64 StartFileReferenceNumber;
  1559.         public Int64 LowUsn;
  1560.         public Int64 HighUsn;
  1561.     }
  1562.  
  1563.     /// <summary>
  1564.     /// Create USN Journal Data structure, contains Maximum Size(64bits) and Allocation Delta(64(bits).
  1565.     /// </summary>
  1566.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1567.     public struct CREATE_USN_JOURNAL_DATA
  1568.     {
  1569.         public UInt64 MaximumSize;
  1570.         public UInt64 AllocationDelta;
  1571.     }
  1572.  
  1573.     /// <summary>
  1574.     /// Create USN Journal Data structure, contains Maximum Size(64bits) and Allocation Delta(64(bits).
  1575.     /// </summary>
  1576.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1577.     public struct DELETE_USN_JOURNAL_DATA
  1578.     {
  1579.         public UInt64 UsnJournalID;
  1580.         public UInt32 DeleteFlags;
  1581.         public UInt32 Reserved;
  1582.     }
  1583.  
  1584.     /// <summary>
  1585.     /// Contains the USN Record Length(32bits), USN(64bits), File Reference Number(64bits),
  1586.     /// Parent File Reference Number(64bits), Reason Code(32bits), File Attributes(32bits),
  1587.     /// File Name Length(32bits), the File Name Offset(32bits) and the File Name.
  1588.     /// </summary>
  1589.     public class UsnEntry : IComparable<UsnEntry>
  1590.     {
  1591.         private const int FR_OFFSET = 8;
  1592.         private const int PFR_OFFSET = 16;
  1593.         private const int USN_OFFSET = 24;
  1594.         private const int REASON_OFFSET = 40;
  1595.         public const int FA_OFFSET = 52;
  1596.         private const int FNL_OFFSET = 56;
  1597.         private const int FN_OFFSET = 58;
  1598.  
  1599.         private UInt32 _recordLength;
  1600.         public UInt32 RecordLength
  1601.         {
  1602.             get { return _recordLength; }
  1603.         }
  1604.  
  1605.         private Int64 _usn;
  1606.         public Int64 USN
  1607.         {
  1608.             get { return _usn; }
  1609.         }
  1610.  
  1611.         private UInt64 _frn;
  1612.         public UInt64 FileReferenceNumber
  1613.         {
  1614.             get { return _frn; }
  1615.         }
  1616.  
  1617.         private UInt64 _pfrn;
  1618.         public UInt64 ParentFileReferenceNumber
  1619.         {
  1620.             get { return _pfrn; }
  1621.         }
  1622.  
  1623.         private UInt32 _reason;
  1624.         public UInt32 Reason
  1625.         {
  1626.             get { return _reason; }
  1627.         }
  1628.  
  1629.         private string _name;
  1630.         public string Name
  1631.         {
  1632.             get
  1633.             {
  1634.                 return _name;
  1635.             }
  1636.         }
  1637.  
  1638.         private string _oldName;
  1639.         public string OldName
  1640.         {
  1641.             get
  1642.             {
  1643.                 if (0 != (_fileAttributes & USN_REASON_RENAME_OLD_NAME))
  1644.                 {
  1645.                     return _oldName;
  1646.                 }
  1647.                 else
  1648.                 {
  1649.                     return null;
  1650.                 }
  1651.             }
  1652.             set { _oldName = value; }
  1653.         }
  1654.  
  1655.         private UInt32 _fileAttributes;
  1656.         public bool IsFolder
  1657.         {
  1658.             get
  1659.             {
  1660.                 bool bRtn = false;
  1661.                 if (0 != (_fileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1662.                 {
  1663.                     bRtn = true;
  1664.                 }
  1665.                 return bRtn;
  1666.             }
  1667.         }
  1668.  
  1669.         public bool IsFile
  1670.         {
  1671.             get
  1672.             {
  1673.                 bool bRtn = false;
  1674.                 if (0 == (_fileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  1675.                 {
  1676.                     bRtn = true;
  1677.                 }
  1678.                 return bRtn;
  1679.             }
  1680.         }
  1681.  
  1682.         /// <summary>
  1683.         /// USN Record Constructor
  1684.         /// </summary>
  1685.         /// <param name="p">Buffer pointer to first byte of the USN Record</param>
  1686.         public UsnEntry(IntPtr ptrToUsnRecord)
  1687.         {
  1688.             _recordLength = (UInt32)Marshal.ReadInt32(ptrToUsnRecord);
  1689.             _frn = (UInt64)Marshal.ReadInt64(ptrToUsnRecord, FR_OFFSET);
  1690.             _pfrn = (UInt64)Marshal.ReadInt64(ptrToUsnRecord, PFR_OFFSET);
  1691.             _usn = (Int64)Marshal.ReadInt64(ptrToUsnRecord, USN_OFFSET);
  1692.             _reason = (UInt32)Marshal.ReadInt32(ptrToUsnRecord, REASON_OFFSET);
  1693.             _fileAttributes = (UInt32)Marshal.ReadInt32(ptrToUsnRecord, FA_OFFSET);
  1694.             short fileNameLength = Marshal.ReadInt16(ptrToUsnRecord, FNL_OFFSET);
  1695.             short fileNameOffset = Marshal.ReadInt16(ptrToUsnRecord, FN_OFFSET);
  1696.             _name = Marshal.PtrToStringUni(new IntPtr(ptrToUsnRecord.ToInt32() + fileNameOffset), fileNameLength / sizeof(char));
  1697.         }
  1698.  
  1699.  
  1700.  
  1701.         #region IComparable<UsnEntry> Members
  1702.  
  1703.         public int CompareTo(UsnEntry other)
  1704.         {
  1705.             return string.Compare(this.Name, other.Name, true);
  1706.         }
  1707.  
  1708.         #endregion
  1709.     }
  1710.  
  1711.     /// <summary>
  1712.     /// Contains the Start USN(64bits), Reason Mask(32bits), Return Only on Close flag(32bits),
  1713.     /// Time Out(64bits), Bytes To Wait For(64bits), and USN Journal ID(64bits).
  1714.     /// </summary>
  1715.     /// <remarks> possible reason bits are from Win32Api
  1716.     /// USN_REASON_DATA_OVERWRITE
  1717.     /// USN_REASON_DATA_EXTEND
  1718.     /// USN_REASON_DATA_TRUNCATION
  1719.     /// USN_REASON_NAMED_DATA_OVERWRITE
  1720.     /// USN_REASON_NAMED_DATA_EXTEND
  1721.     /// USN_REASON_NAMED_DATA_TRUNCATION
  1722.     /// USN_REASON_FILE_CREATE
  1723.     /// USN_REASON_FILE_DELETE
  1724.     /// USN_REASON_EA_CHANGE
  1725.     /// USN_REASON_SECURITY_CHANGE
  1726.     /// USN_REASON_RENAME_OLD_NAME
  1727.     /// USN_REASON_RENAME_NEW_NAME
  1728.     /// USN_REASON_INDEXABLE_CHANGE
  1729.     /// USN_REASON_BASIC_INFO_CHANGE
  1730.     /// USN_REASON_HARD_LINK_CHANGE
  1731.     /// USN_REASON_COMPRESSION_CHANGE
  1732.     /// USN_REASON_ENCRYPTION_CHANGE
  1733.     /// USN_REASON_OBJECT_ID_CHANGE
  1734.     /// USN_REASON_REPARSE_POINT_CHANGE
  1735.     /// USN_REASON_STREAM_CHANGE
  1736.     /// USN_REASON_CLOSE
  1737.     /// </remarks>
  1738.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1739.     public struct READ_USN_JOURNAL_DATA
  1740.     {
  1741.         public Int64 StartUsn;
  1742.         public UInt32 ReasonMask;
  1743.         public UInt32 ReturnOnlyOnClose;
  1744.         public UInt64 Timeout;
  1745.         public UInt64 bytesToWaitFor;
  1746.         public UInt64 UsnJournalId;
  1747.     }
  1748.  
  1749.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1750.     public struct POINT
  1751.     {
  1752.         public int X;
  1753.         public int Y;
  1754.  
  1755.         public POINT(int x, int y)
  1756.         {
  1757.             this.X = x;
  1758.             this.Y = y;
  1759.         }
  1760.     }
  1761.  
  1762.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1763.     public struct IO_STATUS_BLOCK
  1764.     {
  1765.         public uint status;
  1766.         public ulong information;
  1767.     }
  1768.  
  1769.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1770.     public struct OBJECT_ATTRIBUTES
  1771.     {
  1772.         public Int32 Length;
  1773.         public IntPtr RootDirectory;
  1774.         public IntPtr ObjectName;
  1775.         public Int32 Attributes;
  1776.         public Int32 SecurityDescriptor;
  1777.         public Int32 SecurityQualityOfService;
  1778.     }
  1779.  
  1780.     [StructLayout(LayoutKind.Sequential, Pack = 1)]
  1781.     public struct UNICODE_STRING
  1782.     {
  1783.         public Int16 Length;
  1784.         public Int16 MaximumLength;
  1785.         public IntPtr Buffer;
  1786.     }
  1787.  
  1788.     #endregion
  1789.  
  1790.     #region functions
  1791.  
  1792.     /*
  1793.     public static string GetPathFromFileReference(IntPtr rootIntPtr, UInt64 frn)
  1794.     {
  1795.         string name = string.Empty;
  1796.  
  1797.         long allocSize = 0;
  1798.         UNICODE_STRING unicodeString;
  1799.         OBJECT_ATTRIBUTES objAttributes = new OBJECT_ATTRIBUTES();
  1800.         IO_STATUS_BLOCK ioStatusBlock = new IO_STATUS_BLOCK();
  1801.         IntPtr hFile;
  1802.  
  1803.         IntPtr buffer = Marshal.AllocHGlobal(4096);
  1804.         IntPtr refPtr = Marshal.AllocHGlobal(8);
  1805.         IntPtr objAttIntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(objAttributes));
  1806.  
  1807.         //
  1808.         // pointer >> fileid
  1809.         //
  1810.         Marshal.WriteInt64(refPtr, (long)frn);
  1811.  
  1812.         unicodeString.Length = 8;
  1813.         unicodeString.MaximumLength = 8;
  1814.         unicodeString.Buffer = refPtr;
  1815.         //
  1816.         // copy unicode structure to pointer
  1817.         //
  1818.         Marshal.StructureToPtr(unicodeString, objAttIntPtr, true);
  1819.  
  1820.         //
  1821.         //  InitializeObjectAttributes
  1822.         //
  1823.         objAttributes.Length = Marshal.SizeOf(objAttributes);
  1824.         objAttributes.ObjectName = objAttIntPtr;
  1825.         objAttributes.RootDirectory = rootIntPtr;
  1826.         objAttributes.Attributes = (int)OBJ_CASE_INSENSITIVE;
  1827.  
  1828.         int fOk = NtCreateFile(out hFile, 0, ref objAttributes, ref ioStatusBlock, ref allocSize, 0,
  1829.             FileShare.ReadWrite,
  1830.             FILE_OPEN, FILE_OPEN_BY_FILE_ID | FILE_OPEN_FOR_BACKUP_INTENT, IntPtr.Zero, 0);
  1831.         if (fOk.ToInt32() == 0)
  1832.         {
  1833.             fOk = NtQueryInformationFile(hFile, ref ioStatusBlock, buffer, 4096, FILE_INFORMATION_CLASS.FileNameInformation);
  1834.             if (fOk.ToInt32() == 0)
  1835.             {
  1836.                 //
  1837.                 // first 4 bytes are the name length
  1838.                 //
  1839.                 int nameLength = Marshal.ReadInt32(buffer, 0);
  1840.                 //
  1841.                 // next bytes are the name
  1842.                 //
  1843.                 name = Marshal.PtrToStringUni(new IntPtr(buffer.ToInt32() + 4), nameLength / 2);
  1844.             }
  1845.         }
  1846.         hFile.Close();
  1847.         Marshal.FreeHGlobal(buffer);
  1848.         Marshal.FreeHGlobal(objAttIntPtr);
  1849.         Marshal.FreeHGlobal(refPtr);
  1850.         return name;
  1851.     }
  1852.     */
  1853.  
  1854.     /// <summary>
  1855.     /// Writes the data in 'text' to the alternate stream ':Description' of the file 'currentFile.
  1856.     /// </summary>
  1857.     /// <param name="currentfile">Fully qualified path to a file</param>
  1858.     /// <param name="text">Data to write to the ':Description' stream</param>
  1859.     public static void WriteAlternateStream(string currentfile, string text)
  1860.     {
  1861.         string AltStreamDesc = currentfile + ":Description";
  1862.         IntPtr txtBuffer = IntPtr.Zero;
  1863.         IntPtr hFile = IntPtr.Zero;
  1864.         DeleteFile(AltStreamDesc);
  1865.         string descText = text.TrimEnd(' ');
  1866.  
  1867.         try
  1868.         {
  1869.             hFile = CreateFile(AltStreamDesc, GENERIC_WRITE, 0, IntPtr.Zero,
  1870.                                     CREATE_ALWAYS, 0, IntPtr.Zero);
  1871.             if (-1 != hFile.ToInt32())
  1872.             {
  1873.                 txtBuffer = Marshal.StringToHGlobalUni(descText);
  1874.                 uint nBytes, count;
  1875.                 nBytes = (uint)descText.Length;
  1876.                 bool bRtn = WriteFile(hFile, txtBuffer, sizeof(char) * nBytes, out count, 0);
  1877.                 if (!bRtn)
  1878.                 {
  1879.                     if ((sizeof(char) * nBytes) != count)
  1880.                     {
  1881.                         throw new Exception(string.Format("Bytes written {0} should be {1} for file {2}.",
  1882.                             count, sizeof(char) * nBytes, AltStreamDesc));
  1883.                     }
  1884.                     else
  1885.                     {
  1886.                         throw new Exception("WriteFile() returned false");
  1887.                     }
  1888.                 }
  1889.             }
  1890.             else
  1891.             {
  1892.                 throw new Win32Exception(Marshal.GetLastWin32Error());
  1893.             }
  1894.         }
  1895.         catch (Exception exception)
  1896.         {
  1897.             string msg = string.Format("Exception caught in WriteAlternateStream()\n  '{0}'\n  for file '{1}'.",
  1898.                 exception.Message, AltStreamDesc);
  1899.             Console.WriteLine(msg);
  1900.         }
  1901.         finally
  1902.         {
  1903.             CloseHandle(hFile);
  1904.             hFile = IntPtr.Zero;
  1905.             Marshal.FreeHGlobal(txtBuffer);
  1906.             GC.Collect();
  1907.         }
  1908.     }
  1909.  
  1910.     /// <summary>
  1911.     /// Adds the ':Description' alternate stream name to the argument 'currentFile'.
  1912.     /// </summary>
  1913.     /// <param name="currentfile">The file whose alternate stream is to be read</param>
  1914.     /// <returns>A string value representing the value of the alternate stream</returns>
  1915.     public static string ReadAlternateStream(string currentfile)
  1916.     {
  1917.         string AltStreamDesc = currentfile + ":Description";
  1918.         string returnstring = ReadAlternateStreamEx(AltStreamDesc);
  1919.         return returnstring;
  1920.     }
  1921.  
  1922.     /// <summary>
  1923.     /// Reads the stream represented by 'currentFile'.
  1924.     /// </summary>
  1925.     /// <param name="currentfile">Fully qualified path including stream</param>
  1926.     /// <returns>Value of the alternate stream as a string</returns>
  1927.     public static string ReadAlternateStreamEx(string currentfile)
  1928.     {
  1929.         string returnstring = string.Empty;
  1930.         IntPtr hFile = IntPtr.Zero;
  1931.         IntPtr buffer = IntPtr.Zero;
  1932.         try
  1933.         {
  1934.             hFile = CreateFile(currentfile, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
  1935.             if (-1 != hFile.ToInt32())
  1936.             {
  1937.                 buffer = Marshal.AllocHGlobal(1000 * sizeof(char));
  1938.                 ZeroMemory(buffer, 1000 * sizeof(char));
  1939.                 uint nBytes;
  1940.                 bool bRtn = ReadFile(hFile, buffer, 1000 * sizeof(char), out nBytes, IntPtr.Zero);
  1941.                 if (bRtn)
  1942.                 {
  1943.                     if (nBytes > 0)
  1944.                     {
  1945.                         returnstring = Marshal.PtrToStringAuto(buffer);
  1946.                         //byte[] byteBuffer = new byte[nBytes];
  1947.                         //for (int i = 0; i < nBytes; i++)
  1948.                         //{
  1949.                         //    byteBuffer[i] = Marshal.ReadByte(buffer, i);
  1950.                         //}
  1951.                         //returnstring = Encoding.Unicode.GetString(byteBuffer, 0, (int)nBytes);
  1952.                     }
  1953.                     else
  1954.                     {
  1955.                         throw new Exception("ReadFile() returned true but read zero bytes");
  1956.                     }
  1957.                 }
  1958.                 else
  1959.                 {
  1960.                     if (nBytes <= 0)
  1961.                     {
  1962.                         throw new Exception("ReadFile() read zero bytes.");
  1963.                     }
  1964.                     else
  1965.                     {
  1966.                         throw new Exception("ReadFile() returned false");
  1967.                     }
  1968.                 }
  1969.             }
  1970.             else
  1971.             {
  1972.                 Exception excptn = new Win32Exception(Marshal.GetLastWin32Error());
  1973.                 if (!excptn.Message.Contains("cannot find the file"))
  1974.                 {
  1975.                     throw excptn;
  1976.                 }
  1977.             }
  1978.         }
  1979.         catch (Exception exception)
  1980.         {
  1981.             string msg = string.Format("Exception caught in ReadAlternateStream(), '{0}'\n  for file '{1}'.",
  1982.                 exception.Message, currentfile);
  1983.             Console.WriteLine(msg);
  1984.             Console.WriteLine(exception.Message);
  1985.         }
  1986.         finally
  1987.         {
  1988.             CloseHandle(hFile);
  1989.             hFile = IntPtr.Zero;
  1990.             if (buffer != IntPtr.Zero)
  1991.             {
  1992.                 Marshal.FreeHGlobal(buffer);
  1993.             }
  1994.             GC.Collect();
  1995.         }
  1996.         return returnstring;
  1997.     }
  1998.  
  1999.     /// <summary>
  2000.     /// Read the encrypted alternate stream specified by 'currentFile'.
  2001.     /// </summary>
  2002.     /// <param name="currentfile">Fully qualified path to encrypted alternate stream</param>
  2003.     /// <returns>The un-encrypted value of the alternate stream as a string</returns>
  2004.     public static string ReadAlternateStreamEncrypted(string currentfile)
  2005.     {
  2006.         string returnstring = string.Empty;
  2007.         IntPtr buffer = IntPtr.Zero;
  2008.         IntPtr hFile = IntPtr.Zero;
  2009.         try
  2010.         {
  2011.             hFile = CreateFile(currentfile, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
  2012.             if (-1 != hFile.ToInt32())
  2013.             {
  2014.                 buffer = Marshal.AllocHGlobal(1000 * sizeof(char));
  2015.                 ZeroMemory(buffer, 1000 * sizeof(char));
  2016.                 uint nBytes;
  2017.                 bool bRtn = ReadFile(hFile, buffer, 1000 * sizeof(char), out nBytes, IntPtr.Zero);
  2018.                 if (0 != nBytes)
  2019.                 {
  2020.                     returnstring = DecryptLicenseString(buffer, nBytes);
  2021.                 }
  2022.             }
  2023.             else
  2024.             {
  2025.                 Exception excptn = new Win32Exception(Marshal.GetLastWin32Error());
  2026.                 if (!excptn.Message.Contains("cannot find the file"))
  2027.                 {
  2028.                     throw excptn;
  2029.                 }
  2030.             }
  2031.         }
  2032.         catch (Exception exception)
  2033.         {
  2034.             Console.WriteLine("Exception caught in ReadAlternateStreamEncrypted()");
  2035.             Console.WriteLine(exception.Message);
  2036.         }
  2037.         finally
  2038.         {
  2039.             CloseHandle(hFile);
  2040.             hFile = IntPtr.Zero;
  2041.             if (buffer != IntPtr.Zero)
  2042.             {
  2043.                 Marshal.FreeHGlobal(buffer);
  2044.             }
  2045.             GC.Collect();
  2046.         }
  2047.         return returnstring;
  2048.     }
  2049.  
  2050.     /// <summary>
  2051.     /// Writes the value of 'LicenseString' as an encrypted stream to the file:stream specified
  2052.     /// by 'currentFile'.
  2053.     /// </summary>
  2054.     /// <param name="currentFile">Fully qualified path to the alternate stream</param>
  2055.     /// <param name="LicenseString">The string value to encrypt and write to the alternate stream</param>
  2056.     public static void WriteAlternateStreamEncrypted(string currentFile, string LicenseString)
  2057.     {
  2058.         RC2CryptoServiceProvider rc2 = null;
  2059.         CryptoStream cs = null;
  2060.         MemoryStream ms = null;
  2061.         uint count = 0;
  2062.         IntPtr buffer = IntPtr.Zero;
  2063.         IntPtr hFile = IntPtr.Zero;
  2064.         try
  2065.         {
  2066.             Encoding enc = Encoding.Unicode;
  2067.  
  2068.             byte[] ba = enc.GetBytes(LicenseString);
  2069.             ms = new MemoryStream();
  2070.  
  2071.             rc2 = new RC2CryptoServiceProvider();
  2072.             rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0");
  2073.             rc2.IV = GetBytesFromHexString("827d961224d99b2d");
  2074.  
  2075.             cs = new CryptoStream(ms, rc2.CreateEncryptor(), CryptoStreamMode.Write);
  2076.             cs.Write(ba, 0, ba.Length);
  2077.             cs.FlushFinalBlock();
  2078.  
  2079.             buffer = Marshal.AllocHGlobal(1000 * sizeof(char));
  2080.             ZeroMemory(buffer, 1000 * sizeof(char));
  2081.             uint nBytes = (uint)ms.Length;
  2082.             Marshal.Copy(ms.GetBuffer(), 0, buffer, (int)nBytes);
  2083.  
  2084.             DeleteFile(currentFile);
  2085.             hFile = CreateFile(currentFile, GENERIC_WRITE, 0, IntPtr.Zero,
  2086.                                     CREATE_ALWAYS, 0, IntPtr.Zero);
  2087.             if (-1 != hFile.ToInt32())
  2088.             {
  2089.                 bool bRtn = WriteFile(hFile, buffer, nBytes, out count, 0);
  2090.             }
  2091.             else
  2092.             {
  2093.                 Exception excptn = new Win32Exception(Marshal.GetLastWin32Error());
  2094.                 if (!excptn.Message.Contains("cannot find the file"))
  2095.                 {
  2096.                     throw excptn;
  2097.                 }
  2098.             }
  2099.         }
  2100.         catch (Exception exception)
  2101.         {
  2102.             Console.WriteLine("WriteAlternateStreamEncrypted()");
  2103.             Console.WriteLine(exception.Message);
  2104.         }
  2105.         finally
  2106.         {
  2107.             CloseHandle(hFile);
  2108.             hFile = IntPtr.Zero;
  2109.             if (cs != null)
  2110.             {
  2111.                 cs.Close();
  2112.                 cs.Dispose();
  2113.             }
  2114.  
  2115.             rc2 = null;
  2116.             if (ms != null)
  2117.             {
  2118.                 ms.Close();
  2119.                 ms.Dispose();
  2120.             }
  2121.             if (buffer != IntPtr.Zero)
  2122.             {
  2123.                 Marshal.FreeHGlobal(buffer);
  2124.             }
  2125.         }
  2126.     }
  2127.  
  2128.     /// <summary>
  2129.     /// Encrypt the string 'LicenseString' argument and return as a MemoryStream.
  2130.     /// </summary>
  2131.     /// <param name="LicenseString">The string value to encrypt</param>
  2132.     /// <returns>A MemoryStream which contains the encrypted value of 'LicenseString'</returns>
  2133.     private static MemoryStream EncryptLicenseString(string LicenseString)
  2134.     {
  2135.         Encoding enc = Encoding.Unicode;
  2136.  
  2137.         byte[] ba = enc.GetBytes(LicenseString);
  2138.         MemoryStream ms = new MemoryStream();
  2139.  
  2140.         RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
  2141.         rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0");
  2142.         rc2.IV = GetBytesFromHexString("827d961224d99b2d");
  2143.  
  2144.         CryptoStream cs = new CryptoStream(ms, rc2.CreateEncryptor(), CryptoStreamMode.Write);
  2145.         cs.Write(ba, 0, ba.Length);
  2146.  
  2147.         cs.Close();
  2148.         cs.Dispose();
  2149.         rc2 = null;
  2150.         return ms;
  2151.     }
  2152.  
  2153.     /// <summary>
  2154.     /// Given an IntPtr to a bufer and the number of bytes, decrypt the buffer and return an
  2155.     /// unencrypted text string.
  2156.     /// </summary>
  2157.     /// <param name="buffer">An IntPtr to the 'buffer' containing the encrypted string</param>
  2158.     /// <param name="nBytes">The number of bytes in 'buffer' to decrypt</param>
  2159.     /// <returns></returns>
  2160.     private static string DecryptLicenseString(IntPtr buffer, uint nBytes)
  2161.     {
  2162.         byte[] ba = new byte[nBytes];
  2163.         for (int i = 0; i < nBytes; i++)
  2164.         {
  2165.             ba[i] = Marshal.ReadByte(buffer, i);
  2166.         }
  2167.         MemoryStream ms = new MemoryStream(ba);
  2168.  
  2169.         RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider();
  2170.         rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0");
  2171.         rc2.IV = GetBytesFromHexString("827d961224d99b2d");
  2172.  
  2173.         CryptoStream cs = new CryptoStream(ms, rc2.CreateDecryptor(), CryptoStreamMode.Read);
  2174.         string licenseString = string.Empty;
  2175.         byte[] ba1 = new byte[4096];
  2176.         int irtn = cs.Read(ba1, 0, 4096);
  2177.         Encoding enc = Encoding.Unicode;
  2178.         licenseString = enc.GetString(ba1, 0, irtn);
  2179.  
  2180.         cs.Close();
  2181.         cs.Dispose();
  2182.         ms.Close();
  2183.         ms.Dispose();
  2184.         rc2 = null;
  2185.         return licenseString;
  2186.     }
  2187.  
  2188.     /// <summary>
  2189.     /// Gets the byte array generated from the value of 'hexString'.
  2190.     /// </summary>
  2191.     /// <param name="hexString">Hexadecimal string</param>
  2192.     /// <returns>Array of bytes generated from 'hexString'.</returns>
  2193.     public static byte[] GetBytesFromHexString(string hexString)
  2194.     {
  2195.         int numHexChars = hexString.Length / 2;
  2196.         byte[] ba = new byte[numHexChars];
  2197.         int j = 0;
  2198.         for (int i = 0; i < ba.Length; i++)
  2199.         {
  2200.             string hex = new string(new char[] { hexString[j], hexString[j + 1] });
  2201.             ba[i] = byte.Parse(hex, System.Globalization.NumberStyles.HexNumber);
  2202.             j = j + 2;
  2203.         }
  2204.         return ba;
  2205.     }
  2206.  
  2207.     #endregion
  2208.  
  2209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement