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

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

2013-01-04 
哪位帮看看,这段MSDN上的C代码为什么在我的机器上起不了作用?代码源自:http://support.microsoft.com/kb/1

哪位帮看看,这段MSDN上的C代码为什么在我的机器上起不了作用?
代码源自: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说可以


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);
}


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

热点排行