Volume : Device, IComparable

// UsbEject version 1.0 March 2006
// written by Simon Mourier <email: simon [underscore] mourier [at] hotmail [dot] com>

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace UsbEject.Library
{
    /// <summary>
    /// A volume device.
    /// </summary>
    public class Volume : Device, IComparable
    {
        private string _volumeName;
        private string _logicalDrive;
        private int[] _diskNumbers;
        private List<Device> _disks;
        private List<Device> _removableDevices;

        internal Volume(DeviceClass deviceClass, Native.SP_DEVINFO_DATA deviceInfoData, string path, int index)
            :base(deviceClass, deviceInfoData, path, index)
        {
        }

        /// <summary>
        /// Gets the volume's name.
        /// </summary>
        public string VolumeName
        {
            get
            {
                if (_volumeName == null)
                {
                    StringBuilder sb = new StringBuilder(1024);
                    if (!Native.GetVolumeNameForVolumeMountPoint(Path + "\\", sb, sb.Capacity))
                    {
                        // throw new Win32Exception(Marshal.GetLastWin32Error());
                        
                    }

                    if (sb.Length > 0)
                    {
                        _volumeName = sb.ToString();
                    }
                }
                return _volumeName;
            }
        }

        /// <summary>
        /// Gets the volume's logical drive in the form [letter]:\
        /// </summary>
        public string LogicalDrive
        {
            get
            {
                if ((_logicalDrive == null) && (VolumeName != null))
                {
                    ((VolumeDeviceClass)DeviceClass)._logicalDrives.TryGetValue(VolumeName, out _logicalDrive);
                }
                return _logicalDrive;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this volume is a based on USB devices.
        /// </summary>
        public override bool IsUsb
        {
            get
            {
                if (Disks != null)
                {
                    foreach (Device disk in Disks)
                    {
                        if (disk.IsUsb)
                            return true;
                    }
                }
                return false;
            }
        }

        /// <summary>
        /// Gets a list of underlying disks for this volume.
        /// </summary>
        public List<Device> Disks
        {
            get
            {
                if (_disks == null)
                {
                    _disks = new List<Device>();

                    if (DiskNumbers != null)
                    {
                        DiskDeviceClass disks = new DiskDeviceClass();
                        foreach (int index in DiskNumbers)
                        {
                            if (index < disks.Devices.Count)
                            {
                                _disks.Add(disks.Devices[index]);
                            }
                        }
                    }
                }
                return _disks;
            }
        }

        private int[] DiskNumbers
        {
            get
            {
                if (_diskNumbers == null)
                {
                    List<int> numbers = new List<int>();
                    if (LogicalDrive != null)
                    {

                        IntPtr hFile = Native.CreateFile(@"\\.\" + LogicalDrive, Native.GENERIC_READ, Native.FILE_SHARE_READ | Native.FILE_SHARE_WRITE, IntPtr.Zero, Native.OPEN_EXISTING, 0, IntPtr.Zero);
                        if (hFile.ToInt32() == Native.INVALID_HANDLE_VALUE)
                            throw new Win32Exception(Marshal.GetLastWin32Error());

                        int size = 0x400; // some big size
                        IntPtr buffer = Marshal.AllocHGlobal(size);
                        int bytesReturned = 0;
                        try
                        {
                            if (!Native.DeviceIoControl(hFile, Native.IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IntPtr.Zero, 0, buffer, size, out bytesReturned, IntPtr.Zero))
                            {
                                // do nothing here on purpose
                            }
                        }
                        finally
                        {
                            Native.CloseHandle(hFile);
                        }

                        if (bytesReturned > 0)
                        {
                            int numberOfDiskExtents = (int)Marshal.PtrToStructure(buffer, typeof(int));
                            for (int i = 0; i < numberOfDiskExtents; i++)
                            {
                                IntPtr extentPtr = new IntPtr(buffer.ToInt32() + Marshal.SizeOf(typeof(long)) + i * Marshal.SizeOf(typeof(Native.DISK_EXTENT)));
                                Native.DISK_EXTENT extent = (Native.DISK_EXTENT)Marshal.PtrToStructure(extentPtr, typeof(Native.DISK_EXTENT));
                                numbers.Add(extent.DiskNumber);
                            }
                        }
                        Marshal.FreeHGlobal(buffer);
                    }

                    _diskNumbers = new int[numbers.Count];
                    numbers.CopyTo(_diskNumbers);
                }
                return _diskNumbers;
            }
        }

        /// <summary>
        /// Gets a list of removable devices for this volume.
        /// </summary>
        public override List<Device> RemovableDevices
        {
            get
            {
                if (_removableDevices == null)
                {
                    _removableDevices = new List<Device>();
                    if (Disks == null)
                    {
                        _removableDevices = base.RemovableDevices;
                    }
                    else
                    {
                        foreach (Device disk in Disks)
                        {
                            foreach (Device device in disk.RemovableDevices)
                            {
                                _removableDevices.Add(device);
                            }
                        }
                    }
                }
                return _removableDevices;
            }
        }

        /// <summary>
        /// Compares the current instance with another object of the same type.
        /// </summary>
        /// <param name="obj">An object to compare with this instance.</param>
        /// <returns>A 32-bit signed integer that indicates the relative order of the comparands.</returns>
        public override int CompareTo(object obj)
        {
            Volume device = obj as Volume;
            if (device == null)
                throw new ArgumentException();

            if (LogicalDrive == null)
                return 1;

            if (device.LogicalDrive == null)
                return -1;

            return LogicalDrive.CompareTo(device.LogicalDrive);
        }
    }
}

转载于:https://my.oschina.net/jrlapple/blog/124308

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值