首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

哪位帮看看,这段MSDN上的C代码为什么在小弟我的机器上起不了作用

2012-02-27 
哪位帮看看,这段MSDN上的C代码为什么在我的机器上起不了作用? - C++ Builder / Windows SDK/API代码源自:h

哪位帮看看,这段MSDN上的C代码为什么在我的机器上起不了作用? - C++ Builder / Windows SDK/API
代码源自:http://support.microsoft.com/kb/165721/zh-cn

我在BCB中建立了一个控制台程序:
#include <windows.h>
  #include <winioctl.h>
  #include <tchar.h>
  #include <stdio.h>

  // Prototypes

  BOOL EjectVolume(TCHAR cDriveLetter);

  HANDLE OpenVolume(TCHAR cDriveLetter);
  BOOL LockVolume(HANDLE hVolume);
  BOOL DismountVolume(HANDLE hVolume);
  BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent);
  BOOL AutoEjectVolume(HANDLE hVolume);
  BOOL CloseVolume(HANDLE hVolume);

  LPTSTR szVolumeFormat = TEXT("\\\\.\\%c:");
  LPTSTR szRootFormat = TEXT("%c:\\");
  LPTSTR szErrorFormat = TEXT("Error %d: %s\n");

  void ReportError(LPTSTR szMsg)
  {
  _tprintf(szErrorFormat, GetLastError(), szMsg);
  }

  HANDLE OpenVolume(TCHAR cDriveLetter)
  {
  HANDLE hVolume;
  UINT uDriveType;
  TCHAR szVolumeName[8];
  TCHAR szRootName[5];
  DWORD dwAccessFlags;

  wsprintf(szRootName, szRootFormat, cDriveLetter);

  uDriveType = GetDriveType(szRootName);
  switch(uDriveType) {
  case DRIVE_REMOVABLE:
  dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
  break;
  case DRIVE_CDROM:
  dwAccessFlags = GENERIC_READ;
  break;
  default:
  _tprintf(TEXT("Cannot eject. Drive type is incorrect.\n"));
  return INVALID_HANDLE_VALUE;
  }

  wsprintf(szVolumeName, szVolumeFormat, cDriveLetter);

  hVolume = CreateFile( szVolumeName,
  dwAccessFlags,
  FILE_SHARE_READ | FILE_SHARE_WRITE,
  NULL,
  OPEN_EXISTING,
  0,
  NULL );
  if (hVolume == INVALID_HANDLE_VALUE)
  ReportError(TEXT("CreateFile"));

  return hVolume;
  }

  BOOL CloseVolume(HANDLE hVolume)
  {
  return CloseHandle(hVolume);
  }

  #define LOCK_TIMEOUT 10000 // 10 Seconds
  #define LOCK_RETRIES 20

  BOOL LockVolume(HANDLE hVolume)
  {
  DWORD dwBytesReturned;
  DWORD dwSleepAmount;
  int nTryCount;

  dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;

  // Do this in a loop until a timeout period has expired
  for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
  if (DeviceIoControl(hVolume,
  FSCTL_LOCK_VOLUME,
  NULL, 0,
  NULL, 0,
  &dwBytesReturned,
  NULL))
  return TRUE;

  Sleep(dwSleepAmount);
  }

  return FALSE;
  }

  BOOL DismountVolume(HANDLE hVolume)
  {
  DWORD dwBytesReturned;

  return DeviceIoControl( hVolume,
  FSCTL_DISMOUNT_VOLUME,
  NULL, 0,
  NULL, 0,


  &dwBytesReturned,
  NULL);
  }

  BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
  {
  DWORD dwBytesReturned;
  PREVENT_MEDIA_REMOVAL PMRBuffer;

  PMRBuffer.PreventMediaRemoval = fPreventRemoval;

  return DeviceIoControl( hVolume,
  IOCTL_STORAGE_MEDIA_REMOVAL,
  &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
  NULL, 0,
  &dwBytesReturned,
  NULL);
  }

  AutoEjectVolume(HANDLE hVolume)
  {
  DWORD dwBytesReturned;

  return DeviceIoControl( hVolume,
  IOCTL_STORAGE_EJECT_MEDIA,
  NULL, 0,
  NULL, 0,
  &dwBytesReturned,
  NULL);
  }

  BOOL EjectVolume(TCHAR cDriveLetter)
  {
  HANDLE hVolume;

  BOOL fRemoveSafely = FALSE;
  BOOL fAutoEject = FALSE;

  // Open the volume.
  hVolume = OpenVolume(cDriveLetter);
  if (hVolume == INVALID_HANDLE_VALUE)
  return FALSE;

  // Lock and dismount the volume.
  if (LockVolume(hVolume) && DismountVolume(hVolume)) {
  fRemoveSafely = TRUE;

  // Set prevent removal to false and eject the volume.
  if (PreventRemovalOfVolume(hVolume, FALSE) &&
  AutoEjectVolume(hVolume))
  fAutoEject = TRUE;
  }

  // Close the volume so other processes can use the drive.
  if (!CloseVolume(hVolume))
  return FALSE;

  if (fAutoEject)
  printf("Media in Drive %c has been ejected safely.\n",
  cDriveLetter);
  else {
  if (fRemoveSafely)
  printf("Media in Drive %c can be safely removed.\n",
  cDriveLetter);
  }

  return TRUE;
  }

  void Usage()
  {
  printf("Usage: Eject <drive letter>\n\n");
  return ;
  }

  void main(int argc, char * argv[])
  {
  if (argc != 2) {
  Usage();
  return ;
  }

  if (!EjectVolume(argv[1][0]))
  printf("Failure ejecting drive %c.\n", argv[1][0]);

  return ;
  }


