Changeset 1223


Ignore:
Timestamp:
9/29/2009 2:48:14 PM (5 years ago)
Author:
lowjoel
Message:

Implemented raw volume access.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/eraser6/Eraser.Util/VolumeInfo.cs

    r1207 r1223  
    393393        } 
    394394 
     395        /// <summary> 
     396        /// Opens a file with read, write, or read/write access. 
     397        /// </summary> 
     398        /// <param name="access">A System.IO.FileAccess constant specifying whether 
     399        /// to open the file with Read, Write, or ReadWrite file access.</param> 
     400        /// <returns>A System.IO.FileStream object opened in the specified mode 
     401        /// and access, unshared, and no special file options.</returns> 
     402        public FileStream Open(FileAccess access) 
     403        { 
     404            return Open(access, FileShare.None, FileOptions.None); 
     405        } 
     406 
     407        /// <summary> 
     408        /// Opens a file with read, write, or read/write access and the specified 
     409        /// sharing option. 
     410        /// </summary> 
     411        /// <param name="access">A System.IO.FileAccess constant specifying whether 
     412        /// to open the file with Read, Write, or ReadWrite file access.</param> 
     413        /// <param name="share">A System.IO.FileShare constant specifying the type 
     414        /// of access other FileStream objects have to this file.</param> 
     415        /// <returns>A System.IO.FileStream object opened with the specified mode, 
     416        /// access, sharing options, and no special file options.</returns> 
     417        public FileStream Open(FileAccess access, FileShare share) 
     418        { 
     419            return Open(access, share, FileOptions.None); 
     420        } 
     421 
     422        /// <summary> 
     423        /// Opens a file with read, write, or read/write access, the specified 
     424        /// sharing option, and other advanced options. 
     425        /// </summary> 
     426        /// <param name="mode">A System.IO.FileMode constant specifying the mode 
     427        /// (for example, Open or Append) in which to open the file.</param> 
     428        /// <param name="access">A System.IO.FileAccess constant specifying whether 
     429        /// to open the file with Read, Write, or ReadWrite file access.</param> 
     430        /// <param name="share">A System.IO.FileShare constant specifying the type 
     431        /// of access other FileStream objects have to this file.</param> 
     432        /// <param name="options">The System.IO.FileOptions constant specifying 
     433        /// the advanced file options to use when opening the file.</param> 
     434        /// <returns>A System.IO.FileStream object opened with the specified mode, 
     435        /// access, sharing options, and special file options.</returns> 
     436        public FileStream Open(FileAccess access, FileShare share, FileOptions options) 
     437        { 
     438            SafeFileHandle handle = OpenHandle(access, share, options); 
     439 
     440            //Check that the handle is valid 
     441            if (handle.IsInvalid) 
     442                throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); 
     443 
     444            //Return the FileStream 
     445            return new FileStream(handle, access); 
     446        } 
     447 
     448        private SafeFileHandle OpenHandle(FileAccess access, FileShare share, FileOptions options) 
     449        { 
     450            //Access mode 
     451            uint iAccess = 0; 
     452            switch (access) 
     453            { 
     454                case FileAccess.Read: 
     455                    iAccess = KernelApi.NativeMethods.GENERIC_READ; 
     456                    break; 
     457                case FileAccess.ReadWrite: 
     458                    iAccess = KernelApi.NativeMethods.GENERIC_READ | 
     459                        KernelApi.NativeMethods.GENERIC_WRITE; 
     460                    break; 
     461                case FileAccess.Write: 
     462                    iAccess = KernelApi.NativeMethods.GENERIC_WRITE; 
     463                    break; 
     464            } 
     465 
     466            //Sharing mode 
     467            if ((share & FileShare.Inheritable) != 0) 
     468                throw new NotSupportedException("Inheritable handles are not supported."); 
     469 
     470            //Advanced options 
     471            if ((options & FileOptions.Asynchronous) != 0) 
     472                throw new NotSupportedException("Asynchronous handles are not implemented."); 
     473 
     474            //Create the handle 
     475            string openPath = VolumeId; 
     476            if (openPath.Length > 0 && openPath[openPath.Length - 1] == '\\') 
     477                openPath = openPath.Remove(openPath.Length - 1); 
     478            SafeFileHandle result = KernelApi.NativeMethods.CreateFile(openPath, iAccess, 
     479                (uint)share, IntPtr.Zero, (uint)FileMode.Open, (uint)options, IntPtr.Zero); 
     480            if (result.IsInvalid) 
     481                throw KernelApi.GetExceptionForWin32Error(Marshal.GetLastWin32Error()); 
     482 
     483            return result; 
     484        } 
     485 
     486        public VolumeLock LockVolume(FileStream stream) 
     487        { 
     488            return new VolumeLock(stream.SafeFileHandle); 
     489        } 
     490 
    395491        private List<string> mountPoints = new List<string>(); 
    396492    } 
     493 
     494    public class VolumeLock : IDisposable 
     495    { 
     496        internal VolumeLock(SafeFileHandle handle) 
     497        { 
     498            uint result = 0; 
     499            for (int i = 0; !KernelApi.NativeMethods.DeviceIoControl(handle, 
     500                    KernelApi.NativeMethods.FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 
     501                    0, out result, IntPtr.Zero); ++i) 
     502            { 
     503                if (i > 100) 
     504                    throw new IOException("Could not lock volume."); 
     505                System.Threading.Thread.Sleep(100); 
     506            } 
     507 
     508            Handle = handle; 
     509        } 
     510 
     511        ~VolumeLock() 
     512        { 
     513            Dispose(false); 
     514        } 
     515 
     516        public void Dispose() 
     517        { 
     518            Dispose(true); 
     519        } 
     520 
     521        void Dispose(bool disposing) 
     522        { 
     523            if (disposing) 
     524                GC.SuppressFinalize(this); 
     525 
     526            uint result = 0; 
     527            if (!KernelApi.NativeMethods.DeviceIoControl(Handle, KernelApi.NativeMethods.FSCTL_UNLOCK_VOLUME, 
     528                IntPtr.Zero, 0, IntPtr.Zero, 0, out result, IntPtr.Zero)) 
     529            { 
     530                throw new IOException("Could not unlock volume."); 
     531            } 
     532        } 
     533 
     534        private SafeFileHandle Handle; 
     535    } 
    397536} 
Note: See TracChangeset for help on using the changeset viewer.