Example #1
0
        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();
            }
        }
Example #2
0
 public bool Equals(DeviceNumber rhs)
 {
     return (Device == rhs.Device) &&
         (Partition == rhs.Partition) &&
         (Type == rhs.Type);
 }
Example #3
0
 public bool Equals(DeviceNumber rhs)
 {
     return((Device == rhs.Device) &&
            (Partition == rhs.Partition) &&
            (Type == rhs.Type));
 }
Example #4
0
        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();
            }
        }