Changeset 2206


Ignore:
Timestamp:
6/19/2010 10:14:24 AM (4 years ago)
Author:
lowjoel
Message:
  • Don't define a shortcut function for DeviceIoControl? since that's a rather low-level API and we don't want to confuse things further.
  • Properly implement the querying of the Physical drive a volume belongs to using the IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS Control Code
Location:
trunk/eraser/Eraser.Util
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/eraser/Eraser.Util/NativeMethods/Kernel.cs

    r2196 r2206  
    646646        public const uint FSCTL_LOCK_VOLUME = 0x90018; 
    647647        public const uint FSCTL_UNLOCK_VOLUME = 0x9001C; 
     648 
     649        [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     650        [return: MarshalAs(UnmanagedType.Bool)] 
     651        public static extern bool DeviceIoControl(SafeFileHandle hDevice, 
     652            uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, 
     653            out NTFS_VOLUME_DATA_BUFFER lpOutBuffer, uint nOutBufferSize, 
     654            out uint lpBytesReturned, IntPtr lpOverlapped); 
     655 
     656        /// <summary> 
     657        /// Retrieves information about the specified NTFS file system volume. 
     658        /// </summary> 
     659        public const int FSCTL_GET_NTFS_VOLUME_DATA = (9 << 16) | (25 << 2); 
     660 
     661        /// <summary> 
     662        /// Removes the boot signature from the master boot record, so that the disk will 
     663        /// be formatted from sector zero to the end of the disk. Partition information 
     664        /// is no longer stored in sector zero. 
     665        /// </summary> 
    648666        public const uint IOCTL_DISK_DELETE_DRIVE_LAYOUT = 
    649667            (0x00000007 << 16) | ((0x01 | 0x02) << 14) | (0x0040 << 2); 
     
    679697        [DllImport("Kernel32.dll", SetLastError = true)] 
    680698        [return: MarshalAs(UnmanagedType.Bool)] 
    681         private extern static bool DeviceIoControl(SafeFileHandle hDevice, 
     699        public extern static bool DeviceIoControl(SafeFileHandle hDevice, 
    682700            uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, 
    683701            out long lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned, 
    684702            IntPtr lpOverlapped); 
    685703 
    686         public static bool DeviceIoControl(SafeFileHandle hDevice, 
    687             uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, 
    688             out long lpOutBuffer, out uint lpBytesReturned, IntPtr lpOverlapped) 
    689         { 
    690             return DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, 
    691                 out lpOutBuffer, sizeof(long), out lpBytesReturned, lpOverlapped); 
    692         } 
    693  
    694704        /// <summary> 
    695705        /// Retrieves the length of the specified disk, volume, or partition. 
     
    698708            (0x00000007 << 16) | (0x0001 << 14) | (0x0017 << 2); 
    699709 
    700         [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    701         [return: MarshalAs(UnmanagedType.Bool)] 
    702         public static extern bool DeviceIoControl(SafeFileHandle hDevice, 
    703             uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, 
    704             out NTFS_VOLUME_DATA_BUFFER lpOutBuffer, uint nOutBufferSize, 
    705             out uint lpBytesReturned, IntPtr lpOverlapped); 
    706  
    707         /// <summary> 
    708         /// Retrieves information about the specified NTFS file system volume. 
    709         /// </summary> 
    710         public const int FSCTL_GET_NTFS_VOLUME_DATA = (9 << 16) | (25 << 2); 
     710        /// <summary> 
     711        /// Retrieves the physical location of a specified volume on one or more disks. 
     712        /// </summary> 
     713        public const int IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = 
     714            ((0x00000056) << 16) | ((0) << 14) | ((0) << 2) | (0); 
     715 
     716        /// <summary> 
     717        /// Represents a physical location on a disk. 
     718        /// </summary> 
     719        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
     720        public struct VOLUME_DISK_EXTENTS 
     721        { 
     722            /// <summary> 
     723            /// The number of disks in the volume (a volume can span multiple disks). 
     724            ///  
     725            /// An extent is a contiguous run of sectors on one disk. When the number 
     726            /// of extents returned is greater than one (1), the error code 
     727            /// ERROR_MORE_DATA is returned. You should call DeviceIoControl again, 
     728            /// allocating enough buffer space based on the value of NumberOfDiskExtents 
     729            /// after the first DeviceIoControl call. 
     730            /// </summary> 
     731            public uint NumberOfDiskExtents; 
     732 
     733            /// <summary> 
     734            /// The first extent in the set. Subsequent extents are found after this 
     735            /// structure. 
     736            /// </summary> 
     737            public DISK_EXTENT Extent; 
     738        } 
     739 
     740        /// <summary> 
     741        /// Represents a disk extent. 
     742        /// </summary> 
     743        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
     744        public struct DISK_EXTENT 
     745        { 
     746            /// <summary> 
     747            /// The number of the disk that contains this extent. 
     748            ///  
     749            /// This is the same number that is used to construct the name of the disk, 
     750            /// for example, the X in PhysicalDriveX or HarddiskX. 
     751            /// </summary> 
     752            public uint DiskNumber; 
     753 
     754            /// <summary> 
     755            /// The offset from the beginning of the disk to the extent, in bytes. 
     756            /// </summary> 
     757            public long StartingOffset; 
     758 
     759            /// <summary> 
     760            /// The number of bytes in this extent. 
     761            /// </summary> 
     762            public long ExtentLength; 
     763        } 
    711764 
    712765        /// <summary> 
  • trunk/eraser/Eraser.Util/PhysicalDriveInfo.cs

    r2196 r2206  
    138138                    uint returned = 0; 
    139139                    if (NativeMethods.DeviceIoControl(handle, NativeMethods.IOCTL_DISK_GET_LENGTH_INFO, 
    140                         IntPtr.Zero, 0, out result, out returned, IntPtr.Zero)) 
     140                        IntPtr.Zero, 0, out result, sizeof(long), out returned, IntPtr.Zero)) 
    141141                    { 
    142142                        return result; 
  • trunk/eraser/Eraser.Util/VolumeInfo.cs

    r2189 r2206  
    480480                    if (NativeMethods.DeviceIoControl(handle, 
    481481                        NativeMethods.IOCTL_DISK_GET_LENGTH_INFO, IntPtr.Zero, 0, out result2, 
    482                         out returned, IntPtr.Zero)) 
     482                        sizeof(long), out returned, IntPtr.Zero)) 
    483483                    { 
    484484                        return result2; 
     
    582582            get 
    583583            { 
    584                 foreach (PhysicalDriveInfo info in PhysicalDriveInfo.Drives) 
    585                 { 
    586                     if (info.Volumes.IndexOf(this) != -1) 
    587                         return info; 
    588                 } 
    589  
     584                IntPtr buffer = IntPtr.Zero; 
     585                List<NativeMethods.DISK_EXTENT> extents = new List<NativeMethods.DISK_EXTENT>(); 
     586                SafeFileHandle handle = OpenHandle(FileAccess.Read, FileShare.ReadWrite, 
     587                    FileOptions.None); 
     588 
     589                try 
     590                { 
     591                    uint returnSize = 0; 
     592                    int bufferSize = Marshal.SizeOf(typeof(NativeMethods.VOLUME_DISK_EXTENTS)); 
     593                    buffer = Marshal.AllocHGlobal(bufferSize); 
     594                    NativeMethods.VOLUME_DISK_EXTENTS header; 
     595 
     596                    if (!NativeMethods.DeviceIoControl(handle, 
     597                        NativeMethods.IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IntPtr.Zero, 0, 
     598                        buffer, (uint)bufferSize, out returnSize, IntPtr.Zero)) 
     599                    { 
     600                        int error = Marshal.GetLastWin32Error(); 
     601                        if (error != Win32ErrorCode.InsufficientBuffer) 
     602                            throw Win32ErrorCode.GetExceptionForWin32Error(error); 
     603 
     604                        //Calculate the size of the buffer required 
     605                        header = (NativeMethods.VOLUME_DISK_EXTENTS) 
     606                            Marshal.PtrToStructure(buffer, 
     607                                typeof(NativeMethods.VOLUME_DISK_EXTENTS)); 
     608                        Marshal.FreeHGlobal(buffer); 
     609                        bufferSize += (int)(header.NumberOfDiskExtents - 1) * 
     610                            Marshal.SizeOf(typeof(NativeMethods.DISK_EXTENT)); 
     611                        buffer = Marshal.AllocHGlobal(bufferSize); 
     612 
     613                        if (!NativeMethods.DeviceIoControl(handle, 
     614                            NativeMethods.IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IntPtr.Zero, 0, 
     615                            buffer, (uint)bufferSize, out returnSize, IntPtr.Zero)) 
     616                        { 
     617                            throw Win32ErrorCode.GetExceptionForWin32Error( 
     618                                Marshal.GetLastWin32Error()); 
     619                        } 
     620                    } 
     621 
     622                    //Parse the structure. 
     623                    header = (NativeMethods.VOLUME_DISK_EXTENTS)Marshal.PtrToStructure(buffer, 
     624                        typeof(NativeMethods.VOLUME_DISK_EXTENTS)); 
     625                    extents.Add(header.Extent); 
     626 
     627                    for (long i = 1, offset = (uint)Marshal.SizeOf(typeof( 
     628                        NativeMethods.VOLUME_DISK_EXTENTS)); i < header.NumberOfDiskExtents; 
     629                        ++i, offset += Marshal.SizeOf(typeof(NativeMethods.DISK_EXTENT))) 
     630                    { 
     631                        NativeMethods.DISK_EXTENT extent = new NativeMethods.DISK_EXTENT(); 
     632                        Marshal.PtrToStructure(new IntPtr(buffer.ToInt64() + offset), extent); 
     633                        extents.Add(extent); 
     634                    } 
     635                } 
     636                finally 
     637                { 
     638                    handle.Close(); 
     639                    Marshal.FreeHGlobal(buffer); 
     640                } 
     641 
     642                if (extents.Count == 1) 
     643                    return new PhysicalDriveInfo((int)extents[0].DiskNumber); 
    590644                return null; 
    591645            } 
Note: See TracChangeset for help on using the changeset viewer.