我以管理员身份运行获取 HDD SMART 属性的程序,但收到此错误: 未能获得 S.M.A.R.T.数据。错误代码:5 错误消息:访问被拒绝。
为什么访问被拒绝?如何解决?程序似乎是正确的,如果不正确,请帮忙纠正。
void GetSMART()
{
// Открытие физического диска
int driveNumber = 0; // № диска
wstring drivePath = L"\\\\.\\PhysicalDrive" + std::to_wstring(driveNumber);
HANDLE hDrive = CreateFile(drivePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (hDrive == INVALID_HANDLE_VALUE) {
return;
}
// Получение S.M.A.R.T.
bool isGetData;
DWORD bytesReturned;
const int inParamsSize = sizeof(SENDCMDINPARAMS) - 1;
SENDCMDINPARAMS inParams = { 0 };
inParams.cBufferSize = READ_ATTRIBUTE_BUFFER_SIZE;
inParams.irDriveRegs.bFeaturesReg = READ_ATTRIBUTES;
inParams.irDriveRegs.bSectorCountReg = 1;
inParams.irDriveRegs.bSectorNumberReg = 1;
inParams.irDriveRegs.bCylLowReg = SMART_CYL_LOW;
inParams.irDriveRegs.bCylHighReg = SMART_CYL_HI;
inParams.irDriveRegs.bDriveHeadReg = 0xA0 | ((static_cast<BYTE>(driveNumber) & 1) << 4);
inParams.irDriveRegs.bCommandReg = SMART_CMD;
const int outParamsSize = sizeof(SENDCMDOUTPARAMS) - 1 + READ_ATTRIBUTE_BUFFER_SIZE;
SENDCMDOUTPARAMS outParamsAttributes[outParamsSize] = { 0 };
isGetData = DeviceIoControl(hDrive, SMART_RCV_DRIVE_DATA,
&inParams, inParamsSize, &outParamsAttributes, outParamsSize, &bytesReturned, NULL);
if (!isGetData) {
DWORD errorCode = GetLastError();
LPSTR errorMessage = nullptr;
DWORD result = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPSTR>(&errorMessage),
0,
nullptr
);
if (result != 0) {
std::cout << "Failed to get S.M.A.R.T. data. Error code: " << errorCode << std::endl;
std::cout << "Error message: " << errorMessage << std::endl;
}
else {
std::cout << "Failed to retrieve error message." << std::endl;
}
LocalFree(errorMessage);
CloseHandle(hDrive);
return;
}
}
为什么访问被拒绝?
因为I/O控制代码
SMART_RCV_DRIVE_DATA
在winioctl.h
头文件中定义为
#define SMART_RCV_DRIVE_DATA CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
请注意,
RequiredAccess
宏中的CTL_CODE
参数为FILE_READ_ACCESS | FILE_WRITE_ACCESS
。
如何解决?
为了解决该问题,您应该调用
CreateFile()
函数,并将 dwDesiredAccess
指定为 FILE_READ_DATA | FILE_WRITE_DATA
,而不仅仅是 GENERIC_READ
。
像这样:
HANDLE hDrive = CreateFile(drivePath.c_str(), FILE_READ_DATA | FILE_WRITE_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
GENERIC_READ | GENERIC_WRITE
也可以工作:
HANDLE hDrive = CreateFile(drivePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
无需以管理员身份运行。