/* * Process Hacker - * misc. functions * * Copyright (C) 2008-2009 wj32 * * This file is part of Process Hacker. * * Process Hacker is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Process Hacker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Process Hacker. If not, see . */ using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Reflection; using System.Text; using System.Windows.Forms; namespace ProcessHacker.Common { /// /// Provides methods for manipulating various types of data. /// public static class Utils { public enum Endianness { Little, Big } #region Constants public static int[] Primes = { 3, 7, 11, 0x11, 0x17, 0x1d, 0x25, 0x2f, 0x3b, 0x47, 0x59, 0x6b, 0x83, 0xa3, 0xc5, 0xef, 0x125, 0x161, 0x1af, 0x209, 0x277, 0x2f9, 0x397, 0x44f, 0x52f, 0x63d, 0x78b, 0x91d, 0xaf1, 0xd2b, 0xfd1, 0x12fd, 0x16cf, 0x1b65, 0x20e3, 0x2777, 0x2f6f, 0x38ff, 0x446f, 0x521f, 0x628d, 0x7655, 0x8e01, 0xaa6b, 0xcc89, 0xf583, 0x126a7, 0x1619b, 0x1a857, 0x1fd3b, 0x26315, 0x2dd67, 0x3701b, 0x42023, 0x4f361, 0x5f0ed, 0x72125, 0x88e31, 0xa443b, 0xc51eb, 0xec8c1, 0x11bdbf, 0x154a3f, 0x198c4f, 0x1ea867, 0x24ca19, 0x2c25c1, 0x34fa1b, 0x3f928f, 0x4c4987, 0x5b8b6f, 0x6dda89 }; public static string[] SizeUnitNames = { "B", "kB", "MB", "GB", "TB", "PB", "EB" }; #endregion /// /// The maximum unit specifier to use when formatting sizes. /// public static int UnitSpecifier = 4; /// /// Flattens an array of arrays into a single array. /// /// The type of each element in the arrays. /// /// An array of arrays. If an array in the array is null, it will be ignored. /// /// An array containing elements from each array. public static T[] Concat(params T[][] ap) { int tl = 0; foreach (var array in ap) if (array != null) tl += array.Length; T[] na = new T[tl]; int i = 0; foreach (var array in ap) { if (array != null) { Array.Copy(array, 0, na, i, array.Length); i += array.Length; } } return na; } /// /// Determines whether the specified value is contained /// within an array. /// /// The type of the array. /// The array to search. /// The value to search for. /// True if the array contains the value, otherwise false. public static bool Contains(this T[] array, T value) { return Array.IndexOf(array, value) != -1; } /// /// Counts the number of bits in the specified number. /// /// The number to process. /// The number of bits in the specified number. public static int CountBits(this int value) { int count = 0; while (value != 0) { count++; value &= value - 1; } return count; } /// /// Counts the number of bits in the specified number. /// /// The number to process. /// The number of bits in the specified number. public static int CountBits(this long value) { int count = 0; while (value != 0) { count++; value &= value - 1; } return count; } /// /// Creates an array of bytes from the specified byte pointer. /// /// A pointer to an array of bytes. /// The length of the array. /// A new byte array. public unsafe static byte[] Create(byte* ptr, int length) { byte[] array = new byte[length]; for (int i = 0; i < length; i++) array[i] = ptr[i]; return array; } /// /// Adds an ellipsis to a string if it is longer than the specified length. /// /// The string. /// The maximum length. /// The modified string. public static string CreateEllipsis(string s, int len) { if (s.Length <= len) return s; else return s.Substring(0, len - 4) + " ..."; } /// /// Creates a string containing random uppercase characters. /// /// The number of characters to generate. /// The generated string. public static string CreateRandomString(int length) { Random r = new Random((int)(DateTime.Now.ToFileTime() & 0xffffffff)); StringBuilder sb = new StringBuilder(length); for (int i = 0; i < length; i++) sb.Append((char)('A' + r.Next(25))); return sb.ToString(); } /// /// Clears and cleans up resources held by the menu items. /// public static void DisposeAndClear(this Menu.MenuItemCollection items) { //foreach (MenuItem item in items) //{ // item.Dispose(); //} items.Clear(); } /// /// Disables the menu items contained in the specified menu. /// /// The menu. public static void DisableAllMenuItems(Menu menu) { foreach (MenuItem item in menu.MenuItems) item.Enabled = false; } /// /// Disables all menu items. /// public static void DisableAll(this Menu menu) { DisableAllMenuItems(menu); } /// /// Performs a divide operation, rounding up. /// /// /// The positive number to divide. The result is undefined if the dividend /// is negative or zero. /// /// /// The positive number to divide by. The result is undefined if the divisor /// is negative or zero. /// /// A rounded-up quotient. public static int DivideUp(int dividend, int divisor) { return (dividend - 1) / divisor + 1; } /// /// Performs an action on a control after its handle has been created. /// If the control's handle has already been created, the action is /// executed immediately. /// /// The control is execute the action on. /// The action to execute. public static void DoDelayed(this Control control, Action action) { if (control.IsHandleCreated) { action(control); } else { LayoutEventHandler handler = null; handler = (sender, e) => { if (control.IsHandleCreated) { control.Layout -= handler; action(control); } }; control.Layout += handler; } } /// /// Duplicates the specified array. /// /// The type of array to duplicate. /// The array to duplicate. /// A copy of the specified array. public static T[] Duplicate(this T[] array) { T[] newArray = new T[array.Length]; array.CopyTo(newArray, 0); return newArray; } /// /// Enables the menu items contained in the specified menu. /// /// The menu. public static void EnableAllMenuItems(Menu menu) { foreach (MenuItem item in menu.MenuItems) item.Enabled = true; } /// /// Enables all menu items. /// public static void EnableAll(this Menu menu) { EnableAllMenuItems(menu); } /// /// Compares two arrays and determines whether they are equal. /// /// The type of each element in the arrays. /// The first array. /// The second array. /// Whether the two arrays are considered to be equal. public static bool Equals(this T[] array, T[] other) { return Equals(array, other, 0); } /// /// Compares two arrays and determines whether they are equal. /// /// The type of each element in the arrays. /// The first array. /// The second array. /// The index from which to begin comparing. /// Whether the two arrays are considered to be equal. public static bool Equals(this T[] array, T[] other, int startIndex) { return Equals(array, other, startIndex, array.Length); } /// /// Compares two arrays and determines whether they are equal. /// /// The type of each element in the arrays. /// The first array. /// The second array. /// The index from which to begin comparing. /// The number of elements to compare. /// Whether the two arrays are considered to be equal. public static bool Equals(this T[] array, T[] other, int startIndex, int length) { for (int i = startIndex; i < startIndex + length; i++) if (!array[i].Equals(other[i])) return false; return true; } /// /// Escapes a string using C-style escaping. /// /// The string to escape. /// The escaped string. public static string Escape(this string str) { str = str.Replace("\\", "\\\\"); str = str.Replace("\"", "\\\""); return str; } public static void Fill(this T[] array, T value) { for (int i = 0; i < array.Length; i++) array[i] = value; } /// /// Fills a combobox with enum value names. /// /// The combobox to modify. /// The type of the enum. public static void Fill(this ComboBox box, Type t) { foreach (string s in Enum.GetNames(t)) box.Items.Add(s); } /// /// Moves the specified rectangle to fit inside the working area /// of the display containing the specified control. /// /// The rectangle to process. /// The control from which to get the display. /// A new rectangle with its location modified. public static Rectangle FitRectangle(Rectangle rect, Control c) { return FitRectangle(rect, Screen.GetWorkingArea(c)); } /// /// Moves the specified rectangle to fit inside the specified bounds. /// /// The rectangle to process. /// The bounds in which the rectangle should be. /// A new rectangle with its location modified. public static Rectangle FitRectangle(Rectangle rect, Rectangle bounds) { if (rect.X < bounds.Left) rect.X = bounds.Left; if (rect.Y < bounds.Top) rect.Y = bounds.Top; if (rect.X + rect.Width > bounds.Width) rect.X = bounds.Width - rect.Width; if (rect.Y + rect.Height > bounds.Height) rect.Y = bounds.Height - rect.Height; return rect; } /// /// Gets a string representation for an address. /// /// An address. /// A string representation of the specified address. public static string FormatAddress(int address) { return "0x" + address.ToString("x"); } /// /// Gets a string representation for an address. /// /// An address. /// A string representation of the specified address. public static string FormatAddress(uint address) { return "0x" + address.ToString("x"); } /// /// Gets a string representation for an address. /// /// An address. /// A string representation of the specified address. public static string FormatAddress(long address) { return "0x" + address.ToString("x"); } /// /// Gets a string representation for an address. /// /// An address. /// A string representation of the specified address. public static string FormatAddress(ulong address) { return "0x" + address.ToString("x"); } /// /// Gets a string representation for an address. /// /// An address. /// A string representation of the specified address. public static string FormatAddress(IntPtr address) { return "0x" + address.ToString("x"); } public static string FormatFlags(Type e, long value) { string r = ""; for (int i = 0; i < 32; i++) { long fv = 1 << i; if ((value & fv) == fv) { r += Enum.GetName(e, fv) + ", "; } } if (r.EndsWith(", ")) r = r.Remove(r.Length - 2, 2); return r; } /// /// Formats a object into a string representation. /// /// The to format. /// public static string FormatLongTimeSpan(TimeSpan time) { return String.Format( "{0}{1:d2}:{2:d2}:{3:d2}", time.Days != 0 ? (time.Days.ToString() + ".") : "", time.Hours, time.Minutes, time.Seconds ); } /// /// Gets the relative time in nice English. /// /// A DateTime. /// A string. public static string FormatRelativeDateTime(DateTime time) { // Get the time span from the time to now. TimeSpan span = DateTime.Now.Subtract(time); // The partial number of weeks. double weeks = span.TotalDays / 7; // The partial number of fortnights. double fortnights = weeks / 2; // ... double months = span.TotalDays * 12 / 365; double years = months / 12; double centuries = years / 100; string str = ""; // Start from the most general time unit and see if they can be used // without any fractional component. // x centur(y|ies) if (centuries >= 1) str = (int)centuries + " " + ((int)centuries == 1 ? "century" : "centuries"); // x year(s) else if (years >= 1) str = (int)years + " " + ((int)years == 1 ? "year" : "years"); // x month(s) else if (months >= 1) str = (int)months + " " + ((int)months == 1 ? "month" : "months"); // x fortnight(s) else if (fortnights >= 1) str = (int)fortnights + " " + ((int)fortnights == 1 ? "fortnight" : "fortnights"); // x week(s) else if (weeks >= 1) str = (int)weeks + " " + ((int)weeks == 1 ? "week" : "weeks"); // x day(s) (and y hour(s)) else if (span.TotalDays >= 1) { str = (int)span.TotalDays + " " + ((int)span.TotalDays == 1 ? "day" : "days"); if (span.Hours >= 1) str += " and " + span.Hours + " " + (span.Hours == 1 ? "hour" : "hours"); } // x hour(s) (and y minute(s)) else if (span.Hours >= 1) { str = span.Hours + " " + (span.Hours == 1 ? "hour" : "hours"); if (span.Minutes >= 1) str += " and " + span.Minutes + " " + (span.Minutes == 1 ? "minute" : "minutes"); } // x minute(s) (and y second(s)) else if (span.Minutes >= 1) { str = span.Minutes + " " + (span.Minutes == 1 ? "minute" : "minutes"); if (span.Seconds >= 1) str += " and " + span.Seconds + " " + (span.Seconds == 1 ? "second" : "seconds"); } // x second(s) else if (span.Seconds >= 1) str = span.Seconds + " " + (span.Seconds == 1 ? "second" : "seconds"); // x millisecond(s) else if (span.Milliseconds >= 1) str = span.Milliseconds + " " + (span.Milliseconds == 1 ? "millisecond" : "milliseconds"); else str = "a very short time"; // Turn 1 into "a", e.g. 1 minute -> a minute if (str.StartsWith("1 ")) { // Special vowel case: a hour -> an hour if (str[2] != 'h') str = "a " + str.Substring(2); else str = "an " + str.Substring(2); } return str + " ago"; } /// /// Formats a size into a string representation, postfixing it with the correct unit. /// /// The size to format. public static string FormatSize(int size) { return FormatSize((uint)size); } /// /// Formats a size into a string representation, postfixing it with the correct unit. /// /// The size to format. public static string FormatSize(uint size) { int i = 0; double s = (double)size; while (s > 1024 && i < SizeUnitNames.Length && i < UnitSpecifier) { s /= 1024; i++; } return (s == 0 ? "0" : s.ToString("#,#.##")) + " " + SizeUnitNames[i]; } /// /// Formats a size into a string representation, postfixing it with the correct unit. /// /// The size to format. public static string FormatSize(IntPtr size) { unchecked { return FormatSize((ulong)size.ToInt64()); } } /// /// Formats a size into a string representation, postfixing it with the correct unit. /// /// The size to format. public static string FormatSize(long size) { return FormatSize((ulong)size); } /// /// Formats a size into a string representation, postfixing it with the correct unit. /// /// The size to format. public static string FormatSize(ulong size) { int i = 0; double s = (double)size; while (s > 1024 && i < SizeUnitNames.Length && i < UnitSpecifier) { s /= 1024; i++; } return (s == 0 ? "0" : s.ToString("#,#.##")) + " " + SizeUnitNames[i]; } /// /// Formats a object into a string representation. /// /// The to format. /// public static string FormatTimeSpan(TimeSpan time) { return String.Format("{0:d2}:{1:d2}:{2:d2}.{3:d3}", time.Hours, time.Minutes, time.Seconds, time.Milliseconds); } // // Gets a System.DateTime indicating the time the specified assembly was last built. // This will attempt to calculate the time from the build number, if possible. // Otherwise, the last write time of the assembly will be used. // // The assembly to get the build date for. // True to always use the last write time of the assembly, otherwise false. // The time this assembly was built. public static DateTime GetAssemblyBuildDate(Assembly assembly, bool forceFileDate) { Version AssemblyVersion = assembly.GetName().Version; DateTime dt; if (forceFileDate) { dt = GetAssemblyLastWriteTime(assembly); } else { dt = DateTime.Parse("01/01/2000").AddDays(AssemblyVersion.Build).AddSeconds(AssemblyVersion.Revision * 2); if (TimeZone.IsDaylightSavingTime(dt, TimeZone.CurrentTimeZone.GetDaylightChanges(dt.Year))) { dt = dt.AddHours(1); } if (dt > DateTime.Now || AssemblyVersion.Build < 730 || AssemblyVersion.Revision == 0) { dt = GetAssemblyLastWriteTime(assembly); } } return dt; } // // Returns the last write time of the specified assembly. // // The last write time of the assembly, or DateTime.MaxValue if an exception occurred. public static DateTime GetAssemblyLastWriteTime(Assembly assembly) { if (assembly.Location == null || assembly.Location == "") return DateTime.MaxValue; try { return File.GetLastWriteTime(assembly.Location); } catch { return DateTime.MaxValue; } } public static byte[] GetBytes(this int n) { return n.GetBytes(Endianness.Little); } public static byte[] GetBytes(this int n, Endianness type) { byte[] data = new byte[4]; if (type == Endianness.Little) { data[0] = (byte)(n & 0xff); data[1] = (byte)((n >> 8) & 0xff); data[2] = (byte)((n >> 16) & 0xff); data[3] = (byte)((n >> 24) & 0xff); } else if (type == Endianness.Big) { data[0] = (byte)((n >> 24) & 0xff); data[1] = (byte)((n >> 16) & 0xff); data[2] = (byte)((n >> 8) & 0xff); data[3] = (byte)(n & 0xff); } else { throw new ArgumentException(); } return data; } public static byte[] GetBytes(this uint n) { return n.GetBytes(Endianness.Little); } public static byte[] GetBytes(this uint n, Endianness type) { byte[] data = new byte[4]; if (type == Endianness.Little) { data[0] = (byte)(n & 0xff); data[1] = (byte)((n >> 8) & 0xff); data[2] = (byte)((n >> 16) & 0xff); data[3] = (byte)((n >> 24) & 0xff); } else if (type == Endianness.Big) { data[0] = (byte)((n >> 24) & 0xff); data[1] = (byte)((n >> 16) & 0xff); data[2] = (byte)((n >> 8) & 0xff); data[3] = (byte)(n & 0xff); } else { throw new ArgumentException(); } return data; } public static byte[] GetBytes(this ushort n) { return n.GetBytes(Endianness.Little); } public static byte[] GetBytes(this ushort n, Endianness type) { byte[] data = new byte[2]; if (type == Endianness.Little) { data[0] = (byte)(n & 0xff); data[1] = (byte)((n >> 8) & 0xff); } else if (type == Endianness.Big) { data[0] = (byte)((n >> 8) & 0xff); data[1] = (byte)(n & 0xff); } else { throw new ArgumentException(); } return data; } /// /// Converts a 32-bit Unix time value into a DateTime object. /// /// The Unix time value. public static DateTime GetDateTimeFromUnixTime(uint time) { return (new DateTime(1970, 1, 1, 0, 0, 0)).Add(new TimeSpan(0, 0, 0, (int)time)); } public static int GetPrime(int minimum) { if (minimum < 0) throw new ArgumentOutOfRangeException("minimum"); for (int i = 0; i < Primes.Length; i++) { if (Primes[i] >= minimum) return Primes[i]; } for (int i = minimum | 1; i < int.MaxValue; i += 2) { if (IsPrime(i)) return i; } return minimum; } /// /// Parses a string and produces a rectangle. /// /// /// A string describing a rectangle in the following format: /// x,y,width,height (with no spaces). /// /// A rectangle. public static Rectangle GetRectangle(string s) { var split = s.Split(','); return new Rectangle(int.Parse(split[0]), int.Parse(split[1]), int.Parse(split[2]), int.Parse(split[3])); } /// /// Returns a object of the specified thread ID. /// /// The process which the thread belongs to. /// The ID of the thread. /// public static System.Diagnostics.ProcessThread GetThreadFromId(System.Diagnostics.Process p, int id) { foreach (System.Diagnostics.ProcessThread t in p.Threads) if (t.Id == id) return t; return null; } /// /// Determines whether the array is empty (all 0's). /// /// The array to search. /// True if the array is empty; otherwise false. public static bool IsEmpty(this byte[] array) { foreach (byte b in array) { if (b != 0) return false; } return true; } public static bool IsPrime(this int number) { int x; // Is the number even? if ((number & 1) == 0) return number == 2; x = (int)Math.Sqrt(number); for (int i = 3; i <= x; i += 2) { if ((number % i) == 0) return false; } return true; } /// /// Makes a character printable by converting unprintable characters to a dot ('.'). /// /// The character to convert. /// public static char MakePrintable(char c) { if (c >= ' ' && c <= '~') return c; else return '.'; } /// /// Makes a string printable by converting unprintable characters to a dot ('.'). /// /// The string to convert. /// public static string MakePrintable(string s) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.Length; i++) sb.Append(MakePrintable(s[i])); return sb.ToString(); } /// /// Determines whether a string matches according to a wildcard expression. /// /// The wildcard expression. /// The string to match. /// Whether the string matches. public static bool MatchWildcards(string pattern, string text) { return MatchWildcards(pattern, 0, text, 0); } private static bool MatchWildcards(string pattern, int patternStart, string text, int textStart) { // Note: this algorithm is currently recursive for easy understanding. // It should be re-implemented without recursion... int patternIndex = patternStart; int textIndex = textStart; // If we have a zero-length pattern, the string matches. if (pattern.Length == 0 || patternIndex >= pattern.Length) return true; // If we have a zero-length string, the string doesn't match. if (text.Length == 0 || textIndex >= text.Length) return false; // Match up to the first asterisk (or maybe a number of them). while (true) { // Did we reach the end of the pattern? If so, check if we // have also reached the end of the text. if (patternIndex >= pattern.Length) return textIndex >= text.Length; if (pattern[patternIndex] == '*') { patternIndex++; // Skip duplicate asterisks. while (patternIndex < pattern.Length) { if (pattern[patternIndex] != '*') break; patternIndex++; } break; } // Did we reach the end of the text? If so, the match fails. if (textIndex >= text.Length) return false; if (pattern[patternIndex] != text[textIndex] && pattern[patternIndex] != '?') return false; patternIndex++; textIndex++; } // We reached an asterisk (otherwise we would have returned by now). // Keep incrementing the text index until we get a match. // Shortcut: if we are at the end of the pattern, it means the pattern // has trailing asterisk(s). The string matches. if (patternIndex >= pattern.Length) return true; while (textIndex < text.Length) { if (MatchWildcards(pattern, patternIndex, text, textIndex)) return true; textIndex++; } return false; } public static Dictionary ParseCommandLine(string[] args) { Dictionary dict = new Dictionary(); string argPending = null; foreach (string s in args) { if (s.StartsWith("-")) { if (dict.ContainsKey(s)) throw new ArgumentException("Option already specified."); dict.Add(s, ""); argPending = s; } else { if (argPending != null) { dict[argPending] = s; argPending = null; } else { if (!dict.ContainsKey("")) dict.Add("", s); } } } return dict; } public static int ReadInt32(Stream s, Endianness type) { byte[] buffer = new byte[4]; if (s.Read(buffer, 0, 4) == 0) throw new EndOfStreamException(); return ToInt32(buffer, type); } /// /// Reads a null-terminated string from a stream. /// /// The stream to read from. /// The read string. public static string ReadString(Stream s) { StringBuilder str = new StringBuilder(); while (true) { int b = s.ReadByte(); if (b == 0 || b == -1) break; str.Append((char)(byte)b); } return str.ToString(); } public static string ReadString(Stream s, int length) { byte[] buffer = new byte[length]; if (s.Read(buffer, 0, length) == 0) throw new EndOfStreamException(); return System.Text.ASCIIEncoding.ASCII.GetString(buffer); } public static uint ReadUInt32(Stream s, Endianness type) { byte[] buffer = new byte[4]; if (s.Read(buffer, 0, 4) == 0) throw new EndOfStreamException(); return ToUInt32(buffer, type); } /// /// Reads a null-terminated Unicode string from a stream. /// /// The stream to read from. /// The read string. public static string ReadUnicodeString(Stream s) { StringBuilder str = new StringBuilder(); while (true) { int b = s.ReadByte(); if (b == -1) break; int b2 = s.ReadByte(); if (b2 == -1) break; if (b == 0 && b2 == 0) break; str.Append(UnicodeEncoding.Unicode.GetChars(new byte[] { (byte)b, (byte)b2 })); } return str.ToString(); } /// /// Reads a Unicode string from a stream. /// /// The stream to read from. /// The length, in bytes, of the string. /// The read string. public static string ReadUnicodeString(Stream s, int length) { StringBuilder str = new StringBuilder(); int i = 0; while (i < length) { int b = s.ReadByte(); if (b == -1) break; int b2 = s.ReadByte(); if (b2 == -1) break; str.Append(UnicodeEncoding.Unicode.GetChars(new byte[] { (byte)b, (byte)b2 })); i += 2; } return str.ToString(); } /// /// Swaps the order of the bytes. /// /// The number to change. /// A number. public static int Reverse(this int v) { byte b1 = (byte)v; byte b2 = (byte)(v >> 8); byte b3 = (byte)(v >> 16); byte b4 = (byte)(v >> 24); return b4 | (b3 << 8) | (b2 << 16) | (b1 << 24); } /// /// Swaps the order of the bytes. /// /// The number to change. /// A number. public static uint Reverse(this uint v) { uint b0 = v & 0xff; uint b1 = (v >> 8) & 0xff; uint b2 = (v >> 16) & 0xff; uint b3 = (v >> 24) & 0xff; b0 <<= 24; b1 <<= 16; b2 <<= 8; return b0 | b1 | b2 | b3; } /// /// Swaps the order of the bytes. /// /// The number to change. /// A number. public static ushort Reverse(this ushort v) { byte b1 = (byte)v; byte b2 = (byte)(v >> 8); return (ushort)(b2 | (b1 << 8)); } /// /// Reverses an array. /// /// The array to reverse. /// A new array. public static T[] Reverse(this T[] data) { T[] newData = new T[data.Length]; for (int i = 0; i < data.Length; i++) newData[i] = data[data.Length - i - 1]; return newData; } /// /// Selects all of the specified items. /// /// The items. public static void SelectAll(this ListView.ListViewItemCollection items) { foreach (ListViewItem item in items) item.Selected = true; } /// /// Selects all of the items in the specified ListView. /// /// The ListView to process. public static void SelectAll(this ListView items) { for (int i = 0; i < items.VirtualListSize; i++) if (!items.SelectedIndices.Contains(i)) items.SelectedIndices.Add(i); } /// /// Enables or disables double buffering for a control. /// /// The control. /// The type of the control. /// The new setting. public static void SetDoubleBuffered(this Control c, Type t, bool value) { PropertyInfo property = t.GetProperty("DoubleBuffered", BindingFlags.NonPublic | BindingFlags.Instance); property.SetValue(c, value, null); } /// /// Enables or disables double buffering for a control. /// /// The control to set the property on. /// The new value. public static void SetDoubleBuffered(this Control c, bool value) { c.SetDoubleBuffered(c.GetType(), value); } /// /// Shows a file in Windows Explorer. /// /// The file to show. public static void ShowFileInExplorer(string fileName) { System.Diagnostics.Process.Start("explorer.exe", "/select," + fileName); } /// /// Calculates the size of a structure. /// /// The structure type. /// The size of the structure. public static int SizeOf() { return System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)); } /// /// Calculates the size of a structure. /// /// The structure type. /// A power-of-two whole-structure alignment to apply. /// The size of the structure. public static int SizeOf(int alignment) { // HACK: This is wrong, but it works. return SizeOf() + alignment; } /// /// Returns a sorted list of the names in a given enum type. /// /// The enum type to process. /// A list of key-value pairs, sorted based on the number of bits in the value. public static List> SortFlagNames(Type enumType) { List> nameList = new List>(); foreach (string name in Enum.GetNames(enumType)) { long nameLong = Convert.ToInt64(Enum.Parse(enumType, name)); nameList.Add(new KeyValuePair(name, nameLong)); } nameList.Sort((kvp1, kvp2) => kvp2.Value.CountBits().CompareTo(kvp1.Value.CountBits())); return nameList; } public static int ToInt32(this byte[] data) { return data.ToInt32(Endianness.Little); } public static int ToInt32(this byte[] data, Endianness type) { if (type == Endianness.Little) { return (data[0]) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); } else if (type == Endianness.Big) { return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3]); } else { throw new ArgumentException(); } } public static long ToInt64(this byte[] data) { return data.ToInt64(Endianness.Little); } public static long ToInt64(this byte[] data, Endianness type) { if (type == Endianness.Little) { return (data[0]) | (data[1] << 8) | (data[2] << 16) | (data[3] << 24) | (data[4] << 32) | (data[5] << 40) | (data[6] << 48) | (data[7] << 56); } else if (type == Endianness.Big) { return (data[0] << 56) | (data[1] << 48) | (data[2] << 40) | (data[3] << 32) | (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | (data[7]); } else { throw new ArgumentException(); } } public static IntPtr ToIntPtr(this byte[] data) { if (IntPtr.Size != data.Length) throw new ArgumentException("data"); if (IntPtr.Size == sizeof(int)) return new IntPtr(data.ToInt32(Endianness.Little)); else if (IntPtr.Size == sizeof(long)) return new IntPtr(data.ToInt64(Endianness.Little)); else throw new ArgumentException("data"); } public static ushort ToUInt16(this byte[] data, Endianness type) { return ToUInt16(data, 0, type); } public static ushort ToUInt16(this byte[] data, int offset, Endianness type) { if (type == Endianness.Little) { return (ushort)(data[offset] | (data[offset + 1] << 8)); } else if (type == Endianness.Big) { return (ushort)((data[offset] << 8) | data[offset + 1]); } else { throw new ArgumentException(); } } public static uint ToUInt32(this byte[] data, Endianness type) { return ToUInt32(data, 0, type); } public static uint ToUInt32(this byte[] data, int offset, Endianness type) { if (type == Endianness.Little) { return (uint)(data[offset]) | (uint)(data[offset + 1] << 8) | (uint)(data[offset + 2] << 16) | (uint)(data[offset + 3] << 24); } else if (type == Endianness.Big) { return (uint)(data[offset] << 24) | (uint)(data[offset + 1] << 16) | (uint)(data[offset + 2] << 8) | (uint)(data[offset + 3]); } else { throw new ArgumentException(); } } public static void ValidateBuffer(byte[] buffer, int offset, int length) { ValidateBuffer(buffer, offset, length, false); } public static void ValidateBuffer(byte[] buffer, int offset, int length, bool canBeNull) { // Make sure the offset isn't negative. if (offset < 0) throw new ArgumentOutOfRangeException("offset"); // Make sure the length isn't negative. if (length < 0) throw new ArgumentOutOfRangeException("length"); // Make sure we won't overrun the buffer. if (buffer != null) { if (buffer.Length - offset < length) throw new ArgumentOutOfRangeException("The buffer is too small for the specified offset and length."); } else { if (!canBeNull) throw new ArgumentException("The buffer cannot be null."); // We don't have a buffer, so make sure the offset and length are zero. if (offset != 0 || length != 0) throw new ArgumentOutOfRangeException("The offset and length must be zero for a null buffer."); } } } }