Index: branches/eraser6/CodeReview/Eraser.Util/FileSize.cs
===================================================================
--- branches/eraser6/CodeReview/Eraser.Util/File.cs	(revision 1705)
+++ branches/eraser6/CodeReview/Eraser.Util/FileSize.cs	(revision 1709)
@@ -1,7 +1,7 @@
-/* 
+﻿/* 
  * $Id$
  * Copyright 2008-2010 The Eraser Project
  * Original Author: Joel Low <lowjoel@users.sourceforge.net>
- * Modified By: Kasra Nassiri <cjax@users.sourceforge.net> @10/7/2008
+ * Modified By:
  * 
  * This file is part of Eraser.
@@ -24,250 +24,139 @@
 using System.Text;
 
-using System.Runtime.InteropServices;
-using System.ComponentModel;
-using System.Windows.Forms;
-using System.Drawing;
-using System.IO;
-using Microsoft.Win32.SafeHandles;
 using System.Globalization;
 
 namespace Eraser.Util
 {
-	public static class File
+	/// <summary>
+	/// Gets the human-readable representation of a file size from the byte-wise
+	/// length of a file. This returns a KB = 1024 bytes (Windows convention.)
+	/// </summary>
+	public struct FileSize : IConvertible
 	{
 		/// <summary>
-		/// Gets the list of ADSes of the given file. 
+		/// Constructor.
 		/// </summary>
-		/// <param name="info">The FileInfo object with the file path etc.</param>
-		/// <returns>A list containing the names of the ADSes of each file. The
-		/// list will be empty if no ADSes exist.</returns>
-		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
-		public static IList<string> GetADSes(FileInfo info)
+		/// <param name="filesize">The size of the file, in bytes.</param>
+		public FileSize(long filesize)
+			: this()
 		{
-			List<string> result = new List<string>();
-			using (FileStream stream = new StreamInfo(info.FullName).Open(FileMode.Open,
-				FileAccess.Read, FileShare.ReadWrite))
-			using (SafeFileHandle streamHandle = stream.SafeFileHandle)
-			{
-				//Allocate the structures
-				NativeMethods.FILE_STREAM_INFORMATION[] streams = GetADSes(streamHandle);
-
-				foreach (NativeMethods.FILE_STREAM_INFORMATION streamInfo in streams)
-				{
-					//Get the name of the stream. The raw value is :NAME:$DATA
-					string streamName = streamInfo.StreamName.Substring(1,
-						streamInfo.StreamName.LastIndexOf(':') - 1);
-					
-					if (streamName.Length != 0)
-						result.Add(streamName);
-				}
-			}
-
-			return result.AsReadOnly();
+			Size = filesize;
 		}
 
-		private static NativeMethods.FILE_STREAM_INFORMATION[] GetADSes(SafeFileHandle FileHandle)
+		#region IConvertible Members
+
+		public TypeCode GetTypeCode()
 		{
-			NativeMethods.IO_STATUS_BLOCK status = new NativeMethods.IO_STATUS_BLOCK();
-			IntPtr fileInfoPtr = IntPtr.Zero;
+			return TypeCode.Int64;
+		}
 
-			try
-			{
-				NativeMethods.FILE_STREAM_INFORMATION streamInfo =
-					new NativeMethods.FILE_STREAM_INFORMATION();
-				int fileInfoPtrLength = (Marshal.SizeOf(streamInfo) + 32768) / 2;
-				uint ntStatus = 0;
+		public bool ToBoolean(IFormatProvider provider)
+		{
+			throw new InvalidCastException();
+		}
 
-				do
-				{
-					fileInfoPtrLength *= 2;
-					if (fileInfoPtr != IntPtr.Zero)
-						Marshal.FreeHGlobal(fileInfoPtr);
-					fileInfoPtr = Marshal.AllocHGlobal(fileInfoPtrLength);
+		public byte ToByte(IFormatProvider provider)
+		{
+			return Convert.ToByte(Size);
+		}
 
-					ntStatus = NativeMethods.NtQueryInformationFile(FileHandle, ref status,
-						fileInfoPtr, (uint)fileInfoPtrLength,
-						NativeMethods.FILE_INFORMATION_CLASS.FileStreamInformation);
-				}
-				while (ntStatus != 0 /*STATUS_SUCCESS*/ && ntStatus == 0x80000005 /*STATUS_BUFFER_OVERFLOW*/);
+		public char ToChar(IFormatProvider provider)
+		{
+			throw new InvalidCastException();
+		}
 
