Safely remove a USB drive using the Win32 API?

前端 未结 5 1364
盖世英雄少女心
盖世英雄少女心 2020-11-27 04:03

How do I remove a USB drive using the Win32 API? I do a lot of work on embedded systems and on one of these I have to copy my programs on a USB stick and insert it into the

相关标签:
5条回答
  • 2020-11-27 04:19
    #include<SetupAPI.h>
    #include <windows.h>  
    #include<initguid.h>
    #include <newdev.h>
    #include <Cfgmgr32.h>
    
    #pragma comment(lib, "Cfgmgr32.lib")
    #pragma comment(lib, "Setupapi.lib")
    #pragma comment(lib, "Newdev.lib")
    
    int RemoveDevice(const GUID *guid, const wchar_t *hwID) {
        HDEVINFO m_hDevInfo;
        SP_DEVICE_INTERFACE_DATA         spdid;
        SP_DEVINFO_DATA                  spdd;
        DWORD                            dwSize;
        BYTE Buf[1024];
        PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd =
            (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
    
        printf("try to remove device::%ws\n", hwID);
    
        m_hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT| DIGCF_DEVICEINTERFACE);
        if (m_hDevInfo == INVALID_HANDLE_VALUE)
        {
            printf("GetClassDevs Failed!\n");
            return 0;
        }
        spdid.cbSize = sizeof(spdid);
        for (int i = 0; SetupDiEnumDeviceInterfaces(m_hDevInfo, NULL, guid, i, &spdid); i++) {
            dwSize = 0;
            SetupDiGetDeviceInterfaceDetail(m_hDevInfo,
                &spdid, NULL, 0, &dwSize, NULL);
            if (dwSize != 0 && dwSize <= sizeof(Buf)) {
                pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
    
                ZeroMemory((PVOID)&spdd, sizeof(spdd));
                spdd.cbSize = sizeof(spdd);
    
                long res =
                    SetupDiGetDeviceInterfaceDetail(m_hDevInfo, &
                        spdid, pspdidd,
                        dwSize, &dwSize,
                        &spdd);
                if (res) {
                    OLECHAR* guidString;
                    OLECHAR* guidString2;
                    StringFromCLSID(&spdd.ClassGuid, &guidString);
                    StringFromCLSID(&spdid.InterfaceClassGuid, &guidString2);
                    printf("%d, %ws, %ws, %ws\n", spdd.DevInst, pspdidd->DevicePath, guidString, guidString2);
                    CoTaskMemFree(guidString);
                    CoTaskMemFree(guidString2);
                    if (!memcmp(pspdidd->DevicePath, hwID, 2 * lstrlenW(hwID))) {
                        DEVINST DevInstParent = 0;
                        res = CM_Get_Parent(&DevInstParent, spdd.DevInst, 0);
                        for (long tries = 0; tries < 10; tries++) {
                            // sometimes we need some tries...
                            WCHAR VetoNameW[MAX_PATH];
                            PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown;
                            VetoNameW[0] = 0;
    
                            res = CM_Request_Device_EjectW(DevInstParent,
                                &VetoType, VetoNameW, MAX_PATH, 0);
                            if ((res == CR_SUCCESS &&
                                VetoType == PNP_VetoTypeUnknown)) {
                                printf("remove %ws success!\n", pspdidd->DevicePath);
                                SetupDiDestroyDeviceInfoList(m_hDevInfo);
                                return 1;
                            }
                            Sleep(500); // required to give the next tries a chance!
                        }
                        break;
                    }
                }
            }
        }
        printf("Remove Device Failed!\n");
        SetupDiDestroyDeviceInfoList(m_hDevInfo);
        return 0;
    }
    
    int main(){
        GUID GUID_DEVINTERFACE_USB_HUB;
        CLSIDFromString(L"F18A0E88-C30C-11D0-8815-00A0C906BED8", &GUID_DEVINTERFACE_USB_HUB);
    
        RemoveDevice(&GUID_DEVINTERFACE_USB_HUB, L"\\\\?\\usb#root_hub30");
        return 0;
    }
    

    refrences:

    How to Prepare a USB Drive for Safe Removal

    GUID_DEVINTERFACE

    0 讨论(0)
  • 2020-11-27 04:22

    It looks like Sync lets you specify -e to eject removable drives. While not a win32 API, you could probably just call sync -e [drive_letter] from your makefile.

    0 讨论(0)
  • 2020-11-27 04:25

    Here's a solution in Delphi, that I've modified and put into a service for use in a very large enterprise. Go to: link text

    Look for "scapi (Setup & Config Manager API)", and download it. There will be a demo program called USBView that will get you on your way. If you have Delphi, this also includes a TUSBDeviceTree component that you can use to gather information about a USB device when.

    Regards

    0 讨论(0)
  • 2020-11-27 04:30

    You can use the CM_Request_Device_Eject() function as well as some other possibilities. Consult the following projects and articles:

    DevEject: Straightforward. http://www.withopf.com/tools/deveject/

    A useful CodeProject article: http://www.codeproject.com/KB/system/RemoveDriveByLetter.aspx

    0 讨论(0)
  • 2020-11-27 04:35

    Here is a technet article about removable storage media. Look for DismountNtmsMedia.

    0 讨论(0)
提交回复
热议问题