全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:9289
推到 Plurk!
推到 Facebook!

透過 ATA Commands 取得硬碟資訊 IOCTL_ATA_PASS_THROUGH

缺席
ZongDe
一般會員


發表:9
回覆:11
積分:4
註冊:2002-11-27

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-09-17 10:45:14 IP:61.14.xxx.xxx 訂閱
ATA_NBATA DT - 1ATA DT - 2

如上圖,我想透過ATA Commands取的硬碟相關資訊,該如何做到.
有人有相關經驗嗎? 是否可以給各方向..

我有嘗試透下過IOCTL_ATA_PASS_THROUGH的方式,但是回傳的Error Code 是 5,查MSDN的意思是拒絕存取.
難道一定要透過driver層才可以嗎?
以下附上sample code...

這是計算硬碟大小的,可執行
[code cpp]
void __fastcall TForm1::btnDiskSizeClick(TObject *Sender)
{
Memo1->Clear();
HANDLE hDev;
BOOL bRet;
DISK_GEOMETRY pdg;
DWORD rByte;
//SECURITY_ATTRIBUTES SA; // Security attributes
char drvName[] = "\\\\.\\PhysicalDrive0";
hDev = CreateFile( drvName, // Object Name: Point Physical HDD 0
0, // Access Mode: 0 for Devices
FILE_SHARE_READ | FILE_SHARE_WRITE, // Shared Mode:
0, // Security Attributes: NULL can not be inherited(繼承)
OPEN_EXISTING, // Creation Disposition
0, // File flags and attributes
NULL); // Do not copy file attributes
if (hDev == INVALID_HANDLE_VALUE)
{
Memo1->Lines->Add("Open PHYSICALDRIVE0 handle failed!");
return;
}
bRet = DeviceIoControl( hDev,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&pdg,
sizeof(pdg),
&rByte,
NULL);
if (!bRet)
{
Memo1->Lines->Add("DeviceIoControl Failed!");
//Memo1->Lines->Add("GetLastError: " IntToHex(GetLastError(), 8));
return;
}
char buf[64] = {0};
ULONGLONG dwDiskSize;
sprintf(buf, "Cylinders = %I64d", pdg.Cylinders);
Memo1->Lines->Add(buf);
Memo1->Lines->Add("Tracks Per Cylinder = " IntToStr(pdg.TracksPerCylinder));
Memo1->Lines->Add("Sectors Per Track = " IntToStr(pdg.SectorsPerTrack));
Memo1->Lines->Add("Bytes Per Sector = " IntToStr(pdg.BytesPerSector));
dwDiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder * \
(ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;
sprintf(buf, "Physcial Disk Size = %I64d Bytes = %I64d Mb", dwDiskSize, dwDiskSize/(1024 * 1024));
Memo1->Lines->Add(buf);
CloseHandle(hDev);
}
[/code]

以下是透過IOCTL_ATA_PASS_THROUGH的方式

[code cpp]
void __fastcall TForm1::btnATAClick(TObject *Sender)
{
Memo1->Clear();
HANDLE hDev;
BOOL bRet;
ATA_PASS_THROUGH_EX apt;
DWORD rByte;
//SECURITY_ATTRIBUTES SA; // Security attributes
char drvName[] = "\\\\.\\PhysicalDrive0";
hDev = CreateFile( drvName, // Object Name: Point Physical HDD 0
0, // Access Mode: 0 for Devices
FILE_SHARE_READ | FILE_SHARE_WRITE, // Shared Mode:
0, // Security Attributes: NULL can not be inherited(繼承)
OPEN_EXISTING, // Creation Disposition
0, // File flags and attributes
NULL); // Do not copy file attributes
if (hDev == INVALID_HANDLE_VALUE)
{
Memo1->Lines->Add("Open PHYSICALDRIVE0 handle failed!");
return;
}
//
// CMD,CYL default to SMART, changed by P?IDENTIFY and CHECK_POWER_MODE
//IDEREGS regs;
//memset(®s, 0, sizeof(regs));
//regs.bCommandReg = 0xEC;//ATA_IDENTIFY_DEVICE;
//regs.bCylLowReg = regs.bCylHighReg = 0;
//regs.bSectorCountReg = 1;
//
ATA_PASS_THROUGH_EX_WITH_BUFFERS ab;
memset(&ab, 0, sizeof(ab));
ab.apt.Length = sizeof(ATA_PASS_THROUGH_EX);
ab.apt.TimeOutValue = 10;
unsigned size = offsetof(ATA_PASS_THROUGH_EX_WITH_BUFFERS, ucDataBuf);
ab.apt.DataBufferOffset = size;
ab.apt.AtaFlags = ATA_FLAGS_DATA_IN;
ab.apt.DataTransferLength = 512;
size = 512;
ab.ucDataBuf[0] = 0xcf;
ab.apt.CurrentTaskFile[1] = 1;
ab.apt.CurrentTaskFile[3] = ab.apt.CurrentTaskFile[4] = 0;
ab.apt.CurrentTaskFile[6] = 0xEC;
bRet = DeviceIoControl( hDev,
IOCTL_ATA_PASS_THROUGH,
&ab,
size,
&ab,
size,
&rByte,
NULL);
if (!bRet) // 這裡回傳failed
{
long err = GetLastError(); // 取得拒絕存取的訊息
Memo1->Lines->Add("DeviceIoControl Failed! " IntToStr(err));
//Memo1->Lines->Add("GetLastError: " IntToHex(GetLastError(), 8));
return;
}
}
[/code]
ZongDe
一般會員


發表:9
回覆:11
積分:4
註冊:2002-11-27

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-09-19 16:38:31 IP:61.14.xxx.xxx 訂閱

找到方法了
http://smartmontools.sourceforge.net/

目前已經可以下 ATA Command -- Identify 並且取回512 bytes.
系統時間:2024-04-20 2:52:33
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!