使用带有 ATA_PASS_THROUGH_EX 的 DeviceIoControl() 的 SECURITY_SET_PASSWORD 失败

Posted

技术标签:

【中文标题】使用带有 ATA_PASS_THROUGH_EX 的 DeviceIoControl() 的 SECURITY_SET_PASSWORD 失败【英文标题】:SECURITY_SET_PASSWORD using DeviceIoControl() with ATA_PASS_THROUGH_EX failed 【发布时间】:2015-09-22 09:57:05 【问题描述】:

我已经使用 ATA 命令 SECURITY_SET_PASSWORD 在 DeviceIoControl() 函数中尝试了 ATA_PASS_THROUGH_EX 或 ATA_PASS_THROUGH_DIRECT,但它总是以 GetLastError()=87(无效参数)失败。但是 ATA 命令 IDENTIFY 总是成功的。

操作系统环境:Windows 8.1 64bit,Visual Studio 2010,我的应用程序有管理员权限。

我的目标是在 64 位 Windows 8.1 中发出 SECURITY ERASE UNIt 就像这个页面:https://ata.wiki.kernel.org/index.php/ATA_Secure_Erase

像上面的网页一样,当我尝试在 ubuntu live CD 中使用“hdparm”来发出安全擦除时,相同的硬件和相同的 SSD 没有问题。

请您指导我的代码有什么问题?

    m_h = CreateFile("\\\\.\\PhysicalDrive1", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);  
    if ( m_h == INVALID_HANDLE_VALUE ) 
        return 0;

#if 1
    char buffer[512 + sizeof(ATA_PASS_THROUGH_EX)] =  0 ;

    ATA_PASS_THROUGH_EX& PTE = *(ATA_PASS_THROUGH_EX *)buffer;

    PTE.Length = sizeof(PTE);
    PTE.DataTransferLength = 512;
    PTE.DataBufferOffset = sizeof(ATA_PASS_THROUGH_EX);
    PTE.TimeOutValue = 10;
    PTE.AtaFlags = ATA_FLAGS_DATA_OUT | ATA_FLAGS_DRDY_REQUIRED;

    IDEREGS* ir = (IDEREGS*)PTE.CurrentTaskFile;
    ir->bCommandReg = 0xF1;

    strcpy(buffer + sizeof(ATA_PASS_THROUGH_EX) + 2, "test");

    DWORD bytes = 0;
    if (DeviceIoControl(m_h, IOCTL_ATA_PASS_THROUGH, &buffer, sizeof(buffer), &buffer, sizeof(buffer), &bytes, 0) == 0 ) 
        DWORD er = GetLastError();
        printf("error: %d\n", GetLastError());
        return false;
    
#else   
    DWORD dataSize = sizeof(ATA_PASS_THROUGH_DIRECT) + 512;
    ATA_PASS_THROUGH_DIRECT* pPTD = (ATA_PASS_THROUGH_DIRECT*) VirtualAlloc(NULL, dataSize, MEM_COMMIT, PAGE_READWRITE);

    pPTD->Length = sizeof(ATA_PASS_THROUGH_DIRECT); 
    pPTD->DataTransferLength = 512; 
    pPTD->DataBuffer = ((char*)pPTD) + sizeof(ATA_PASS_THROUGH_DIRECT); // sizeof(ATA_PASS_THROUGH_DIRECT);
    pPTD->TimeOutValue =  10;
    pPTD->AtaFlags = ATA_FLAGS_DATA_OUT | ATA_FLAGS_DRDY_REQUIRED;
    pPTD->CurrentTaskFile[1] = 0x01;
    pPTD->CurrentTaskFile[6] = 0xF1;

    strcpy( ((char*)pPTD->DataBuffer) + 2, "test");

    DWORD bytes = 0;
    if (!DeviceIoControl(m_h, IOCTL_ATA_PASS_THROUGH_DIRECT,  pPTD,  dataSize, pPTD, dataSize, &bytes, NULL)) 
        printf("error: %d\n", GetLastError());
        return false;
    
#endif  
    return true;

【问题讨论】:

【参考方案1】:

我认为操作系统阻止了这些 ATA 命令:SECURITY SET PASSWORD、SECURITY ERASE UNIT。因为我确实在 Windows 7 32bit 和 Windows 7 64bit 上成功运行了上面的程序,但是在 Windows 8(32bit/64bit)和 Windows 10(32bit/64bit)中,相同的程序显示无效参数错误(错误代码 87)。

【讨论】:

是的,看起来是这样:social.msdn.microsoft.com/Forums/windowsdesktop/en-US/…

以上是关于使用带有 ATA_PASS_THROUGH_EX 的 DeviceIoControl() 的 SECURITY_SET_PASSWORD 失败的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 uuencode 的“sendmail”发送邮件,并带有主题

HBase - 使用带有值列表的一列与使用带有列列表的一列族的优缺点是啥?

如何使用带有或不带有 Appium 的 Robot Framework 集成 WinAppDriver?

使用带有 ajax Rest 调用的 Spring CSRF 和带有 Thymeleaf 的 HTML 页面

如何在带有 React 的 Typescript/JSX 中使用带有箭头函数的泛型?

优化数据库有啥更好的方法:使用带有不同过滤器的一堆存储过程,还是使用带有 if 条件的单个存储过程?