Changeset 2191


Ignore:
Timestamp:
6/18/2010 3:05:22 PM (4 years ago)
Author:
lowjoel
Message:

Implemented the opening of physical disks for direct read/write access.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/eraser/Eraser.Util/PhysicalDriveInfo.cs

    r2188 r2191  
    6666                { 
    6767                    using (SafeFileHandle handle = OpenWin32Device(GetDiskPath(i), 
    68                         NativeMethods.FILE_READ_ATTRIBUTES)) 
     68                        NativeMethods.FILE_READ_ATTRIBUTES, FileShare.ReadWrite, FileOptions.None)) 
    6969                    { 
    7070                        if (handle.IsInvalid) 
     
    7676 
    7777                return result.AsReadOnly(); 
    78             } 
    79         } 
    80  
    81         /// <summary> 
    82         /// Opens a device in the Win32 Namespace. 
    83         /// </summary> 
    84         /// <param name="deviceName">The name of the device to open.</param> 
    85         /// <param name="access">The access needed for the handle.</param> 
    86         /// <returns>A <see cref="SafeFileHandle"/> to the device.</returns> 
    87         private static SafeFileHandle OpenWin32Device(string deviceName, uint access) 
    88         { 
    89             //Define the DOS device name for access 
    90             string dosDeviceName = string.Format(CultureInfo.InvariantCulture, 
    91                 "eraser{0}_{1}", System.Diagnostics.Process.GetCurrentProcess().Id, 
    92                 System.AppDomain.GetCurrentThreadId()); 
    93             if (!NativeMethods.DefineDosDevice( 
    94                 NativeMethods.DosDeviceDefineFlags.RawTargetPath, dosDeviceName, 
    95                 deviceName)) 
    96             { 
    97                 throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); 
    98             } 
    99  
    100             try 
    101             { 
    102                 //Open the device handle. 
    103                 return NativeMethods.CreateFile(string.Format(CultureInfo.InvariantCulture, 
    104                     "\\\\.\\{0}", dosDeviceName), access, 
    105                     NativeMethods.FILE_SHARE_READ | NativeMethods.FILE_SHARE_WRITE, IntPtr.Zero, 
    106                     (int)FileMode.Open, (uint)FileAttributes.ReadOnly, IntPtr.Zero); 
    107             } 
    108             finally 
    109             { 
    110                 //Then undefine the DOS device 
    111                 if (!NativeMethods.DefineDosDevice( 
    112                     NativeMethods.DosDeviceDefineFlags.ExactMatchOnRmove | 
    113                     NativeMethods.DosDeviceDefineFlags.RawTargetPath | 
    114                     NativeMethods.DosDeviceDefineFlags.RemoveDefinition, 
    115                     dosDeviceName, deviceName)) 
    116                 { 
    117                     throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); 
    118                 } 
    11978            } 
    12079        } 
     
    13493                    string path = GetPartitionPath(i); 
    13594                    using (SafeFileHandle handle = OpenWin32Device(path, 
    136                         NativeMethods.FILE_READ_ATTRIBUTES)) 
     95                        NativeMethods.FILE_READ_ATTRIBUTES, FileShare.ReadWrite, FileOptions.None)) 
    13796                    { 
    13897                        if (handle.IsInvalid) 
     
    171130            { 
    172131                using (SafeFileHandle handle = OpenWin32Device(GetDiskPath(), 
    173                     NativeMethods.GENERIC_READ)) 
     132                    NativeMethods.GENERIC_READ, FileShare.ReadWrite, FileOptions.None)) 
    174133                { 
    175134                    if (handle.IsInvalid) 
     
    189148        } 
    190149 
     150        /// <summary> 
     151        /// Opens a file with read, write, or read/write access. 
     152        /// </summary> 
     153        /// <param name="access">A System.IO.FileAccess constant specifying whether 
     154        /// to open the file with Read, Write, or ReadWrite file access.</param> 
     155        /// <returns>A System.IO.FileStream object opened in the specified mode 
     156        /// and access, unshared, and no special file options.</returns> 
     157        public FileStream Open(FileAccess access) 
     158        { 
     159            return Open(access, FileShare.None, FileOptions.None); 
     160        } 
     161 
     162        /// <summary> 
     163        /// Opens a file with read, write, or read/write access and the specified 
     164        /// sharing option. 
     165        /// </summary> 
     166        /// <param name="access">A System.IO.FileAccess constant specifying whether 
     167        /// to open the file with Read, Write, or ReadWrite file access.</param> 
     168        /// <param name="share">A System.IO.FileShare constant specifying the type 
     169        /// of access other FileStream objects have to this file.</param> 
     170        /// <returns>A System.IO.FileStream object opened with the specified mode, 
     171        /// access, sharing options, and no special file options.</returns> 
     172        public FileStream Open(FileAccess access, FileShare share) 
     173        { 
     174            return Open(access, share, FileOptions.None); 
     175        } 
     176 
     177        /// <summary> 
     178        /// Opens a file with read, write, or read/write access, the specified 
     179        /// sharing option, and other advanced options. 
     180        /// </summary> 
     181        /// <param name="mode">A System.IO.FileMode constant specifying the mode 
     182        /// (for example, Open or Append) in which to open the file.</param> 
     183        /// <param name="access">A System.IO.FileAccess constant specifying whether 
     184        /// to open the file with Read, Write, or ReadWrite file access.</param> 
     185        /// <param name="share">A System.IO.FileShare constant specifying the type 
     186        /// of access other FileStream objects have to this file.</param> 
     187        /// <param name="options">The System.IO.FileOptions constant specifying 
     188        /// the advanced file options to use when opening the file.</param> 
     189        /// <returns>A System.IO.FileStream object opened with the specified mode, 
     190        /// access, sharing options, and special file options.</returns> 
     191        public FileStream Open(FileAccess access, FileShare share, FileOptions options) 
     192        { 
     193            SafeFileHandle handle = OpenHandle(access, share, options); 
     194 
     195            //Check that the handle is valid 
     196            if (handle.IsInvalid) 
     197            { 
     198                int errorCode = Marshal.GetLastWin32Error(); 
     199                handle.Close(); 
     200                throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); 
     201            } 
     202 
     203            //Return the stream 
     204            return new PhysicalDriveStream(this, handle, access); 
     205        } 
     206 
     207        private SafeFileHandle OpenHandle(FileAccess access, FileShare share, 
     208            FileOptions options) 
     209        { 
     210            //Access mode 
     211            uint iAccess = 0; 
     212            switch (access) 
     213            { 
     214                case FileAccess.Read: 
     215                    iAccess = NativeMethods.GENERIC_READ; 
     216                    break; 
     217                case FileAccess.ReadWrite: 
     218                    iAccess = NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE; 
     219                    break; 
     220                case FileAccess.Write: 
     221                    iAccess = NativeMethods.GENERIC_WRITE; 
     222                    break; 
     223            } 
     224 
     225            return OpenHandle(iAccess, share, options); 
     226        } 
     227 
     228        private SafeFileHandle OpenHandle(uint access, FileShare share, 
     229            FileOptions options) 
     230        { 
     231            //Sharing mode 
     232            if ((share & FileShare.Inheritable) != 0) 
     233                throw new NotSupportedException("Inheritable handles are not supported."); 
     234 
     235            //Advanced options 
     236            if ((options & FileOptions.Asynchronous) != 0) 
     237                throw new NotSupportedException("Asynchronous handles are not implemented."); 
     238 
     239            //Create the handle 
     240            SafeFileHandle result = OpenWin32Device(GetDiskPath(), access, share, options); 
     241            if (result.IsInvalid) 
     242            { 
     243                int errorCode = Marshal.GetLastWin32Error(); 
     244                result.Close(); 
     245                throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); 
     246            } 
     247 
     248            return result; 
     249        } 
     250 
     251        /// <summary> 
     252        /// Opens a device in the Win32 Namespace. 
     253        /// </summary> 
     254        /// <param name="deviceName">The name of the device to open.</param> 
     255        /// <param name="access">The access needed for the handle.</param> 
     256        /// <returns>A <see cref="SafeFileHandle"/> to the device.</returns> 
     257        private static SafeFileHandle OpenWin32Device(string deviceName, uint access, 
     258            FileShare share, FileOptions options) 
     259        { 
     260            //Define the DOS device name for access 
     261            string dosDeviceName = string.Format(CultureInfo.InvariantCulture, 
     262                "eraser{0}_{1}", System.Diagnostics.Process.GetCurrentProcess().Id, 
     263                System.Threading.Thread.CurrentThread.ManagedThreadId); 
     264            if (!NativeMethods.DefineDosDevice( 
     265                NativeMethods.DosDeviceDefineFlags.RawTargetPath, dosDeviceName, 
     266                deviceName)) 
     267            { 
     268                throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); 
     269            } 
     270 
     271            try 
     272            { 
     273                //Open the device handle. 
     274                return NativeMethods.CreateFile(string.Format(CultureInfo.InvariantCulture, 
     275                    "\\\\.\\{0}", dosDeviceName), access, (uint)share, IntPtr.Zero, 
     276                    (int)FileMode.Open, (uint)options, IntPtr.Zero); 
     277            } 
     278            finally 
     279            { 
     280                //Then undefine the DOS device 
     281                if (!NativeMethods.DefineDosDevice( 
     282                    NativeMethods.DosDeviceDefineFlags.ExactMatchOnRmove | 
     283                    NativeMethods.DosDeviceDefineFlags.RawTargetPath | 
     284                    NativeMethods.DosDeviceDefineFlags.RemoveDefinition, 
     285                    dosDeviceName, deviceName)) 
     286                { 
     287                    throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); 
     288                } 
     289            } 
     290        } 
     291 
    191292        public override bool Equals(object obj) 
    192293        { 
     
    237338        } 
    238339    } 
     340 
     341    public class PhysicalDriveStream : FileStream 
     342    { 
     343        internal PhysicalDriveStream(PhysicalDriveInfo drive, SafeFileHandle handle, 
     344            FileAccess access) 
     345            : base(handle, access) 
     346        { 
     347            Drive = drive; 
     348        } 
     349 
     350        public override void SetLength(long value) 
     351        { 
     352            throw new InvalidOperationException(); 
     353        } 
     354 
     355        public override long Length 
     356        { 
     357            get 
     358            { 
     359                return Drive.Size; 
     360            } 
     361        } 
     362 
     363        /// <summary> 
     364        /// The <see cref="VolumeInfo"/> object this stream is encapsulating. 
     365        /// </summary> 
     366        private PhysicalDriveInfo Drive; 
     367    } 
    239368} 
Note: See TracChangeset for help on using the changeset viewer.