public static unsafe bool GetDeviceNumber(string path, out DeviceNumber result, out Exception failureReason) { result = new DeviceNumber(); failureReason = null; var handle = Native.CreateFile( path, NativeFileAccess.GenericRead, System.IO.FileShare.ReadWrite, IntPtr.Zero, System.IO.FileMode.Open, NativeFileFlags.None, IntPtr.Zero ); var error = Marshal.GetLastWin32Error(); if (error != 0) { failureReason = new Win32Exception(error); return(false); } else if (handle.IsInvalid) { return(false); } try { var devNumber = new Native.STORAGE_DEVICE_NUMBER(); Native.DeviceIoControl( handle, Native.IOCTL_STORAGE_GET_DEVICE_NUMBER, devNumber ); result = new DeviceNumber(devNumber.DeviceNumber, devNumber.PartitionNumber, devNumber.DeviceType); return(true); } catch (Win32Exception w32ex) { // STORAGE_GET_DEVICE_NUMBER will fail for dynamic disks with ERROR_INCORRECT_FUNCTION, // so we try VOLUME_GET_VOLUME_DISK_EXTENTS instead if (w32ex.NativeErrorCode != Native.ERROR_INCORRECT_FUNCTION) { failureReason = w32ex; return(false); } int extentSize = Marshal.SizeOf(typeof(Native.DISK_EXTENT)); int headerSize = Marshal.SizeOf(typeof(Native.VOLUME_DISK_EXTENTS_HEADER)); const int bufferSize = 64; var buffer = new byte[headerSize + (extentSize * bufferSize)]; var header = new Native.VOLUME_DISK_EXTENTS_HEADER { NumberOfDiskExtents = bufferSize }; fixed(byte *pBuffer = buffer) { Marshal.StructureToPtr(header, new IntPtr(pBuffer), false); Native.DeviceIoControl( handle, Native.IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, new IntPtr(pBuffer), (UInt32)buffer.Length ); Marshal.PtrToStructure(new IntPtr(pBuffer), header); var pExtents = pBuffer + headerSize; var extent = new Native.DISK_EXTENT(); if (header.NumberOfDiskExtents > 1) { throw new NotImplementedException("Volumes spread across multiple physical disks are not supported"); } Marshal.PtrToStructure(new IntPtr(pExtents), extent); result = new DeviceNumber(-1024, (int)extent.DiskNumber, -1024); return(true); } } catch (Exception ex) { failureReason = ex; return(false); } finally { handle.Close(); } }
public bool Equals(DeviceNumber rhs) { return (Device == rhs.Device) && (Partition == rhs.Partition) && (Type == rhs.Type); }
public bool Equals(DeviceNumber rhs) { return((Device == rhs.Device) && (Partition == rhs.Partition) && (Type == rhs.Type)); }
public static unsafe bool GetDeviceNumber(string path, out DeviceNumber result, out Exception failureReason) { result = new DeviceNumber(); failureReason = null; var handle = Native.CreateFile( path, NativeFileAccess.GenericRead, System.IO.FileShare.ReadWrite, IntPtr.Zero, System.IO.FileMode.Open, NativeFileFlags.None, IntPtr.Zero ); var error = Marshal.GetLastWin32Error(); if (error != 0) { failureReason = new Win32Exception(error); return false; } else if (handle.IsInvalid) { return false; } try { var devNumber = new Native.STORAGE_DEVICE_NUMBER(); Native.DeviceIoControl( handle, Native.IOCTL_STORAGE_GET_DEVICE_NUMBER, devNumber ); result = new DeviceNumber(devNumber.DeviceNumber, devNumber.PartitionNumber, devNumber.DeviceType); return true; } catch (Win32Exception w32ex) { // STORAGE_GET_DEVICE_NUMBER will fail for dynamic disks with ERROR_INCORRECT_FUNCTION, // so we try VOLUME_GET_VOLUME_DISK_EXTENTS instead if (w32ex.NativeErrorCode != Native.ERROR_INCORRECT_FUNCTION) { failureReason = w32ex; return false; } int extentSize = Marshal.SizeOf(typeof(Native.DISK_EXTENT)); int headerSize = Marshal.SizeOf(typeof(Native.VOLUME_DISK_EXTENTS_HEADER)); const int bufferSize = 64; var buffer = new byte[ headerSize + (extentSize * bufferSize) ]; var header = new Native.VOLUME_DISK_EXTENTS_HEADER { NumberOfDiskExtents = bufferSize }; fixed (byte* pBuffer = buffer) { Marshal.StructureToPtr(header, new IntPtr(pBuffer), false); Native.DeviceIoControl( handle, Native.IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, new IntPtr(pBuffer), (UInt32)buffer.Length ); Marshal.PtrToStructure(new IntPtr(pBuffer), header); var pExtents = pBuffer + headerSize; var extent = new Native.DISK_EXTENT(); if (header.NumberOfDiskExtents > 1) throw new NotImplementedException("Volumes spread across multiple physical disks are not supported"); Marshal.PtrToStructure(new IntPtr(pExtents), extent); result = new DeviceNumber(-1024, (int)extent.DiskNumber, -1024); return true; } } catch (Exception ex) { failureReason = ex; return false; } finally { handle.Close(); } }