我的USB盘为“G”盘,
编译后我执行:
Project1.exe G
结果显示:Media in Drive G has been ejected safely.
但我到我的电脑中看见,这个“G”盘依然存在,还能打开访问里面的内容,为什么会这样?

[解决办法]
http://forum.driverdevelop.com/read.php?tid=92819

没试过。LZ说可以

C/C++ code
Dismount后应该发广播消息吧?偶做虚拟盘的时候在MOUNT后调用BroadcastDeviceChange( DBT_DEVICEARRIVAL, nDriverNo, 0 );Dismount后调用:BroadcastDeviceChange( DBT_DEVICEREMOVECOMPLETE, nDriverNo, 0 );void BroadcastDeviceChange( WPARAM message, int nDosDriveNo, DWORD driveMap ){DEV_BROADCAST_VOLUME dbv;char root[] = {0, \':\', \'\\\\\', 0 };DWORD dwResult;LONG event = 0;int i;if (message == DBT_DEVICEARRIVAL) event = SHCNE_DRIVEADD;if (message == DBT_DEVICEREMOVECOMPLETE) event = SHCNE_DRIVEREMOVED;if (driveMap == 0){root[0] = nDosDriveNo + \'A\';SHChangeNotify(event, SHCNF_PATH, root, NULL);}else{for (i = 0; i < 26; i++){if (driveMap & (1 << i)){root[0] = i + \'A\';SHChangeNotify(event, SHCNF_PATH, root, NULL);}}}dbv.dbcv_size = sizeof(dbv); dbv.dbcv_devicetype = DBT_DEVTYP_VOLUME; dbv.dbcv_reserved = 0;dbv.dbcv_unitmask = (driveMap != 0) ? driveMap : (1 << nDosDriveNo);dbv.dbcv_flags = 0; SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), 0, 500, &dwResult);} 


[解决办法]
测试了你的代码,没有问题,确实是可以删除移动存储设备的.你再试试.这个跟系统的移除有区别.这个删除以后,盘符还在,但是,设备已经安全删除了,从磁盘的卷标可以看出来

热点排行