nsresult sbWinDeviceEject(DEVINST aDevInst) { CONFIGRET cfgRet; // Try ejecting the device three times. WCHAR vetoName[MAX_PATH]; PNP_VETO_TYPE vetoType; bool ejected = PR_FALSE; for (int i = 0; i < 3; i++) { // Try ejecting using CM_Request_Device_Eject. cfgRet = CM_Request_Device_EjectW(aDevInst, &vetoType, vetoName, MAX_PATH, 0); if (cfgRet == CR_SUCCESS) { ejected = PR_TRUE; break; } // Wait for 1/10 second to give the device time to handle the eject. // This probably isn't needed, but all the examples I saw that used // the functions always put in a delay between calls at least for retries Sleep(100); // Try ejecting using CM_Query_And_Remove_SubTree. cfgRet = CM_Query_And_Remove_SubTreeW(aDevInst, &vetoType, vetoName, MAX_PATH, CM_REMOVE_NO_RESTART); if (cfgRet == CR_SUCCESS) { ejected = PR_TRUE; break; } // Wait 1/2 before retrying so we don't just slam the device with a bunch // of eject/remove requests and fail out. Sleep(500); } // Try one last time and let the PnP manager notify the user of failure. if (!ejected) { cfgRet = CM_Request_Device_Eject(aDevInst, NULL, NULL, 0, 0); NS_ENSURE_TRUE(cfgRet == CR_SUCCESS, NS_ERROR_FAILURE); } return NS_OK; }
static BOOL eject_drive_letter(WCHAR DriveLetter) { LPWSTR szRootPath = L"X:\\", szDevicePath = L"X:", szVolumeAccessPath = L"\\\\.\\X:"; WCHAR szDosDeviceName[MAX_PATH]; long DeviceNumber, res, tries; HANDLE hVolume; STORAGE_DEVICE_NUMBER sdn; DWORD dwBytesReturned; DEVINST DevInst; ULONG Status; ULONG ProblemNumber; UINT DriveType; PNP_VETO_TYPE VetoType; WCHAR VetoNameW[MAX_PATH]; BOOL bSuccess; DEVINST DevInstParent; szRootPath[0] = DriveLetter; szDevicePath[0] = DriveLetter; szVolumeAccessPath[4] = DriveLetter; DeviceNumber = -1; hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hVolume == INVALID_HANDLE_VALUE) { PyErr_SetString(PyExc_ValueError, "Invalid handle value for drive letter"); return FALSE; } dwBytesReturned = 0; res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL); if ( res ) { DeviceNumber = sdn.DeviceNumber; } CloseHandle(hVolume); if ( DeviceNumber == -1 ) { PyErr_SetString(PyExc_ValueError, "Can't find drive number"); return FALSE; } res = QueryDosDevice(szDevicePath, szDosDeviceName, MAX_PATH); if ( !res ) { PyErr_SetString(PyExc_ValueError, "Can't find dos device"); return FALSE; } DriveType = GetDriveType(szRootPath); DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, DriveType, szDosDeviceName); if (DevInst == 0) return FALSE; DevInstParent = 0; Status = 0; ProblemNumber = 0; bSuccess = FALSE; res = CM_Get_Parent(&DevInstParent, DevInst, 0); for ( tries = 0; tries < 3; tries++ ) { VetoNameW[0] = 0; res = CM_Request_Device_EjectW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, 0); bSuccess = (res==CR_SUCCESS && VetoType==PNP_VetoTypeUnknown); if ( bSuccess ) { break; } Sleep(500); // required to give the next tries a chance! } if (!bSuccess) PyErr_SetString(PyExc_ValueError, "Failed to eject drive after three tries"); return bSuccess; }
int removeDrive(char drive) { char driveLetter = drive; driveLetter &= ~0x20; if ( driveLetter < 'A' || driveLetter > 'Z' ) { return 1; } wchar_t szRootPath[] = L"X:\\"; // "X:\" -> for GetDriveType szRootPath[0] = driveLetter; wchar_t szDevicePath[] = L"X:"; // "X:" -> for QueryDosDevice szDevicePath[0] = driveLetter; wchar_t szVolumeAccessPath[] = L"\\\\.\\X:"; // "\\.\X:" -> to open the volume szVolumeAccessPath[4] = driveLetter; long DeviceNumber = -1; HANDLE hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); if (hVolume == INVALID_HANDLE_VALUE) { return 1; } STORAGE_DEVICE_NUMBER sdn; DWORD dwBytesReturned = 0; long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL); if ( res ) { DeviceNumber = sdn.DeviceNumber; } CloseHandle(hVolume); if ( DeviceNumber == -1 ) { return 1; } UINT DriveType = GetDriveType(szRootPath); char szDosDeviceName[MAX_PATH]; res = QueryDosDevice(szDevicePath, (LPWSTR)szDosDeviceName, MAX_PATH); if ( !res ) { return 1; } DEVINST DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, DriveType, szDosDeviceName); if ( DevInst == 0 ) { return 1; } PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown; WCHAR VetoNameW[MAX_PATH]; VetoNameW[0] = 0; bool bSuccess = false; DEVINST DevInstParent = 0; res = CM_Get_Parent(&DevInstParent, DevInst, 0); for ( long tries=1; tries<=3; tries++ ) { VetoNameW[0] = 0; res = CM_Request_Device_EjectW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, 0); bSuccess = (res==CR_SUCCESS && VetoType==PNP_VetoTypeUnknown); if ( bSuccess ) { break; } Sleep(500); } if ( bSuccess ) { printf("Success\n\n"); return 0; } printf("failed\n"); printf("Result=0x%2X\n", res); if ( VetoNameW[0] ) { printf("VetoName=%ws)\n\n", VetoNameW); } return 1; }