繁体   English   中英

在 C/C++ 中如何以编程方式检测 SATA SSD 在 Windows 中的插入和拔出?

[英]In C/C++ how to programmatically detect SATA SSD plug in and unplug in Windows?

我正在尝试编写一个 C/C++ 程序来检测 Windows 7 中的新 SATA SSD(固态驱动器)连接。

这款 SATA SSD 还附带一根 SATA-USB 电缆。 我已将 SATA 端连接到 SATA SDD,将 USB 端连接到我的计算机。 这样做我已经能够通过使用 Windows 消息系统检测WM_DEVICECHANGE消息和关联的DBT_DEVICEARRIVAL事件来检测 SATA SDD 连接和移除。 为此,我还使用了RegisterDeviceNotification来注册设备(即 SATA SSD),以便顶级窗口接收设备类型DBT_DEVTYP_DEVICEINTERFACE通知以及 SATA SSD 的 classguid。

但是,当我尝试将 SATA SDD 连接到计算机主板上的 SATA 端口时,我的程序不起作用。

在 C/C++ 中,如何检测 SATA SSD 在 Windows 中的插入和拔出?

通常,将 SSD 驱动器连接到通电计算机上的 SATA 端口是一个坏主意。 SATA 控制器必须具有热插拔功能才能执行此操作。 但是您可以扫描 deviceclass 并从该类中找到所有设备,它可以处理所有有趣的设备。 我发布了可以执行此操作的代码示例:

bool FindConnectedRemovableUsbstorDevices(std::list<std::wstring>& UsbList)
{
std::wstring ClassGuidString(L"{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}");
GUID ClassGuid;
BYTE buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA_W pspdidd = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(buf);
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD size;
SP_DEVINFO_DATA dev_data;
DWORD properties;


if(NOERROR != CLSIDFromString(ClassGuidString.c_str(), &ClassGuid))
    return false;

HDEVINFO dev_info = INVALID_HANDLE_VALUE;
dev_info = SetupDiGetClassDevs(&ClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if (dev_info == INVALID_HANDLE_VALUE)
    return false;

DWORD index = 0;
BOOL ret = FALSE;

spdid.cbSize = sizeof(spdid);

while (true)
{
    ret = SetupDiEnumDeviceInterfaces(dev_info, NULL, &ClassGuid, index, &spdid);
    if (!ret)
        break;

    size = 0;
    SetupDiGetDeviceInterfaceDetail(dev_info, &spdid, NULL, 0, &size, NULL);
    //Get required size

    if (size == 0 || size >= sizeof(buf))
        continue;
    //prepare structs
    ZeroMemory(reinterpret_cast<PVOID>(pspdidd), 1024);
    pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!

    ZeroMemory(reinterpret_cast<PVOID>(&spdd), sizeof(spdd));
    spdd.cbSize = sizeof(spdd);

    BOOL res = SetupDiGetDeviceInterfaceDetail(dev_info, &spdid, pspdidd, size, &size, &spdd);
    //Get info
    if (!res)
        continue;

    HANDLE drive = CreateFileW(pspdidd->DevicePath, FILE_READ_ATTRIBUTES,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, 0, NULL);//open device
    if (drive == INVALID_HANDLE_VALUE)
        continue;

    printf("\n%S\r\n", pspdidd->DevicePath);

    DWORD bytes_returned = 0;
    BOOL b = DeviceIoControl(drive, IOCTL_STORAGE_CHECK_VERIFY2, NULL, 0, NULL, 0, &bytes_returned, NULL);
    if (!b) //check is card reader?
    {
        printf("IOCTL_STORAGE_CHECK_VERIFY2 error = %d\r\n", GetLastError());
        goto stop_process_device;
    }

    bytes_returned = 0;
    STORAGE_DEVICE_NUMBER sdn;
    //Get Drive number
    b = DeviceIoControl(drive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &bytes_returned, NULL);
    if (!b)
        goto stop_process_device;
    RtlZeroMemory(&dev_data, sizeof(SP_DEVINFO_DATA));
    dev_data.cbSize = sizeof(dev_data);
    if (SetupDiEnumDeviceInfo(dev_info, sdn.DeviceNumber, &dev_data))
    {
        //check property
        b = SetupDiGetDeviceRegistryProperty(dev_info, &dev_data, SPDRP_REMOVAL_POLICY, NULL,
            reinterpret_cast<PBYTE>(&properties), sizeof(properties), NULL);
        if (b && properties != CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL)
        {
            UsbList.push_back(pspdidd->DevicePath);
            printf("REMOVAL\r\n");
        }
    }
stop_process_device:
    CloseHandle(drive);
    index++;
}
SetupDiDestroyDeviceInfoList(dev_info);
return true;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM