昨天,在CSDN中看见帖子寻求解决挂载盘符的问题,今天把它搞定了。
      本文只要用最新的SDK(或者2k以上)然后定义Windows版本_WIN32_WINNT为0x0500以上就能编译通过了。
      改变盘符主要是用SetVolumeMountPointDeleteVolumeMountPoint 两个函数。DeleteVolumeMountPoint 很简单就不多说了。SetVolumeMountPoint 的使用主要是要找到被挂载设备的VolumeName。但是设备被卸载以后用GetVolumeNameForVolumeMountPoint根本取不到VolumeName,怎么办呢?
      微软XP的系统文件夹里面有一个叫diskpart.exe的命令行工具,用它可以改变盘符。那么它是怎么做到的呢?
简单的分析(用VC6自带的工具DEPENDS.EXE)就可以看见这个程序使用了很多Setup API函数,我判断使用SetupDiEnumDeviceInfo来取得VolumeName的ClassGUID,但是结果发现取到的ClassGUID和用GetVolumeNameForVolumeMountPoint获取的没有卸载前的VolumeName中的ClassGUID不一样。怎么办呢?
      没关系,让我们祭出屠龙刀:IDA Pro。如何反汇编分析不在本文的介绍了(挺麻烦,而我这人又比较懒嘿嘿)。我一阵海扁它,发现关键是要通过DefineDosDevice 函数将设备Attach到盘符上,然后用GetVolumeNameForVolumeMountPoint取到VolumeName,之后就可以用SetVolumeMountPoint将设备挂载到盘符上了。我把它写成了函数如果要加载盘符就可以使用(前提是盘符未被占用):
ChangeMountPoint( _T("H:\\"), _T("\\Device\\HarddiskVolume2"),true);
卸载的话用:
ChangeMountPoint( _T("H:\\"),NULL, false);
下面是ChangeMountPoint函数的实现:

bool ChangeMountPoint(LPCTSTR lpDriveLetter,LPCTSTR lpDevice,bool bAddMountPoint)
{
    bool bRet 
= false;
    TCHAR szDriveLetterAndSlash[
4= {0};
    TCHAR szDriveLetter[
3= {0};
    TCHAR szUniqueVolumeName[MAX_PATH] 
= {0};
    
if(lpDriveLetter && lpDevice)
    {
        szDriveLetter[
0= lpDriveLetter[0];
        szDriveLetter[
1= TEXT(':');
        szDriveLetter[
2= TEXT('\0');
        
        szDriveLetterAndSlash[
0= lpDriveLetter[0];
        szDriveLetterAndSlash[
1= TEXT(':');
        szDriveLetterAndSlash[
2= TEXT('\\');
        szDriveLetterAndSlash[
3= TEXT('\0');
        
if ( bAddMountPoint )
        {
            
//Try to Attach lpDevice to lpDriveLetter
            bRet = DefineDosDevice (DDD_RAW_TARGET_PATH, szDriveLetter,
                lpDevice);
            
            
if (bRet)
            {
                
if (!GetVolumeNameForVolumeMountPoint (szDriveLetterAndSlash,
                    szUniqueVolumeName,
                    MAX_PATH))
                {
                    
//Can't Find Attached lpDevice 's VolumeName
                    szUniqueVolumeName[0= '\0';
                }
                
                bRet 
= DefineDosDevice ( 
                    DDD_RAW_TARGET_PATH
|DDD_REMOVE_DEFINITION|
                    DDD_EXACT_MATCH_ON_REMOVE, szDriveLetter,
                    lpDevice);
                
                
if (!bRet)
                    
return bRet;
                
                bRet 
= SetVolumeMountPoint(szDriveLetterAndSlash, 
                    szUniqueVolumeName);
            }
        }
        
else
        {
            bRet 
= DeleteVolumeMountPoint (szDriveLetterAndSlash);
        }
    }
    
    
return bRet;
}
posted on 2006-01-10 09:39 孤独的夜 阅读(6397) 评论(18)  编辑 收藏 引用 所属分类: Windows SDK
Comments
  • # re: 在2K以上系统中挂载盘符
    moahi
    Posted @ 2006-01-12 21:30
    LPCTSTR 是什么?  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    孤独的夜
    Posted @ 2006-01-13 13:04
    LPCTSTR代表TChar。在定义了Unicode的情况下是宽字符,否则就是普通字符。  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    xucw
    Posted @ 2006-04-18 14:57
    请问如何把一个文件挂载成一个盘符呢??谢谢  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    xucw
    Posted @ 2006-04-18 14:57
    也就说一个文件夹,如C:\\Test,还有新的盘符的空间怎么控制呢?  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    孤独的夜
    Posted @ 2006-04-18 15:32
    新的盘符的空间就是文件夹所在盘的剩余空间,理论上可以使用ntfs的磁盘限额控制但是没有试过不晓得行不行。  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    afengsoft
    Posted @ 2006-04-26 15:41
    \\\Device\\HarddiskVolume2
    这里写错了,应该是\\Device\\HarddiskVolume2(代表D盘)才对,试了好多次才试出来,所以发上来告诉大家,少走弯路。
      回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    孤独的夜
    Posted @ 2006-04-26 19:18
    呵呵,是我粗心了,谢谢你的提醒。  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符

    Posted @ 2006-05-29 14:53
    请高手指点一下:
    \Device\HarddiskVolume2
    该路径出自哪?如果我想改变的是U盘的盘符,其路径又是什么?什么资料有详细的介绍?
    谢谢!
      回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    孤独的夜
    Posted @ 2006-06-05 11:20
    这个设备命名规则是微软定的,好像msdn里有?我记不清楚了。
    PS:我记得SoftIce中有个工具察看设备名的,你去安装好SoftIce,然后到开始菜单里面它的工具里应该就能找到。  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    aasoft
    Posted @ 2006-07-08 17:52
    我怎么在delphi下不能使用用SetVolumeMountPoint和DeleteVolumeMountPoint 两个函数,windows单元也已经使用了,操作系统是windows XP专业版,请各位为小弟出招,不胜感激!  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    孤独的夜
    Posted @ 2006-07-08 19:34
    汗~,不熟悉delphi,可能这两个函数不在windows单元,你到它的帮助中心搜索一下看看。  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    zzzz
    Posted @ 2007-04-29 09:22
    如何挂接别人机器上的文件?  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符[未登录]
    zz
    Posted @ 2007-05-09 14:29
    头文件是什么  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符[未登录]
    zz
    Posted @ 2007-05-09 14:31
    头文件是什么 编译环境是什么 我在vc6.0下怎么是这样的错误
    mount.cpp
    F:\WODECHENGXU\mount\mount.cpp(31) : error C2065: 'GetVolumeNameForVolumeMountPoint' : undeclared identifier
    F:\WODECHENGXU\mount\mount.cpp(47) : error C2065: 'SetVolumeMountPoint' : undeclared identifier
    F:\WODECHENGXU\mount\mount.cpp(53) : error C2065: 'DeleteVolumeMountPoint' : undeclared identifier
    Error executing cl.exe.

    mount.exe - 3 error(s), 0 warning(s)
      回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    孤独的夜
    Posted @ 2007-05-21 17:26
    1.挂接别人机器上的文件用Net
    WNetAddConnection 后 NetShareAdd。具体可以参考MSDN.
    2.本文只要用最新的SDK(或者2k以上)然后在stdafx.h里定义Windows版本为0x0500  回复  更多评论   
  • # re: 在2K以上系统中挂载盘符
    Programmer
    Posted @ 2009-07-03 13:55
    Instead of using DefineDosDevice() to get the unique volume name, you can use FindFirstVolume()/FindNextVolume()/FindVolumeClose() to enumate all volumes installed on the system.  回复  更多评论   
只有注册用户登录后才能发表评论。