-				//Marshal the structure manually (argh!)
-				List<NativeMethods.FILE_STREAM_INFORMATION> result =
-					new List<NativeMethods.FILE_STREAM_INFORMATION>();
-				unsafe
-				{
-					for (byte* i = (byte*)fileInfoPtr; streamInfo.NextEntryOffset != 0;
-						i += streamInfo.NextEntryOffset)
-					{
-						byte* currStreamPtr = i;
-						streamInfo.NextEntryOffset = *(uint*)currStreamPtr;
-						currStreamPtr += sizeof(uint);
+		public DateTime ToDateTime(IFormatProvider provider)
+		{
+			throw new InvalidCastException();
+		}
 
-						streamInfo.StreamNameLength = *(uint*)currStreamPtr;
-						currStreamPtr += sizeof(uint);
+		public decimal ToDecimal(IFormatProvider provider)
+		{
+			return Convert.ToDecimal(Size);
+		}
 
-						streamInfo.StreamSize = *(long*)currStreamPtr;
-						currStreamPtr += sizeof(long);
+		public double ToDouble(IFormatProvider provider)
+		{
+			return Convert.ToDouble(Size);
+		}
 
-						streamInfo.StreamAllocationSize = *(long*)currStreamPtr;
-						currStreamPtr += sizeof(long);
+		public short ToInt16(IFormatProvider provider)
+		{
+			return Convert.ToInt16(Size);
+		}
 
-						streamInfo.StreamName = Marshal.PtrToStringUni((IntPtr)currStreamPtr,
-							(int)streamInfo.StreamNameLength / 2);
-						result.Add(streamInfo);
-					}
-				}
+		public int ToInt32(IFormatProvider provider)
+		{
+			return Convert.ToInt32(Size);
+		}
 
-				return result.ToArray();
-			}
-			finally
-			{
-				Marshal.FreeHGlobal(fileInfoPtr);
-			}
+		public long ToInt64(IFormatProvider provider)
+		{
+			return Size;
+		}
+
+		public sbyte ToSByte(IFormatProvider provider)
+		{
+			return Convert.ToSByte(Size);
+		}
+
+		public float ToSingle(IFormatProvider provider)
+		{
+			return Convert.ToSingle(Size);
+		}
+
+		public string ToString(IFormatProvider provider)
+		{
+			return ToString(Size);
+		}
+
+		public object ToType(Type conversionType, IFormatProvider provider)
+		{
+			return Convert.ChangeType(Size, conversionType, provider);
+		}
+
+		public ushort ToUInt16(IFormatProvider provider)
+		{
+			return Convert.ToUInt16(Size);
+		}
+
+		public uint ToUInt32(IFormatProvider provider)
+		{
+			return Convert.ToUInt32(Size);
+		}
+
+		public ulong ToUInt64(IFormatProvider provider)
+		{
+			return Convert.ToUInt64(Size);
+		}
+
+		#endregion
+
+		/// <summary>
+		/// The size of the file, in bytes.
+		/// </summary>
+		public long Size
+		{
+			get;
+			private set;
 		}
 
 		/// <summary>
-		/// Uses SHGetFileInfo to retrieve the description for the given file,
-		/// folder or drive.
+		/// Converts this file size to the concise equivalent.
 		/// </summary>
-		/// <param name="path">A string that contains the path and file name for
-		/// the file in question. Both absolute and relative paths are valid.
-		/// Directories and volumes must contain the trailing \</param>
-		/// <returns>A string containing the description</returns>
-		public static string GetFileDescription(string path)
+		/// <returns>A string containing the file size and the associated unit.
+		/// Files larger than 1MB will be accurate to 2 decimal places.</returns>
+		public override string ToString()
 		{
-			NativeMethods.SHFILEINFO shfi = new NativeMethods.SHFILEINFO();
-			NativeMethods.SHGetFileInfo(path, 0, ref shfi, Marshal.SizeOf(shfi),
-				NativeMethods.SHGetFileInfoFlags.SHGFI_DISPLAYNAME);
-			return shfi.szDisplayName;
+			return ToString(CultureInfo.CurrentCulture);
 		}
 
 		/// <summary>
-		/// Uses SHGetFileInfo to retrieve the icon for the given file, folder or
-		/// drive.
+		/// Converts a file size to the concise equivalent.
 		/// </summary>
