使用DeviceIoControl读取HDD SMART属性

问题描述 投票:0回答:1

我以管理员身份运行获取 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;
    }
}
c++ hard-drive deviceiocontrol
1个回答
0
投票

为什么访问被拒绝?

因为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);

无需以管理员身份运行。

© www.soinside.com 2019 - 2024. All rights reserved.