using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Text; using System.Threading; namespace BurnOutSharp { public static class Utilities { /// /// Search for a byte array in another array /// public static bool Contains(this byte[] stack, byte[] needle, out int position, int start = 0, int end = -1) { // Initialize the found position to -1 position = -1; // If either array is null or empty, we can't do anything if (stack == null || stack.Length == 0 || needle == null || needle.Length == 0) return false; // If the needle array is larger than the stack array, it can't be contained within if (needle.Length > stack.Length) return false; // If start or end are not set properly, set them to defaults if (start < 0) start = 0; if (end < 0) end = stack.Length - needle.Length; for (int i = start; i < end; i++) { if (stack.EqualAt(needle, i)) { position = i; return true; } } return false; } /// /// See if a byte array starts with another /// public static bool StartsWith(this byte[] stack, byte[] needle) { return stack.Contains(needle, out int _, start: 0, end: 1); } /// /// Get if a stack at a certain index is equal to a needle /// private static bool EqualAt(this byte[] stack, byte[] needle, int index) { // If we're too close to the end of the stack, return false if (needle.Length >= stack.Length - index) return false; for (int i = 0; i < needle.Length; i++) { if (stack[i + index] != needle[i]) return false; } return true; } /// /// Get the file version as reported by the filesystem /// public static string GetFileVersion(string file) { if (file == null || !File.Exists(file)) return string.Empty; FileVersionInfo fvinfo = FileVersionInfo.GetVersionInfo(file); if (fvinfo.FileVersion == null) return ""; if (fvinfo.FileVersion != "") return fvinfo.FileVersion.Replace(", ", "."); else return fvinfo.ProductVersion.Replace(", ", "."); } /// /// Get the filesystem name for the given drive letter /// /// /// http://pinvoke.net/default.aspx/kernel32/GetVolumeInformation.html /// public static string GetFileSystemName(char driveLetter) { string fsName = null; StringBuilder volname = new StringBuilder(261); StringBuilder fsname = new StringBuilder(261); if (GetVolumeInformation($"{driveLetter}:\\", volname, volname.Capacity, out uint sernum, out uint maxlen, out FileSystemFeature flags, fsname, fsname.Capacity)) { // Now you know the file system of your drive // NTFS or FAT16 or UDF for instance fsName = fsname.ToString(); } return fsName; } #region P/Invoke // https://stackoverflow.com/questions/8819188/c-sharp-classes-to-undelete-files/8820157#8820157 // Move Method public const uint FileBegin = 0; public const uint FileCurrent = 1; public const uint FileEnd = 2; // Handle Constants public const uint INVALID_HANDLE_VALUE = 0; public const int IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080; [DllImport("kernel32.dll", SetLastError = true)] public static extern bool CloseHandle(IntPtr handle); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CreateFile( [MarshalAs(UnmanagedType.LPTStr)] string filename, [MarshalAs(UnmanagedType.U4)] FileAccess access, [MarshalAs(UnmanagedType.U4)] FileShare share, IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, [MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes, IntPtr templateFile); [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public extern static bool GetVolumeInformation( string rootPathName, StringBuilder volumeNameBuffer, int volumeNameSize, out uint volumeSerialNumber, out uint maximumComponentLength, out FileSystemFeature fileSystemFlags, StringBuilder fileSystemNameBuffer, int nFileSystemNameSize); [DllImport("Kernel32.dll", SetLastError = true)] public extern static bool DeviceIoControl( IntPtr hDevice, uint IoControlCode, IntPtr InMediaRemoval, uint InBufferSize, IntPtr OutBuffer, int OutBufferSize, out int BytesReturned, IntPtr Overlapped); // Used to read in a file [DllImport("kernel32.dll")] public static extern bool ReadFile( IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToRead, ref uint lpNumberOfBytesRead, IntPtr lpOverlapped); [DllImport("kernel32.dll")] public static extern bool ReadFileEx( IntPtr hFile, [Out] byte[] lpBuffer, uint nNumberOfBytesToRead, [In] ref NativeOverlapped lpOverlapped, IOCompletionCallback lpCompletionRoutine); // Used to set the offset in file to start reading [DllImport("kernel32.dll")] public static extern bool SetFilePointerEx( IntPtr hFile, long liDistanceToMove, ref IntPtr lpNewFilePointer, uint dwMoveMethod); [StructLayout(LayoutKind.Sequential)] struct STORAGE_DEVICE_NUMBER { public int DeviceType; public int DeviceNumber; public int PartitionNumber; } public enum MEDIA_TYPE : uint { Unknown, F5_1Pt2_512, F3_1Pt44_512, F3_2Pt88_512, F3_20Pt8_512, F3_720_512, F5_360_512, F5_320_512, F5_320_1024, F5_180_512, F5_160_512, RemovableMedia, FixedMedia, F3_120M_512, F3_640_512, F5_640_512, F5_720_512, F3_1Pt2_512, F3_1Pt23_1024, F5_1Pt23_1024, F3_128Mb_512, F3_230Mb_512, F8_256_128, F3_200Mb_512, F3_240M_512, F3_32M_512 } [StructLayout(LayoutKind.Sequential)] public struct DISK_GEOMETRY { public long Cylinders; public MEDIA_TYPE MediaType; public int TracksPerCylinder; public int SectorsPerTrack; public int BytesPerSector; public long DiskSize { get { return Cylinders * (long)TracksPerCylinder * (long)SectorsPerTrack * (long)BytesPerSector; } } } [Flags] public enum FileSystemFeature : uint { /// /// The file system preserves the case of file names when it places a name on disk. /// CasePreservedNames = 2, /// /// The file system supports case-sensitive file names. /// CaseSensitiveSearch = 1, /// /// The specified volume is a direct access (DAX) volume. This flag was introduced in Windows 10, version 1607. /// DaxVolume = 0x20000000, /// /// The file system supports file-based compression. /// FileCompression = 0x10, /// /// The file system supports named streams. /// NamedStreams = 0x40000, /// /// The file system preserves and enforces access control lists (ACL). /// PersistentACLS = 8, /// /// The specified volume is read-only. /// ReadOnlyVolume = 0x80000, /// /// The volume supports a single sequential write. /// SequentialWriteOnce = 0x100000, /// /// The file system supports the Encrypted File System (EFS). /// SupportsEncryption = 0x20000, /// /// The specified volume supports extended attributes. An extended attribute is a piece of /// application-specific metadata that an application can associate with a file and is not part /// of the file's data. /// SupportsExtendedAttributes = 0x00800000, /// /// The specified volume supports hard links. For more information, see Hard Links and Junctions. /// SupportsHardLinks = 0x00400000, /// /// The file system supports object identifiers. /// SupportsObjectIDs = 0x10000, /// /// The file system supports open by FileID. For more information, see FILE_ID_BOTH_DIR_INFO. /// SupportsOpenByFileId = 0x01000000, /// /// The file system supports re-parse points. /// SupportsReparsePoints = 0x80, /// /// The file system supports sparse files. /// SupportsSparseFiles = 0x40, /// /// The volume supports transactions. /// SupportsTransactions = 0x200000, /// /// The specified volume supports update sequence number (USN) journals. For more information, /// see Change Journal Records. /// SupportsUsnJournal = 0x02000000, /// /// The file system supports Unicode in file names as they appear on disk. /// UnicodeOnDisk = 4, /// /// The specified volume is a compressed volume, for example, a DoubleSpace volume. /// VolumeIsCompressed = 0x8000, /// /// The file system supports disk quotas. /// VolumeQuotas = 0x20 } #endregion } }