1

I run my program that gets HDD SMART attributes as admin, but get this error: Failed to get S.M.A.R.T. data. Error code: 5 Error message: Access is denied.

Why access is denied?How to fix it?Program seems to be correct,if not,please help to correct it.

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;
    }
}
2
  • Why access is denied? My guess is you need UAC elevation. Commented May 19, 2023 at 14:12
  • but I run my app as admin Commented May 20, 2023 at 20:09

1 Answer 1

0

Why access is denied?

Because the I/O control code SMART_RCV_DRIVE_DATA is defined in the winioctl.h header file as

#define SMART_RCV_DRIVE_DATA            CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

Note that RequiredAccess parameter in the CTL_CODE macro is FILE_READ_ACCESS | FILE_WRITE_ACCESS.

How to fix it?

In order to fix the problem, you should call CreateFile() function specifying dwDesiredAccess as FILE_READ_DATA | FILE_WRITE_DATA, not just GENERIC_READ. Like that:

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 also will work:

HANDLE hDrive = CreateFile(drivePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);

Running it as Administrator is unnecessary.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.