Код: Выделить всё
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class ATAFeaturesForm : Form
{
const uint FILE_READ_ACCESS = 0x80000000;
const uint FILE_WRITE_ACCESS = 0x40000000;
const uint FILE_SHARE_READ = 0x1;
const uint FILE_SHARE_WRITE = 0x2;
const uint OPEN_EXISTING = 3;
const uint IOCTL_ATA_PASS_THROUGH = 0x4D02C;
const ushort ATA_FLAGS_DATA_IN = 0x02;
[StructLayout(LayoutKind.Sequential)]
struct ATA_PASS_THROUGH_EX
{
public ushort Length;
public ushort AtaFlags;
public byte PathId;
public byte TargetId;
public byte Lun;
public byte ReservedAsUchar;
public uint DataTransferLength;
public uint TimeOutValue;
public IntPtr DataBuffer;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] PreviousTaskFile;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] CurrentTaskFile;
}
[StructLayout(LayoutKind.Sequential)]
struct ATAIdentifyDeviceData
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
public byte[] Data;
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
ref ATA_PASS_THROUGH_EX lpInBuffer,
uint nInBufferSize,
IntPtr lpOutBuffer,
uint nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);
public ATAFeaturesForm()
{
InitializeComponent();
FetchATADetails();
}
private void FetchATADetails()
{
try
{
string drivePath = @"\\.\PhysicalDrive0";
IntPtr hDevice = CreateFile(
drivePath,
FILE_READ_ACCESS | FILE_WRITE_ACCESS,
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero
);
if (hDevice == IntPtr.Zero || hDevice.ToInt32() == -1)
{
int error = Marshal.GetLastWin32Error();
throw new IOException($"Failed to open the device. Error code: {error}");
}
ATA_PASS_THROUGH_EX ataPassThrough = new ATA_PASS_THROUGH_EX
{
Length = (ushort)Marshal.SizeOf(typeof(ATA_PASS_THROUGH_EX)),
AtaFlags = ATA_FLAGS_DATA_IN,
PathId = 0,
TargetId = 0,
Lun = 0,
ReservedAsUchar = 0,
DataTransferLength = 512,
TimeOutValue = 10,
DataBuffer = Marshal.AllocHGlobal(512),
PreviousTaskFile = new byte[8],
CurrentTaskFile = new byte[8]
};
ataPassThrough.CurrentTaskFile[6] = 0xEC; // ATA IDENTIFY command
uint bytesReturned;
IntPtr ataIdentifyDeviceData = Marshal.AllocHGlobal(512);
if (!DeviceIoControl(
hDevice,
IOCTL_ATA_PASS_THROUGH,
ref ataPassThrough,
(uint)Marshal.SizeOf(ataPassThrough),
ataIdentifyDeviceData,
512,
out bytesReturned,
IntPtr.Zero))
{
int error = Marshal.GetLastWin32Error();
Marshal.FreeHGlobal(ataIdentifyDeviceData);
Marshal.FreeHGlobal(ataPassThrough.DataBuffer);
throw new IOException($"Failed to retrieve ATA information. Error code: {error}");
}
byte[] data = new byte[512];
Marshal.Copy(ataIdentifyDeviceData, data, 0, 512);
DisplayATADetails(data);
Marshal.FreeHGlobal(ataIdentifyDeviceData);
Marshal.FreeHGlobal(ataPassThrough.DataBuffer);
if (!CloseHandle(hDevice))
{
int error = Marshal.GetLastWin32Error();
throw new IOException($"Failed to close the device handle. Error code: {error}");
}
}
catch (Exception ex)
{
MessageBox.Show($"Error retrieving ATA details: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void DisplayATADetails(byte[] data)
{
var ataRevision = Encoding.ASCII.GetString(data, 54, 8).Trim();
var transportVersion = Encoding.ASCII.GetString(data, 76, 8).Trim();
var cylinders = BitConverter.ToUInt16(data, 2);
var heads = BitConverter.ToUInt16(data, 6);
var sectors = BitConverter.ToUInt16(data, 12);
var totalSectors = BitConverter.ToUInt32(data, 120);
var bytesPerSector = 512; // Typically 512 bytes
var multipleSectors = BitConverter.ToUInt16(data, 94);
var maxPIO = (data[102] >> 0) & 0xFF;
var maxDMA = (data[63] >> 0) & 0xFF;
var unformattedCapacity = (long)bytesPerSector * totalSectors / (1024 * 1024); // MB
string message = $"ATA Revision: {ataRevision}\r\n" +
$"Transport Version: {transportVersion}\r\n" +
$"Hard Disk Cylinders: {cylinders}\r\n" +
$"Hard Disk Heads: {heads}\r\n" +
$"Hard Disk Sectors: {sectors}\r\n" +
$"Total Sectors: {totalSectors}\r\n" +
$"Bytes Per Sector: {bytesPerSector}\r\n" +
$"Multiple Sectors: {multipleSectors}\r\n" +
$"Maximum PIO Mode: {maxPIO}\r\n" +
$"Maximum DMA Mode: {maxDMA}\r\n" +
$"Unformatted Capacity: {unformattedCapacity} MB";
MessageBox.Show(message, "ATA Details", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
Я хочу получите следующие данные:
Информация о поставщике,
Цилиндры жесткого диска,
Головки жесткого диска,
Головки жесткого диска,
p>
Секторы жесткого диска,
Версия ATA,
Транспортная версия,
Общее количество секторов,
Байт на сектор,
Размер буфера,
Несколько секторов, p>
Байты исправления ошибок,
Неформатированная емкость,
Максимальный режим PIO,
Максимальный режим многословного DMA,
Наивысшая возможная скорость передачи,
Согласованная скорость передачи,
Минимальное время передачи нескольких слов по DMA,
Рекомендуемое время передачи нескольких слов по DMA,
Минимальное время передачи PIO без IORDY,
Минимальное время передачи PIO с IORDY,
Управляющий байт ATA,
Значение контрольной суммы ATA,
Кто-нибудь знает, с помощью какого IOCTL я могу получить эти данные или причину ошибки в моем коде?
Подробнее здесь: https://stackoverflow.com/questions/787 ... in-c-sharp