-		/// <param name="path">A string that contains the path and file name for
-		/// the file in question. Both absolute and relative paths are valid.
-		/// Directories and volumes must contain the trailing \</param>
-		/// <returns>An Icon object containing the bitmap</returns>
-		public static Icon GetFileIcon(string path)
-		{
-			NativeMethods.SHFILEINFO shfi = new NativeMethods.SHFILEINFO();
-			NativeMethods.SHGetFileInfo(path, 0, ref shfi, Marshal.SizeOf(shfi),
-				NativeMethods.SHGetFileInfoFlags.SHGFI_SMALLICON |
-				NativeMethods.SHGetFileInfoFlags.SHGFI_ICON);
-
-			if (shfi.hIcon != IntPtr.Zero)
-				return Icon.FromHandle(shfi.hIcon);
-			else
-				throw new IOException(string.Format(CultureInfo.CurrentCulture,
-					"Could not load file icon from {0}", path),
-					Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()));
-		}
-
-		/// <summary>
-		/// Compacts the file path, fitting in the given width.
-		/// </summary>
-		/// <param name="longPath">The long file path.</param>
-		/// <param name="newWidth">The target width of the text.</param>
-		/// <param name="drawFont">The font used for drawing the text.</param>
-		/// <returns>The compacted file path.</returns>
-		public static string GetCompactPath(string longPath, int newWidth, Font drawFont)
-		{
-			using (Control ctrl = new Control())
-			{
-				//First check if the source string is too long.
-				Graphics g = ctrl.CreateGraphics();
-				int width = g.MeasureString(longPath, drawFont).ToSize().Width;
-				if (width <= newWidth)
-					return longPath;
-
-				//It is, shorten it.
-				int aveCharWidth = width / longPath.Length;
-				int charCount = newWidth / aveCharWidth;
-				StringBuilder builder = new StringBuilder();
-				builder.Append(longPath);
-				builder.EnsureCapacity(charCount);
-
-				while (g.MeasureString(builder.ToString(), drawFont).Width > newWidth)
-				{
-					if (!NativeMethods.PathCompactPathEx(builder, longPath,
-						(uint)charCount--, 0))
-					{
-						return string.Empty;
-					}
-				}
-
-				return builder.ToString();
-			}
-		}
-
-		/// <summary>
-		/// Determines if a given file is protected by SFC.
-		/// </summary>
-		/// <param name="filePath">The path to check</param>
-		/// <returns>True if the file is protected.</returns>
-		public static bool IsProtectedSystemFile(string filePath)
-		{
-			return NativeMethods.SfcIsFileProtected(IntPtr.Zero, filePath);
-		}
-
-		/// <summary>
-		/// Checks whether the path given is compressed.
-		/// </summary>
-		/// <param name="path">The path to the file or folder</param>
-		/// <returns>True if the file or folder is compressed.</returns>
-		public static bool IsCompressed(string path)
-		{
-			ushort compressionStatus = 0;
-			uint bytesReturned = 0;
-
-			using (SafeFileHandle handle = NativeMethods.CreateFile(path,
-				NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE,
-				0, IntPtr.Zero, NativeMethods.OPEN_EXISTING,
-				NativeMethods.FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero))
-			{
-				if (NativeMethods.DeviceIoControl(handle, NativeMethods.FSCTL_GET_COMPRESSION,
-					IntPtr.Zero, 0, out compressionStatus, sizeof(ushort), out bytesReturned,
-					IntPtr.Zero))
-				{
-					return compressionStatus != NativeMethods.COMPRESSION_FORMAT_NONE;
-				}
-			}
-
-			return false;
-		}
-
-		/// <summary>
-		/// Sets whether the file system object pointed to by path is compressed.
-		/// </summary>
-		/// <param name="path">The path to the file or folder.</param>
-		/// <returns>True if the file or folder has its compression value set.</returns>
-		public static bool SetCompression(string path, bool compressed)
-		{
-			ushort compressionStatus = compressed ?
-				NativeMethods.COMPRESSION_FORMAT_DEFAULT :
-				NativeMethods.COMPRESSION_FORMAT_NONE;
-			uint bytesReturned = 0;
-
-			using (SafeFileHandle handle = NativeMethods.CreateFile(path,
-				NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE,
-				0, IntPtr.Zero, NativeMethods.OPEN_EXISTING,
-				NativeMethods.FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero))
-			{
-				return NativeMethods.DeviceIoControl(handle, NativeMethods.FSCTL_SET_COMPRESSION,
-					ref compressionStatus, sizeof(ushort), IntPtr.Zero, 0, out bytesReturned,
-					IntPtr.Zero);
-			}
-		}
-
-		/// <summary>
-		/// Gets the human-readable representation of a file size from the byte-wise
-		/// length of a file. This returns a KB = 1024 bytes (Windows convention.)
-		/// </summary>
-		/// <param name="bytes">The file size to scale.</param>
+		/// <param name="size">The size of the file to convert.</param>
 		/// <returns>A string containing the file size and the associated unit.
 		/// Files larger than 1MB will be accurate to 2 decimal places.</returns>
