Here is the code I promised. First the Win32Api class that has all the DllImports, the constants, etc to access the USN Journal:
using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography; using Microsoft.Win32; using System.ComponentModel; namespace PInvoke { public class Win32Api { #region enums public enum GetLastErrorEnum { ERROR_SUCCESS = 0, ERROR_INVALID_FUNCTION = 1, ERROR_HANDLE_EOF = 38, ERROR_INVALID_PARAMETER = 87, ERROR_JOURNAL_DELETE_IN_PROGRESS = 1178, ERROR_JOURNAL_NOT_ACTIVE = 1179, ERROR_JOURNAL_ENTRY_DELETED = 1181, ERROR_INVALID_USER_BUFFER = 1784 } public enum UsnJournalDeleteFlags { USN_DELETE_FLAG_DELETE = 1, USN_DELETE_FLAG_NOTIFY = 2 } #endregion #region constants public const UInt32 GENERIC_READ = 0x80000000; public const UInt32 GENERIC_WRITE = 0x40000000; public const UInt32 FILE_SHARE_READ = 0x00000001; public const UInt32 FILE_SHARE_WRITE = 0x00000002; public const UInt32 FILE_ATTRIBUTE_DIRECTORY = 0x00000010; public const UInt32 CREATE_NEW = 1; public const UInt32 CREATE_ALWAYS = 2; public const UInt32 OPEN_EXISTING = 3; public const UInt32 OPEN_ALWAYS = 4; public const UInt32 TRUNCATE_EXISTING = 5; public const UInt32 FILE_ATTRIBUTE_NORMAL = 0x80; public const UInt32 FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; public const Int32 INVALID_HANDLE_VALUE = -1; // CTL_CODE( DeviceType, Function, Method, Access ) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)) private const UInt32 FILE_DEVICE_FILE_SYSTEM = 0x00000009; private const UInt32 METHOD_NEITHER = 3; private const UInt32 METHOD_BUFFERED = 0; private const UInt32 FILE_ANY_ACCESS = 0; private const UInt32 FILE_SPECIAL_ACCESS = 0; private const UInt32 FILE_READ_ACCESS = 1; private const UInt32 FILE_WRITE_ACCESS = 2; public const UInt32 USN_REASON_DATA_OVERWRITE = 0x00000001; public const UInt32 USN_REASON_DATA_EXTEND = 0x00000002; public const UInt32 USN_REASON_DATA_TRUNCATION = 0x00000004; public const UInt32 USN_REASON_NAMED_DATA_OVERWRITE = 0x00000010; public const UInt32 USN_REASON_NAMED_DATA_EXTEND = 0x00000020; public const UInt32 USN_REASON_NAMED_DATA_TRUNCATION = 0x00000040; public const UInt32 USN_REASON_FILE_CREATE = 0x00000100; public const UInt32 USN_REASON_FILE_DELETE = 0x00000200; public const UInt32 USN_REASON_EA_CHANGE = 0x00000400; public const UInt32 USN_REASON_SECURITY_CHANGE = 0x00000800; public const UInt32 USN_REASON_RENAME_OLD_NAME = 0x00001000; public const UInt32 USN_REASON_RENAME_NEW_NAME = 0x00002000; public const UInt32 USN_REASON_INDEXABLE_CHANGE = 0x00004000; public const UInt32 USN_REASON_BASIC_INFO_CHANGE = 0x00008000; public const UInt32 USN_REASON_HARD_LINK_CHANGE = 0x00010000; public const UInt32 USN_REASON_COMPRESSION_CHANGE = 0x00020000; public const UInt32 USN_REASON_ENCRYPTION_CHANGE = 0x00040000; public const UInt32 USN_REASON_OBJECT_ID_CHANGE = 0x00080000; public const UInt32 USN_REASON_REPARSE_POINT_CHANGE = 0x00100000; public const UInt32 USN_REASON_STREAM_CHANGE = 0x00200000; public const UInt32 USN_REASON_CLOSE = 0x80000000; public static Int32 GWL_EXSTYLE = -20; public static Int32 WS_EX_LAYERED = 0x00080000; public static Int32 WS_EX_TRANSPARENT = 0x00000020; public const UInt32 FSCTL_GET_OBJECT_ID = 0x9009c; // FSCTL_ENUM_USN_DATA = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 44, METHOD_NEITHER, FILE_ANY_ACCESS) public const UInt32 FSCTL_ENUM_USN_DATA = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (44 << 2) | METHOD_NEITHER; // FSCTL_READ_USN_JOURNAL = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 46, METHOD_NEITHER, FILE_ANY_ACCESS) public const UInt32 FSCTL_READ_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (46 << 2) | METHOD_NEITHER; // FSCTL_CREATE_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 57, METHOD_NEITHER, FILE_ANY_ACCESS) public const UInt32 FSCTL_CREATE_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (57 << 2) | METHOD_NEITHER; // FSCTL_QUERY_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 61, METHOD_BUFFERED, FILE_ANY_ACCESS) public const UInt32 FSCTL_QUERY_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (61 << 2) | METHOD_BUFFERED; // FSCTL_DELETE_USN_JOURNAL CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 62, METHOD_BUFFERED, FILE_ANY_ACCESS) public const UInt32 FSCTL_DELETE_USN_JOURNAL = (FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (62 << 2) | METHOD_BUFFERED; #endregion #region dll imports /// <summary> /// Creates the file specified by 'lpFileName' with desired access, share mode, security attributes, /// creation disposition, flags and attributes. /// </summary> /// <param name="lpFileName">Fully qualified path to a file</param> /// <param name="dwDesiredAccess">Requested access (write, read, read/write, none)</param> /// <param name="dwShareMode">Share mode (read, write, read/write, delete, all, none)</param> /// <param name="lpSecurityAttributes">IntPtr to a 'SECURITY_ATTRIBUTES' structure</param> /// <param name="dwCreationDisposition">Action to take on file or device specified by 'lpFileName' (CREATE_NEW, /// CREATE_ALWAYS, OPEN_ALWAYS, OPEN_EXISTING, TRUNCATE_EXISTING)</param> /// <param name="dwFlagsAndAttributes">File or device attributes and flags (typically FILE_ATTRIBUTE_NORMAL)</param> /// <param name="hTemplateFile">IntPtr to a valid handle to a template file with 'GENERIC_READ' access right</param> /// <returns>IntPtr handle to the 'lpFileName' file or device or 'INVALID_HANDLE_VALUE'</returns> [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); /// <summary> /// Closes the file specified by the IntPtr 'hObject'. /// </summary> /// <param name="hObject">IntPtr handle to a file</param> /// <returns>'true' if successful, otherwise 'false'</returns> [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle( IntPtr hObject); /// <summary> /// Fills the 'BY_HANDLE_FILE_INFORMATION' structure for the file specified by 'hFile'. /// </summary> /// <param name="hFile">Fully qualified name of a file</param> /// <param name="lpFileInformation">Out BY_HANDLE_FILE_INFORMATION argument</param> /// <returns>'true' if successful, otherwise 'false'</returns> [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetFileInformationByHandle( IntPtr hFile, out BY_HANDLE_FILE_INFORMATION lpFileInformation); /// <summary> /// Deletes the file specified by 'fileName'. /// </summary> /// <param name="fileName">Fully qualified path to the file to delete</param> /// <returns>'true' if successful, otherwise 'false'</returns> [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeleteFile( string fileName); /// <summary> /// Read data from the file specified by 'hFile'. /// </summary> /// <param name="hFile">IntPtr handle to the file to read</param> /// <param name="lpBuffer">IntPtr to a buffer of bytes to receive the bytes read from 'hFile'</param> /// <param name="nNumberOfBytesToRead">Number of bytes to read from 'hFile'</param> /// <param name="lpNumberOfBytesRead">Number of bytes read from 'hFile'</param> /// <param name="lpOverlapped">IntPtr to an 'OVERLAPPED' structure</param> /// <returns>'true' if successful, otherwise 'false'</returns> [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool ReadFile( IntPtr hFile, IntPtr lpBuffer, uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, IntPtr lpOverlapped); /// <summary> /// Writes the /// </summary> /// <param name="hFile">IntPtr handle to the file to write</param> /// <param name="bytes">IntPtr to a buffer of bytes to write to 'hFile'</param> /// <param name="nNumberOfBytesToWrite">Number of bytes in 'lpBuffer' to write to 'hFile'</param> /// <param name="lpNumberOfBytesWritten">Number of bytes written to 'hFile'</param> /// <param name="overlapped">IntPtr to an 'OVERLAPPED' structure</param> /// <returns>'true' if successful, otherwise 'false'</returns> [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WriteFile( IntPtr hFile, IntPtr bytes, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, int overlapped); /// <summary> /// Writes the data in 'lpBuffer' to the file specified by 'hFile'. /// </summary> /// <param name="hFile">IntPtr handle to file to write</param> /// <param name="lpBuffer">Buffer of bytes to write to file 'hFile'</param> /// <param name="nNumberOfBytesToWrite">Number of bytes in 'lpBuffer' to write to 'hFile'</param> /// <param name="lpNumberOfBytesWritten">Number of bytes written to 'hFile'</param> /// <param name="overlapped">IntPtr to an 'OVERLAPPED' structure</param> /// <returns>'true' if successful, otherwise 'false'</returns> [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WriteFile( IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten, int overlapped); /// <summary> /// Sends the 'dwIoControlCode' to the device specified by 'hDevice'. /// </summary> /// <param name="hDevice">IntPtr handle to the device to receive 'dwIoControlCode'</param> /// <param name="dwIoControlCode">Device IO Control Code to send</param> /// <param name="lpInBuffer">Input buffer if required</param> /// <param name="nInBufferSize">Size of input buffer</param> /// <param name="lpOutBuffer">Output buffer if required</param> /// <param name="nOutBufferSize">Size of output buffer</param> /// <param name="lpBytesReturned">Number of bytes returned in output buffer</param> /// <param name="lpOverlapped">IntPtr to an 'OVERLAPPED' structure</param> /// <returns>'true' if successful, otherwise 'false'</returns> [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeviceIoControl( IntPtr hDevice, UInt32 dwIoControlCode, IntPtr lpInBuffer, Int32 nInBufferSize, out USN_JOURNAL_DATA lpOutBuffer, Int32 nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped); /// <summary> /// Sends the control code 'dwIoControlCode' to the device driver specified by 'hDevice'. /// </summary> /// <param name="hDevice">IntPtr handle to the device to receive 'dwIoControlCode</param> /// <param name="dwIoControlCode">Device IO Control Code to send</param> /// <param name="lpInBuffer">Input buffer if required</param> /// <param name="nInBufferSize">Size of input buffer </param> /// <param name="lpOutBuffer">Output buffer if required</param> /// <param name="nOutBufferSize">Size of output buffer</param> /// <param name="lpBytesReturned">Number of bytes returned</param> /// <param name="lpOverlapped">Pointer to an 'OVERLAPPED' struture</param> /// <returns></returns> [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool DeviceIoControl( IntPtr hDevice, UInt32 dwIoControlCode, IntPtr lpInBuffer, Int32 nInBufferSize, IntPtr lpOutBuffer, Int32 nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped); /// <summary> /// Sets the number of bytes specified by 'size' of the memory associated with the argument 'ptr' /// to zero. /// </summary> /// <param name="ptr"></param> /// <param name="size"></param> [DllImport("kernel32.dll")] public static extern void ZeroMemory(IntPtr ptr, int size); [DllImport("user32.dll", CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetCursorPos(out POINT pt); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern Int32 GetWindowLong(IntPtr hWnd, Int32 nIndex); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern Int32 SetWindowLong(IntPtr hWnd, Int32 nIndex, Int32 newVal); #endregion #region structures /// <summary> /// By Handle File Information structure, contains File Attributes(32bits), Creation Time(FILETIME), /// Last Access Time(FILETIME), Last Write Time(FILETIME), Volume Serial Number(32bits), /// File Size High(32bits), File Size Low(32bits), Number of Links(32bits), File Index High(32bits), /// File Index Low(32bits). /// </summary> [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct BY_HANDLE_FILE_INFORMATION { public uint FileAttributes; public FILETIME CreationTime; public FILETIME LastAccessTime; public FILETIME LastWriteTime; public uint VolumeSerialNumber; public uint FileSizeHigh; public uint FileSizeLow; public uint NumberOfLinks; public uint FileIndexHigh; public uint FileIndexLow; } /// <summary> /// USN Journal Data structure, contains USN Journal ID(64bits), First USN(64bits), Next USN(64bits), /// Lowest Valid USN(64bits), Max USN(64bits), Maximum Size(64bits) and Allocation Delta(64bits). /// </summary> [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct USN_JOURNAL_DATA { public UInt64 UsnJournalID; public Int64 FirstUsn; public Int64 NextUsn; public Int64 LowestValidUsn; public Int64 MaxUsn; public UInt64 MaximumSize; public UInt64 AllocationDelta; } /// <summary> /// MFT Enum Data structure, contains Start File Reference Number(64bits), Low USN(64bits), /// High USN(64bits). /// </summary> [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct MFT_ENUM_DATA { public UInt64 StartFileReferenceNumber; public Int64 LowUsn; public Int64 HighUsn; } /// <summary> /// Create USN Journal Data structure, contains Maximum Size(64bits) and Allocation Delta(64(bits). /// </summary> [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct CREATE_USN_JOURNAL_DATA { public UInt64 MaximumSize; public UInt64 AllocationDelta; } /// <summary> /// Create USN Journal Data structure, contains Maximum Size(64bits) and Allocation Delta(64(bits). /// </summary> [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct DELETE_USN_JOURNAL_DATA { public UInt64 UsnJournalID; public UInt32 DeleteFlags; public UInt32 Reserved; } /// <summary> /// Contains the USN Record Length(32bits), USN(64bits), File Reference Number(64bits), /// Parent File Reference Number(64bits), Reason Code(32bits), File Attributes(32bits), /// File Name Length(32bits), the File Name Offset(32bits) and the File Name. /// </summary> public class USN_RECORD { private const int FR_OFFSET = 8; private const int PFR_OFFSET = 16; private const int USN_OFFSET = 24; private const int REASON_OFFSET = 40; public const int FA_OFFSET = 52; private const int FNL_OFFSET = 56; private const int FN_OFFSET = 58; public UInt32 RecordLength; public UInt64 FileReferenceNumber; public UInt64 ParentFileReferenceNumber; public Int64 Usn; public UInt32 Reason; public UInt32 FileAttributes; public Int32 FileNameLength; public Int32 FileNameOffset; public string FileName = string.Empty; /// <summary> /// USN Record Constructor /// </summary> /// <param name="p">Buffer of bytes representing the USN Record</param> public USN_RECORD(IntPtr p) { this.RecordLength = (UInt32)Marshal.ReadInt32(p); this.FileReferenceNumber = (UInt64)Marshal.ReadInt64(p, FR_OFFSET); this.ParentFileReferenceNumber = (UInt64)Marshal.ReadInt64(p, PFR_OFFSET); this.Usn = Marshal.ReadInt64(p, USN_OFFSET); this.Reason = (UInt32)Marshal.ReadInt32(p, REASON_OFFSET); this.FileAttributes = (UInt32)Marshal.ReadInt32(p, FA_OFFSET); this.FileNameLength = Marshal.ReadInt16(p, FNL_OFFSET); this.FileNameOffset = Marshal.ReadInt16(p, FN_OFFSET); FileName = Marshal.PtrToStringUni(new IntPtr(p.ToInt32() + this.FileNameOffset), this.FileNameLength / sizeof(char)); } } /// <summary> /// Contains the Start USN(64bits), Reason Mask(32bits), Return Only on Close flag(32bits), /// Time Out(64bits), Bytes To Wait For(64bits), and USN Journal ID(64bits). /// </summary> [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct READ_USN_JOURNAL_DATA { public Int64 StartUsn; public UInt32 ReasonMask; public UInt32 ReturnOnlyOnClose; public UInt64 Timeout; public UInt64 bytesToWaitFor; public UInt64 UsnJournalId; } [StructLayout(LayoutKind.Sequential)] public struct POINT { public int X; public int Y; public POINT(int x, int y) { this.X = x; this.Y = y; } } #endregion #region functions /// <summary> /// Writes the data in 'text' to the alternate stream ':Description' of the file 'currentFile. /// </summary> /// <param name="currentfile">Fully qualified path to a file</param> /// <param name="text">Data to write to the ':Description' stream</param> public static void WriteAlternateStream(string currentfile, string text) { string AltStreamDesc = currentfile + ":Description"; IntPtr txtBuffer = IntPtr.Zero; IntPtr hFile = IntPtr.Zero; DeleteFile(AltStreamDesc); string descText = text.TrimEnd(' '); try { hFile = CreateFile(AltStreamDesc, GENERIC_WRITE, 0, IntPtr.Zero, CREATE_ALWAYS, 0, IntPtr.Zero); if (-1 != hFile.ToInt32()) { txtBuffer = Marshal.StringToHGlobalUni(descText); uint nBytes, count; nBytes = (uint)descText.Length; bool bRtn = WriteFile(hFile, txtBuffer, sizeof(char) * nBytes, out count, 0); if (!bRtn) { if ((sizeof(char) * nBytes) != count) { throw new Exception(string.Format("Bytes written {0} should be {1} for file {2}.", count, sizeof(char) * nBytes, AltStreamDesc)); } else { throw new Exception("WriteFile() returned false"); } } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } catch (Exception exception) { string msg = string.Format("Exception caught in WriteAlternateStream()\n '{0}'\n for file '{1}'.", exception.Message, AltStreamDesc); Console.WriteLine(msg); } finally { CloseHandle(hFile); hFile = IntPtr.Zero; Marshal.FreeHGlobal(txtBuffer); GC.Collect(); } } /// <summary> /// Adds the ':Description' alternate stream name to the argument 'currentFile'. /// </summary> /// <param name="currentfile">The file whose alternate stream is to be read</param> /// <returns>A string value representing the value of the alternate stream</returns> public static string ReadAlternateStream(string currentfile) { string AltStreamDesc = currentfile + ":Description"; string returnstring = ReadAlternateStreamEx(AltStreamDesc); return returnstring; } /// <summary> /// Reads the stream represented by 'currentFile'. /// </summary> /// <param name="currentfile">Fully qualified path including stream</param> /// <returns>Value of the alternate stream as a string</returns> public static string ReadAlternateStreamEx(string currentfile) { string returnstring = string.Empty; IntPtr hFile = IntPtr.Zero; IntPtr buffer = IntPtr.Zero; try { hFile = CreateFile(currentfile, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if (-1 != hFile.ToInt32()) { buffer = Marshal.AllocHGlobal(1000 * sizeof(char)); ZeroMemory(buffer, 1000 * sizeof(char)); uint nBytes; bool bRtn = ReadFile(hFile, buffer, 1000 * sizeof(char), out nBytes, IntPtr.Zero); if (bRtn) { if (nBytes > 0) { returnstring = Marshal.PtrToStringAuto(buffer); //byte[] byteBuffer = new byte[nBytes]; //for (int i = 0; i < nBytes; i++) //{ // byteBuffer[i] = Marshal.ReadByte(buffer, i); //} //returnstring = Encoding.Unicode.GetString(byteBuffer, 0, (int)nBytes); } else { throw new Exception("ReadFile() returned true but read zero bytes"); } } else { if (nBytes <= 0) { throw new Exception("ReadFile() read zero bytes."); } else { throw new Exception("ReadFile() returned false"); } } } else { Exception excptn = new Win32Exception(Marshal.GetLastWin32Error()); if (!excptn.Message.Contains("cannot find the file")) { throw excptn; } } } catch (Exception exception) { string msg = string.Format("Exception caught in ReadAlternateStream(), '{0}'\n for file '{1}'.", exception.Message, currentfile); Console.WriteLine(msg); Console.WriteLine(exception.Message); } finally { CloseHandle(hFile); hFile = IntPtr.Zero; if (buffer != IntPtr.Zero) { Marshal.FreeHGlobal(buffer); } GC.Collect(); } return returnstring; } /// <summary> /// Read the encrypted alternate stream specified by 'currentFile'. /// </summary> /// <param name="currentfile">Fully qualified path to encrypted alternate stream</param> /// <returns>The un-encrypted value of the alternate stream as a string</returns> public static string ReadAlternateStreamEncrypted(string currentfile) { string returnstring = string.Empty; IntPtr buffer = IntPtr.Zero; IntPtr hFile = IntPtr.Zero; try { hFile = CreateFile(currentfile, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); if (-1 != hFile.ToInt32()) { buffer = Marshal.AllocHGlobal(1000 * sizeof(char)); ZeroMemory(buffer, 1000 * sizeof(char)); uint nBytes; bool bRtn = ReadFile(hFile, buffer, 1000 * sizeof(char), out nBytes, IntPtr.Zero); if (0 != nBytes) { returnstring = DecryptLicenseString(buffer, nBytes); } } else { Exception excptn = new Win32Exception(Marshal.GetLastWin32Error()); if (!excptn.Message.Contains("cannot find the file")) { throw excptn; } } } catch (Exception exception) { Console.WriteLine("Exception caught in ReadAlternateStreamEncrypted()"); Console.WriteLine(exception.Message); } finally { CloseHandle(hFile); hFile = IntPtr.Zero; if (buffer != IntPtr.Zero) { Marshal.FreeHGlobal(buffer); } GC.Collect(); } return returnstring; } /// <summary> /// Writes the value of 'LicenseString' as an encrypted stream to the file:stream specified /// by 'currentFile'. /// </summary> /// <param name="currentFile">Fully qualified path to the alternate stream</param> /// <param name="LicenseString">The string value to encrypt and write to the alternate stream</param> public static void WriteAlternateStreamEncrypted(string currentFile, string LicenseString) { RC2CryptoServiceProvider rc2 = null; CryptoStream cs = null; MemoryStream ms = null; uint count = 0; IntPtr buffer = IntPtr.Zero; IntPtr hFile = IntPtr.Zero; try { Encoding enc = Encoding.Unicode; byte[] ba = enc.GetBytes(LicenseString); ms = new MemoryStream(); rc2 = new RC2CryptoServiceProvider(); rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0"); rc2.IV = GetBytesFromHexString("827d961224d99b2d"); cs = new CryptoStream(ms, rc2.CreateEncryptor(), CryptoStreamMode.Write); cs.Write(ba, 0, ba.Length); cs.FlushFinalBlock(); buffer = Marshal.AllocHGlobal(1000 * sizeof(char)); ZeroMemory(buffer, 1000 * sizeof(char)); uint nBytes = (uint)ms.Length; Marshal.Copy(ms.GetBuffer(), 0, buffer, (int)nBytes); DeleteFile(currentFile); hFile = CreateFile(currentFile, GENERIC_WRITE, 0, IntPtr.Zero, CREATE_ALWAYS, 0, IntPtr.Zero); if (-1 != hFile.ToInt32()) { bool bRtn = WriteFile(hFile, buffer, nBytes, out count, 0); } else { Exception excptn = new Win32Exception(Marshal.GetLastWin32Error()); if (!excptn.Message.Contains("cannot find the file")) { throw excptn; } } } catch (Exception exception) { Console.WriteLine("WriteAlternateStreamEncrypted()"); Console.WriteLine(exception.Message); } finally { CloseHandle(hFile); hFile = IntPtr.Zero; if (cs != null) { cs.Close(); cs.Dispose(); } rc2 = null; if (ms != null) { ms.Close(); ms.Dispose(); } if (buffer != IntPtr.Zero) { Marshal.FreeHGlobal(buffer); } } } /// <summary> /// Encrypt the string 'LicenseString' argument and return as a MemoryStream. /// </summary> /// <param name="LicenseString">The string value to encrypt</param> /// <returns>A MemoryStream which contains the encrypted value of 'LicenseString'</returns> private static MemoryStream EncryptLicenseString(string LicenseString) { Encoding enc = Encoding.Unicode; byte[] ba = enc.GetBytes(LicenseString); MemoryStream ms = new MemoryStream(); RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider(); rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0"); rc2.IV = GetBytesFromHexString("827d961224d99b2d"); CryptoStream cs = new CryptoStream(ms, rc2.CreateEncryptor(), CryptoStreamMode.Write); cs.Write(ba, 0, ba.Length); cs.Close(); cs.Dispose(); rc2 = null; return ms; } /// <summary> /// Given an IntPtr to a bufer and the number of bytes, decrypt the buffer and return an /// unencrypted text string. /// </summary> /// <param name="buffer">An IntPtr to the 'buffer' containing the encrypted string</param> /// <param name="nBytes">The number of bytes in 'buffer' to decrypt</param> /// <returns></returns> private static string DecryptLicenseString(IntPtr buffer, uint nBytes) { byte[] ba = new byte[nBytes]; for( int i=0; i<nBytes; i++) { ba[i] = Marshal.ReadByte(buffer, i); } MemoryStream ms = new MemoryStream(ba); RC2CryptoServiceProvider rc2 = new RC2CryptoServiceProvider(); rc2.Key = GetBytesFromHexString("7a6823a42a3a3ae27057c647db812d0"); rc2.IV = GetBytesFromHexString("827d961224d99b2d"); CryptoStream cs = new CryptoStream(ms, rc2.CreateDecryptor(), CryptoStreamMode.Read); string licenseString = string.Empty; byte[] ba1 = new byte[4096]; int irtn = cs.Read(ba1, 0, 4096); Encoding enc = Encoding.Unicode; licenseString = enc.GetString(ba1, 0, irtn); cs.Close(); cs.Dispose(); ms.Close(); ms.Dispose(); rc2 = null; return licenseString; } /// <summary> /// Gets the byte array generated from the value of 'hexString'. /// </summary> /// <param name="hexString">Hexadecimal string</param> /// <returns>Array of bytes generated from 'hexString'.</returns> public static byte[] GetBytesFromHexString(string hexString) { int numHexChars = hexString.Length / 2; byte[] ba = new byte[numHexChars]; int j = 0; for (int i = 0; i < ba.Length; i++) { string hex = new string(new char[] { hexString[j], hexString[j + 1] }); ba[i] = byte.Parse(hex, System.Globalization.NumberStyles.HexNumber); j = j + 2; } return ba; } #endregion } }
Next the FileNameAndParentFrn class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PInvoke;
namespace ConsoleUSNJournalProject
{
[Serializable]
public class FileNameAndParentFrn : IEquatable<FileNameAndParentFrn>
{
#region Properties
private uint _volSer;
public uint VolSer
{
get { return _volSer; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private UInt64 _frn;
public UInt64 Frn
{
get { return _frn; }
set { _frn = value; }
}
private UInt64 _parentFrn;
public UInt64 ParentFrn
{
get { return _parentFrn; }
set { _parentFrn = value; }
}
private byte[] _md5;
public byte[] MD5
{
get { return _md5; }
set { _md5 = value; }
}
#endregion
#region Constructor(s)
public FileNameAndParentFrn(uint volser, string name, UInt64 frn, UInt64 parentFrn)
{
if (!string.IsNullOrEmpty(name))
{
_name = name;
}
else
{
throw new ArgumentException("Invalid argument: null or Length = zero", "name");
}
_volSer = volser;
_parentFrn = parentFrn;
_frn = frn;
_md5 = null;
} // end FileNameAndParentFrn() closing bracket
public FileNameAndParentFrn(uint volser, ulong frn)
{
_volSer = volser;
_frn = frn;
}
public FileNameAndParentFrn(uint volser, Win32Api.USN_RECORD usn)
{
if (!string.IsNullOrEmpty(usn.FileName))
{
_name = usn.FileName;
}
else
{
throw new ArgumentException("Invalid argument: null or Length = zero", "name");
}
_volSer = volser;
_parentFrn = usn.ParentFileReferenceNumber;
_frn = usn.FileReferenceNumber;
_md5 = null;
} // end FileNameAndParentFrn() closing bracket
#endregion
#region IEquatable<FileNameAndParentFrn> Members
public bool Equals(FileNameAndParentFrn other)
{
bool retval = false;
if ((object)other != null)
{
if (_frn == other._frn && _volSer == other.VolSer)
retval = true;
}
return retval;
}
public override bool Equals(object obj)
{
if (obj == null) return base.Equals(obj);
if (!(obj is FileNameAndParentFrn))
{
throw new InvalidCastException("Argument is not a 'FileNameAndParentFrn' type object");
}
return base.Equals(obj);
}
public override int GetHashCode()
{
return this._frn.GetHashCode();
}
public static bool operator ==(FileNameAndParentFrn fnapfrn1, FileNameAndParentFrn fnapfrn2)
{
return fnapfrn1.Equals(fnapfrn2);
}
public static bool operator !=(FileNameAndParentFrn fnapfrn1, FileNameAndParentFrn fnapfrn2)
{
return (!fnapfrn1.Equals(fnapfrn2));
}
#endregion
}
}
Still not enough room. The rest of the code is in another reply.
StCroixSkipper