Пример #1
0
 internal static extern bool DeviceIoControlStorageQuery(SafeFileHandle hDevice,
                                                         WindowsIoctl ioControlCode,
                                                         ref StoragePropertyQuery inBuffer,
                                                         uint nInBufferSize,
                                                         IntPtr outBuffer,
                                                         uint nOutBufferSize,
                                                         ref uint pBytesReturned,
                                                         IntPtr overlapped);
Пример #2
0
        internal static DeviceInfo[] GetList()
        {
            List <string> deviceIDs = new List <string>();

            try
            {
                ManagementObjectSearcher mgmtObjSearcher =
                    new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
                ManagementObjectCollection objCol = mgmtObjSearcher.Get();

                deviceIDs.AddRange(from ManagementObject drive in objCol select(string) drive["DeviceID"]);

                mgmtObjSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_TapeDrive");
                objCol          = mgmtObjSearcher.Get();

                deviceIDs.AddRange(from ManagementObject drive in objCol select(string) drive["DeviceID"]);

                mgmtObjSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_CDROMDrive");
                objCol          = mgmtObjSearcher.Get();

                deviceIDs.AddRange(from ManagementObject drive in objCol select(string) drive["Drive"]);
            }
            catch (Exception)
            {
#if DEBUG
                throw;
#else
                return(null);
#endif
            }

            List <DeviceInfo> devList = new List <DeviceInfo>();

            foreach (string devId in deviceIDs)
            {
                string physId = devId;
                // TODO: This can be done better
                if (devId.Length == 2 && devId[1] == ':')
                {
                    physId = "\\\\?\\" + devId;
                }
                SafeFileHandle fd = Extern.CreateFile(physId, 0, FileShare.Read | FileShare.Write, IntPtr.Zero,
                                                      FileMode.OpenExisting, 0, IntPtr.Zero);
                if (fd.IsInvalid)
                {
                    continue;
                }

                StoragePropertyQuery query = new StoragePropertyQuery
                {
                    PropertyId           = StoragePropertyId.Device,
                    QueryType            = StorageQueryType.Standard,
                    AdditionalParameters = new byte[1]
                };

                //StorageDeviceDescriptor descriptor = new StorageDeviceDescriptor();
                //descriptor.RawDeviceProperties = new byte[16384];

                IntPtr descriptorPtr = Marshal.AllocHGlobal(1000);
                byte[] descriptorB   = new byte[1000];

                uint returned = 0;
                int  error    = 0;

                bool hasError = !Extern.DeviceIoControlStorageQuery(fd, WindowsIoctl.IoctlStorageQueryProperty,
                                                                    ref query, (uint)Marshal.SizeOf(query),
                                                                    descriptorPtr, 1000, ref returned, IntPtr.Zero);

                if (hasError)
                {
                    error = Marshal.GetLastWin32Error();
                }

                Marshal.Copy(descriptorPtr, descriptorB, 0, 1000);

                if (hasError && error != 0)
                {
                    continue;
                }

                StorageDeviceDescriptor descriptor = new StorageDeviceDescriptor
                {
                    Version               = BitConverter.ToUInt32(descriptorB, 0),
                    Size                  = BitConverter.ToUInt32(descriptorB, 4),
                    DeviceType            = descriptorB[8],
                    DeviceTypeModifier    = descriptorB[9],
                    RemovableMedia        = BitConverter.ToBoolean(descriptorB, 10),
                    CommandQueueing       = BitConverter.ToBoolean(descriptorB, 11),
                    VendorIdOffset        = BitConverter.ToInt32(descriptorB, 12),
                    ProductIdOffset       = BitConverter.ToInt32(descriptorB, 16),
                    ProductRevisionOffset = BitConverter.ToInt32(descriptorB, 20),
                    SerialNumberOffset    = BitConverter.ToInt32(descriptorB, 24),
                    BusType               = (StorageBusType)BitConverter.ToUInt32(descriptorB, 28),
                    RawPropertiesLength   = BitConverter.ToUInt32(descriptorB, 32)
                };

                DeviceInfo info = new DeviceInfo {
                    Path = physId, Bus = descriptor.BusType.ToString()
                };

                if (descriptor.VendorIdOffset > 0)
                {
                    info.Vendor =
                        StringHandlers.CToString(descriptorB, Encoding.ASCII, start: descriptor.VendorIdOffset);
                }
                if (descriptor.ProductIdOffset > 0)
                {
                    info.Model =
                        StringHandlers.CToString(descriptorB, Encoding.ASCII, start: descriptor.ProductIdOffset);
                }
                // TODO: Get serial number of SCSI and USB devices, probably also FireWire (untested)
                if (descriptor.SerialNumberOffset > 0)
                {
                    info.Serial =
                        StringHandlers.CToString(descriptorB, Encoding.ASCII, start: descriptor.SerialNumberOffset);

                    // fix any serial numbers that are returned as hex-strings
                    if (Array.TrueForAll(info.Serial.ToCharArray(), c => "0123456789abcdef".IndexOf(c) >= 0) &&
                        info.Serial.Length == 40)
                    {
                        info.Serial = HexStringToString(info.Serial).Trim();
                    }
                }

                if (string.IsNullOrEmpty(info.Vendor) || info.Vendor == "ATA")
                {
                    string[] pieces = info.Model.Split(' ');
                    if (pieces.Length > 1)
                    {
                        info.Vendor = pieces[0];
                        info.Model  = info.Model.Substring(pieces[0].Length + 1);
                    }
                }

                switch (descriptor.BusType)
                {
                case StorageBusType.SCSI:
                case StorageBusType.ATAPI:
                case StorageBusType.ATA:
                case StorageBusType.FireWire:
                case StorageBusType.SSA:
                case StorageBusType.Fibre:
                case StorageBusType.USB:
                case StorageBusType.iSCSI:
                case StorageBusType.SAS:
                case StorageBusType.SATA:
                    info.Supported = true;
                    break;
                }

                Marshal.FreeHGlobal(descriptorPtr);
                devList.Add(info);
            }

            DeviceInfo[] devices = devList.ToArray();

            return(devices);
        }