-		public static string GetHumanReadableFileSize(long bytes)
+		public static string ToString(long size)
 		{
 			//List of units, in ascending scale
@@ -282,92 +171,19 @@
 			};
 
-			double dBytes = (double)bytes;
+			double dSize = (double)size;
 			for (int i = 0; i != units.Length; ++i)
 			{
-				if (dBytes < 1000.0)
+				if (dSize < 1000.0)
 					if (i <= 1)
 						return string.Format(CultureInfo.CurrentCulture,
-							"{0} {1}", (int)dBytes, units[i]);
+							"{0} {1}", (int)dSize, units[i]);
 					else
 						return string.Format(CultureInfo.CurrentCulture,
-							"{0:0.00} {1}", dBytes, units[i]);
-				dBytes /= 1024.0;
+							"{0:0.00} {1}", dSize, units[i]);
+				dSize /= 1024.0;
 			}
 
 			return string.Format(CultureInfo.CurrentCulture, "{0, 2} {1}",
-				dBytes, units[units.Length - 1]);
-		}
-
-		private static DateTime FileTimeToDateTime(System.Runtime.InteropServices.ComTypes.FILETIME value)
-		{
-			long time = (long)((((ulong)value.dwHighDateTime) << sizeof(int) * 8) |
-				(uint)value.dwLowDateTime);
-			return DateTime.FromFileTime(time);
-		}
-
-		private static System.Runtime.InteropServices.ComTypes.FILETIME DateTimeToFileTime(DateTime value)
-		{
-			long time = value.ToFileTime();
-
-			System.Runtime.InteropServices.ComTypes.FILETIME result =
-				new System.Runtime.InteropServices.ComTypes.FILETIME();
-			result.dwLowDateTime = (int)(time & 0xFFFFFFFFL);
-			result.dwHighDateTime = (int)(time >> 32);
-
-			return result;
-		}
-
-		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#")]
-		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#")]
-		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "3#")]
-		public static void GetFileTime(SafeFileHandle file, out DateTime creationTime,
-			out DateTime accessedTime, out DateTime modifiedTime)
-		{
-			System.Runtime.InteropServices.ComTypes.FILETIME accessedTimeNative =
-				new System.Runtime.InteropServices.ComTypes.FILETIME();
-			System.Runtime.InteropServices.ComTypes.FILETIME modifiedTimeNative =
-				new System.Runtime.InteropServices.ComTypes.FILETIME();
-			System.Runtime.InteropServices.ComTypes.FILETIME createdTimeNative =
-				new System.Runtime.InteropServices.ComTypes.FILETIME();
-
-			if (!NativeMethods.GetFileTime(file, out createdTimeNative, out accessedTimeNative,
-				out modifiedTimeNative))
-			{
-				throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
-			}
-
-			creationTime = FileTimeToDateTime(createdTimeNative);
-			accessedTime = FileTimeToDateTime(accessedTimeNative);
-			modifiedTime = FileTimeToDateTime(modifiedTimeNative);
-		}
-
-		public static void SetFileTime(SafeFileHandle file, DateTime creationTime,
-			DateTime accessedTime, DateTime modifiedTime)
-		{
-			System.Runtime.InteropServices.ComTypes.FILETIME accessedTimeNative =
-				new System.Runtime.InteropServices.ComTypes.FILETIME();
-			System.Runtime.InteropServices.ComTypes.FILETIME modifiedTimeNative =
-				new System.Runtime.InteropServices.ComTypes.FILETIME();
-			System.Runtime.InteropServices.ComTypes.FILETIME createdTimeNative =
-				new System.Runtime.InteropServices.ComTypes.FILETIME();
-
-			if (!NativeMethods.GetFileTime(file, out createdTimeNative,
-				out accessedTimeNative, out modifiedTimeNative))
-			{
-				throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
-			}
-
-			if (creationTime != DateTime.MinValue)
-				createdTimeNative = DateTimeToFileTime(creationTime);
-			if (accessedTime != DateTime.MinValue)
-				accessedTimeNative = DateTimeToFileTime(accessedTime);
-			if (modifiedTime != DateTime.MinValue)
-				modifiedTimeNative = DateTimeToFileTime(modifiedTime);
-
-			if (!NativeMethods.SetFileTime(file, ref createdTimeNative,
-				ref accessedTimeNative, ref modifiedTimeNative))
-			{
-				throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
-			}
+				dSize, units[units.Length - 1]);
 		}
 	}
