Ejemplo n.º 1
0
        /// <summary>
        /// Search drives by WMI (Win32_DiskDrive).
        /// </summary>
        /// <param name="diskRosterPre">List of disk information</param>
        private static void SearchDiskDrive(ref List <DiskInfo> diskRosterPre)
        {
            using (var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive"))
            {
                foreach (var drive in searcher.Get())
                {
                    if (drive["Index"] == null)                     // Index number of physical drive
                    {
                        continue;
                    }

                    int index;
                    if (!int.TryParse(drive["Index"].ToString(), out index))
                    {
                        continue;
                    }

                    var info = new DiskInfo();
                    info.PhysicalDrive = index;

                    if (drive["Model"] != null)
                    {
                        info.Model = drive["Model"].ToString();
                    }

                    if (drive["InterfaceType"] != null)
                    {
                        info.InterfaceType = drive["InterfaceType"].ToString();
                    }

                    if (drive["MediaType"] != null)
                    {
                        info.MediaTypeDiskDrive = drive["MediaType"].ToString();
                    }

                    if (drive["Size"] != null)
                    {
                        long numSize;
                        if (long.TryParse(drive["Size"].ToString(), out numSize))
                        {
                            info.SizeWMI = numSize;
                        }
                    }

                    diskRosterPre.Add(info);
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Get disk information by P/Invoke.
        /// </summary>
        /// <param name="physicalDrive">Index number of physical drive</param>
        /// <returns>Disk information</returns>
        internal static DiskInfo GetDiskInfo(int physicalDrive)
        {
            var info = new DiskInfo {
                PhysicalDrive = physicalDrive
            };

            SafeFileHandle hFile = null;

            try
            {
                hFile = NativeMethod.CreateFile(
                    String.Format(@"\\.\PhysicalDrive{0}", physicalDrive),
                    NativeMethod.GENERIC_READ | NativeMethod.GENERIC_WRITE,                     // Administrative privilege is required. GENERIC_WRITE is for IOCTL_ATA_PASS_THROUGH.
                    NativeMethod.FILE_SHARE_READ | NativeMethod.FILE_SHARE_WRITE,
                    IntPtr.Zero,
                    NativeMethod.OPEN_EXISTING,
                    NativeMethod.FILE_ATTRIBUTE_NORMAL,
                    IntPtr.Zero);
                if (hFile == null || hFile.IsInvalid)
                {
                    // This is normal when this application is not run by administrator.
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to get handle to disk.");
                }

                // ---------------------------------
                // Use IOCTL_STORAGE_QUERY_PROPERTY.
                // ---------------------------------
                var storageQuery = new NativeMethod.STORAGE_PROPERTY_QUERY();
                storageQuery.PropertyId = NativeMethod.StorageDeviceProperty;
                storageQuery.QueryType  = NativeMethod.PropertyStandardQuery;

                NativeMethod.STORAGE_DEVICE_DESCRIPTOR storageDescriptor;
                uint bytesReturned1;

                var result1 = NativeMethod.DeviceIoControl(
                    hFile,
                    NativeMethod.IOCTL_STORAGE_QUERY_PROPERTY,
                    ref storageQuery,
                    (uint)Marshal.SizeOf(typeof(NativeMethod.STORAGE_PROPERTY_QUERY)),
                    out storageDescriptor,
                    (uint)Marshal.SizeOf(typeof(NativeMethod.STORAGE_DEVICE_DESCRIPTOR)),
                    out bytesReturned1,
                    IntPtr.Zero);
                if (result1 == false)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to get disk information.");
                }

                // Convert to byte array.
                var size  = Marshal.SizeOf(storageDescriptor);
                var ptr   = Marshal.AllocHGlobal(size);
                var bytes = new byte[size];

                Marshal.StructureToPtr(storageDescriptor, ptr, true);
                Marshal.Copy(ptr, bytes, 0, size);
                Marshal.FreeHGlobal(ptr);

                // Set values.
                info.Vendor      = ConvertBytesToString(bytes, (int)storageDescriptor.VendorIdOffset).Trim();
                info.Product     = ConvertBytesToString(bytes, (int)storageDescriptor.ProductIdOffset).Trim();
                info.IsRemovable = storageDescriptor.RemovableMedia;
                info.BusType     = ConvertBusTypeToString(storageDescriptor.BusType);

                // -------------------------------
                // Use IOCTL_DISK_GET_LENGTH_INFO.
                // -------------------------------
                long diskSize;
                uint bytesReturned2;

                var result2 = NativeMethod.DeviceIoControl(
                    hFile,
                    NativeMethod.IOCTL_DISK_GET_LENGTH_INFO,
                    IntPtr.Zero,
                    0,
                    out diskSize,
                    (uint)Marshal.SizeOf(typeof(long)),
                    out bytesReturned2,
                    IntPtr.Zero);
                if (result2 == false)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to get disk size.");
                }

                // Set value.
                info.SizePInvoke = diskSize;

                // ---------------------------
                // Use IOCTL_ATA_PASS_THROUGH.
                // ---------------------------
                var ataQuery = new NativeMethod.ATAIdentifyDeviceQuery();
                ataQuery.data = new ushort[256];

                ataQuery.header.Length             = (ushort)Marshal.SizeOf(typeof(NativeMethod.ATA_PASS_THROUGH_EX));
                ataQuery.header.AtaFlags           = NativeMethod.ATA_FLAGS.ATA_FLAGS_DATA_IN;
                ataQuery.header.DataTransferLength = (uint)ataQuery.data.Length * 2; // Size of "data" in bytes
                ataQuery.header.TimeOutValue       = 3;                              // Sec
                ataQuery.header.DataBufferOffset   = Marshal.OffsetOf(typeof(NativeMethod.ATAIdentifyDeviceQuery), "data");
                ataQuery.header.PreviousTaskFile   = new byte[8];
                ataQuery.header.CurrentTaskFile    = new byte[8];
                ataQuery.header.CurrentTaskFile[6] = 0xec;                 // ATA IDENTIFY DEVICE

                uint bytesReturned3;

                var result3 = NativeMethod.DeviceIoControl(
                    hFile,
                    NativeMethod.IOCTL_ATA_PASS_THROUGH,
                    ref ataQuery,
                    (uint)Marshal.SizeOf(typeof(NativeMethod.ATAIdentifyDeviceQuery)),
                    ref ataQuery,
                    (uint)Marshal.SizeOf(typeof(NativeMethod.ATAIdentifyDeviceQuery)),
                    out bytesReturned3,
                    IntPtr.Zero);
                if (result3)
                {
                    const int index = 217;                     // Word index of nominal media rotation rate (1 means non-rotating media.)
                    info.NominalMediaRotationRate = ataQuery.data[index];
                }
                else
                {
                    // None. It is normal that IOCTL_ATA_PASS_THROUGH fails when used to external or removable media.
                }
            }
            catch (Win32Exception ex)
            {
                Debug.WriteLine("{0} (Code: {1}).", ex.Message.Substring(0, ex.Message.Length - 1), ex.ErrorCode);
                throw;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                throw;
            }
            finally
            {
                if (hFile != null)
                {
                    // CloseHandle is inappropriate to close SafeFileHandle.
                    // Dispose method is not necessary because Close method will call it internally.
                    hFile.Close();
                }
            }

            return(info);
        }