eject.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // this file almost totally copied from MSDN
  2. #include <windows.h>
  3. #include <stdio.h>
  4. #include <winioctl.h>
  5. #define LOCK_TIMEOUT 3000 // 10 Seconds
  6. #define LOCK_RETRIES 20
  7. static HANDLE OpenVolume(TCHAR cDriveLetter)
  8. {
  9. HANDLE hVolume;
  10. UINT uDriveType;
  11. wchar_t szVolumeName[8] = {0};
  12. wchar_t szRootName[5] = {0};
  13. DWORD dwAccessFlags = 0;
  14. wsprintf(szRootName, L"%c:\\", cDriveLetter);
  15. uDriveType = GetDriveType(szRootName);
  16. switch(uDriveType) {
  17. case DRIVE_REMOVABLE:
  18. dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
  19. break;
  20. case DRIVE_CDROM:
  21. dwAccessFlags = GENERIC_READ;
  22. break;
  23. default:
  24. printf("Cannot eject. Drive type is incorrect.\n");
  25. return INVALID_HANDLE_VALUE;
  26. }
  27. wsprintf(szVolumeName, L"\\\\.\\%c:", cDriveLetter);
  28. hVolume = CreateFile( szVolumeName,
  29. dwAccessFlags,
  30. FILE_SHARE_READ | FILE_SHARE_WRITE,
  31. NULL,
  32. OPEN_EXISTING,
  33. 0,
  34. NULL );
  35. if (hVolume == INVALID_HANDLE_VALUE)
  36. printf("CreateFile error %d\n", GetLastError());
  37. return hVolume;
  38. }
  39. static BOOL CloseVolume(HANDLE hVolume)
  40. {
  41. return CloseHandle(hVolume);
  42. }
  43. static BOOL LockVolume(HANDLE hVolume)
  44. {
  45. DWORD dwBytesReturned;
  46. DWORD dwSleepAmount;
  47. int nTryCount;
  48. dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;
  49. // Do this in a loop until a timeout period has expired
  50. for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
  51. if (DeviceIoControl(hVolume,
  52. FSCTL_LOCK_VOLUME,
  53. NULL, 0,
  54. NULL, 0,
  55. &dwBytesReturned,
  56. NULL))
  57. return TRUE;
  58. Sleep(dwSleepAmount);
  59. }
  60. return FALSE;
  61. }
  62. static BOOL DismountVolume(HANDLE hVolume)
  63. {
  64. DWORD dwBytesReturned;
  65. return DeviceIoControl( hVolume,
  66. FSCTL_DISMOUNT_VOLUME,
  67. NULL, 0,
  68. NULL, 0,
  69. &dwBytesReturned,
  70. NULL);
  71. }
  72. static BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
  73. {
  74. DWORD dwBytesReturned;
  75. PREVENT_MEDIA_REMOVAL PMRBuffer;
  76. PMRBuffer.PreventMediaRemoval = fPreventRemoval;
  77. return DeviceIoControl( hVolume,
  78. IOCTL_STORAGE_MEDIA_REMOVAL,
  79. &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
  80. NULL, 0,
  81. &dwBytesReturned,
  82. NULL);
  83. }
  84. static int AutoEjectVolume(HANDLE hVolume)
  85. {
  86. DWORD dwBytesReturned;
  87. return DeviceIoControl( hVolume,
  88. IOCTL_STORAGE_EJECT_MEDIA,
  89. NULL, 0,
  90. NULL, 0,
  91. &dwBytesReturned,
  92. NULL);
  93. }
  94. BOOL EjectVolume(TCHAR cDriveLetter)
  95. {
  96. HANDLE hVolume;
  97. BOOL fAutoEject = FALSE;
  98. hVolume = OpenVolume(cDriveLetter);
  99. if (hVolume == INVALID_HANDLE_VALUE)
  100. return FALSE;
  101. // Lock and dismount the volume.
  102. if (LockVolume(hVolume) && DismountVolume(hVolume)) {
  103. // Set prevent removal to false and eject the volume.
  104. if (PreventRemovalOfVolume(hVolume, FALSE) && AutoEjectVolume(hVolume))
  105. fAutoEject = TRUE;
  106. }
  107. // Close the volume so other processes can use the drive.
  108. if (!CloseVolume(hVolume))
  109. return FALSE;
  110. if (fAutoEject) return TRUE;
  111. else return FALSE;
  112. }