大家好啊,向大家请教个问题,如何识别移动硬盘的盘符;
下面代码主要功能是:每有移动存储设备插入电脑,接受到一个消息,
通过API函数禁用移动存储设备;移动硬盘一直无法识别
#include <Dbt.h>
#include <Winioctl.h>//查找可移动磁盘
CString CUSBMngDlg::FindFdisk()
{
CString strdir="";
for(char cc='A';cc<='Z';cc++)
{
strdir.Format("%c:",cc);
if(GetDriveType((LPCTSTR)strdir)==DRIVE_REMOVABLE) //只能识别U盘,无法识别移动硬盘
//if(GetDriveType((LPCTSTR)strdir)==DRIVE_FIXED) 
return strdir;
    }
    return strdir="";
}//每当有优盘插入时,接收一次系统发给的消息
LRESULT CUSBMngDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
if(message == WM_DEVICECHANGE)  
{  
switch(wParam)  
{  
case DBT_DEVICEARRIVAL: //设备插入消息 
{
HANDLE hDevice;
DWORD dwOutBytes;
bool bResult;
            CString logicalDisk; m_NewFdisk = FindFdisk();

//if(m_NewFdisk != m_OldFdisk && m_NewFdisk!= "")
//if(m_NewFdisk !=“”)
if (m_NewFdisk !="")
{  
logicalDisk = "\\\\.\\"+m_NewFdisk;
    hDevice = CreateFile(
logicalDisk,                                 //要打开的驱动名称
GENERIC_READ|GENERIC_WRITE,                  //访问方式
FILE_SHARE_READ|FILE_SHARE_WRITE,            //共享方式
NULL,                                        //安全描述符指针
OPEN_EXISTING,                               //创建方式
0,                                           //文件属性及标志
NULL                                         //模板文件的句柄
);

   bResult = DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&dwOutBytes,(LPOVERLAPPED)NULL); 
} if(m_NewFdisk!="")
{
m_OldFdisk=m_NewFdisk;
}
else
{
m_OldFdisk="";
}
}
//break;  
}


return CDialog::WindowProc(message, wParam, lParam);
}

解决方案 »

  1.   

    移动硬盘的type就是DRIVE_FIXED。得用其他方法识别,比如判断是不是USB设备等
      

  2.   

    谢谢楼上朋友的回复,
    我用//if(GetDriveType((LPCTSTR)strdir)==DRIVE_FIXED)也不可以啊,
    还有个问题就是,优盘是获取一个盘符,
    移动硬盘获取多个盘符,但是只能接受系统的一个消息吧
      

  3.   

    GetDriveType是针对逻辑盘符的。依靠我的记忆,DBT_DEVICEARRIVAL也是对应逻辑盘符的,有几个盘符就有几次消息。
    GetDriveType(strdir)的参数strdir请用“X:\\”的形式,所以逻辑盘符都能得到属性,与是否移动硬盘没有关系另外给你个建议用GetLogicalDrives可以带到当前的所有逻辑盘符,不需要用for(char cc='A';cc <='Z';cc++) 全部循环
      

  4.   

    对于只有一块硬盘的电脑可以这么想……首先获得系统目录,如果在C盘,那么就排除C盘所在的这个物理盘。然后其他盘如果是DRIVE_REMOVABLE,那么就是U盘和闪存,如果是DRIVE_FIXED就是移动硬盘。你去网上下载《安全移动存储系统》,参考一下这个软件的思路:)
      

  5.   

    可以用setupapi里面的函数,根据硬件classid来判断
      

  6.   

    参考南邮某学生的一段代码,可以识别优盘和移动硬盘盘符,但是锁盘好像有点问题,不起作用,
    有优盘插入时,在下拉列表框内显示盘符,并且锁住优盘或者移动硬盘
    请大家帮忙看下,谢谢
    CString GetDiskNumber(CString name)
    {
        HKEY hkey;
        char sz[256];
        DWORD dwtype,sl = 256;
        int number=0;

    // 确定选择的磁盘
    for(int i=1;i<8;i++) //好像这边有问题 {
    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",\
    NULL,KEY_ALL_ACCESS,&hkey)==ERROR_SUCCESS)
    {
    CString id;
    id.Format("%d",i);
    if(RegQueryValueEx(hkey,id,NULL,&dwtype,(LPBYTE)sz,&sl)==ERROR_SUCCESS)
    {
    CString str=(CString)sz;
    if(str.Compare(name)==0)
    {
    number=i;
    break;
    }
    }
    }
    }
    CString driver="\\\\.\\PHYSICALDRIVE";
    CString num;
    num.Format("%d",number);
    driver+=num;
    return driver;
    }
    LRESULT CMSSDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
    {
    CString name;
    CString driver;  //获取物理盘符
    int id;
    HANDLE hDevice;      //打开设备的句柄
    DWORD dwOutBytes;
    bool bResult;           //DeviceIOControl返回值
    CString logicalDisk;   //设备的盘符

    if (WM_DEVICECHANGE == message)
    {
    m_select.ResetContent();

    HKEY hkey;
    char sz[256];
    DWORD dwtype,sl = 256;

    for(int i=1;i<8;i++)
    {
    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",\
    NULL,KEY_ALL_ACCESS,&hkey)==ERROR_SUCCESS)
    {
    CString id;
    id.Format("%d",i);
    if(RegQueryValueEx(hkey,id,NULL,&dwtype,(LPBYTE)sz,&sl)==ERROR_SUCCESS)
    {
    CString str=(CString)sz;
    m_select.AddString(sz);
    }
    }
    }
    m_select.SetCurSel(0);  //默认选择为下拉列表框的第一项
    id=m_select.GetCurSel(); //id=0
       //感觉这几行代码有问题         //U盘返回值 name=USBSTOR\Disk&Ven_CBM&Prod_Flash_Disk&Rev_5.00
      //移动硬盘返回值USBSTOR\Disk&Ven_Hitachi&Prod_HTS542516K9SA00&Rev_0002\000000000033&0

    m_select.GetLBText(id,name);                //driver=\\.\PHYSICALDRIVE1
    driver=GetDiskNumber(name);                 

    logicalDisk = driver;                //hDevice有返回值
    hDevice = CreateFile(
    logicalDisk,                                 //要打开的驱动名称
    GENERIC_READ|GENERIC_WRITE,                  //访问方式
    FILE_SHARE_READ|FILE_SHARE_WRITE,            //共享方式
    NULL,                                        //安全描述符指针
    OPEN_EXISTING,                               //创建方式
    0,                                           //文件属性及标志
    NULL                                         //模板文件的句柄
    );

                    //bResult值为1
    bResult = DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&dwOutBytes,(LPOVERLAPPED)NULL);

    RegCloseKey(hkey);
    }

    return CDialog::WindowProc(message, wParam, lParam);
    }
      

  7.   

    通过读取注册表及DeviceIoControl可以区别,具体见http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=193595     BOOL   CCopyHook::IsIDE(CString   DriveName)   
      {   
      ////本段程序的前提是DriveName是已经过GetDriveType的判断是本地磁盘,否则报错,作用是判断是否是真正的本地磁盘////////   
      //////////////////111111111111111111111111111111111111111/////////////////////////////////////////////   
      ///////////////////////获得某分区(目的地址)的信息/////////////////////////   
      HANDLE   hDeviceDest   =   NULL;   
      DWORD   nBytesRead   =   0;//预设为0,当缓冲区的长度不够时,该值为所需的缓冲区的长度   
      DWORD   nBufferSize   =   sizeof(PARTITION_INFORMATION);   
      PPARTITION_INFORMATION   lpPartInfo   =   (PPARTITION_INFORMATION)malloc(nBufferSize);   
      if(lpPartInfo   ==   NULL)   
      {   
      //MessageBox("缓冲区分配出错!","失败!",MB_OK);   
      return   FALSE;   
      }   
      memset(lpPartInfo,   0,   nBufferSize);//将缓冲区lpPartInfo的内容设为nDiskBufferSize个NULL   
      //CString   DriveName="J:";//为判断提供接口   
      DriveName="\\\\.\\"+DriveName;   
        
      hDeviceDest   =   CreateFile(LPCTSTR(DriveName),//注意一定要是\\\\.\\的形式,CreateFile的要求   ""\\??\\Volume{e9233817-90be-11d6-88b7-00e04c3de005}   
      GENERIC_READ,   
      FILE_SHARE_READ   |   FILE_SHARE_WRITE,   
      NULL,   OPEN_EXISTING,   
      0,   NULL);   
        
      if(hDeviceDest   ==   NULL)   
      {   
      //MessageBox("CreateFile出错!","失败!",MB_OK);   
      return   FALSE;   
      }   
      /////////////获得该分区信息/////////////////////////   
      BOOL   ret1=DeviceIoControl(   
      hDeviceDest,   
      IOCTL_DISK_GET_PARTITION_INFO,   
      NULL,   
      0,   
      (LPVOID)   lpPartInfo,   
      (DWORD)   nBufferSize,   
      (LPDWORD)   &nBytesRead,   
      NULL//指向一个异步的结构体   
      );   
        
      if   (!ret1)   
      {   
      LPVOID   lpMsgBuf;   
      FormatMessage(     
      FORMAT_MESSAGE_ALLOCATE_BUFFER   |     
      FORMAT_MESSAGE_FROM_SYSTEM   |     
      FORMAT_MESSAGE_IGNORE_INSERTS,   
      NULL,   
      GetLastError(),   
      MAKELANGID(LANG_NEUTRAL,   SUBLANG_DEFAULT),   //   Default   language   
      (LPTSTR)   &lpMsgBuf,   
      0,   
      NULL     
      );   
      //MessageBox(   (LPCTSTR)lpMsgBuf,   "Error",   MB_OK   |   MB_ICONINFORMATION   );   
      LocalFree(   lpMsgBuf   );   
      //MessageBox("DeviceIoControl出错!","失败!",MB_OK);   
      return     FALSE;   
      }   
      ///////////////////导出该分区信息///////////////////////////////////   
      LARGE_INTEGER   StartingOffset=lpPartInfo->StartingOffset;   
      LONGLONG   QuadPart=StartingOffset.QuadPart;//取上面的值之一情形,支持64位整型   
      LARGE_INTEGER   PartitionLength=lpPartInfo->PartitionLength;   
      LONGLONG   QuadPart1=PartitionLength.QuadPart;//取上面的值之一情形,支持64位整型   
      DWORD   HiddenSectors=lpPartInfo->HiddenSectors;   
      DWORD   PartitionNumber=lpPartInfo->PartitionNumber;   
      BYTE     PartitionType=lpPartInfo->PartitionType;   
      BOOLEAN   BootIndicator=lpPartInfo->BootIndicator;   
      BOOLEAN   RecognizedPartition=lpPartInfo->RecognizedPartition;   
      BOOLEAN   RewritePartition=lpPartInfo->RewritePartition;   
        
      free(lpPartInfo);   
      CloseHandle(hDeviceDest);   
        
      /////////////////////查询注册表中COUNT(Disk)的值//////////////////////////////////////   
      UINT   IDESeqNum;//IDE的序号   
      BOOL   FindIDE=FALSE;   
        
      HKEY   hKEY;   
      RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",   0,   KEY_READ,   &hKEY);     
      ///////////接收DWORD型/////////////   
        
      DWORD   Type;//仅仅用于接收数据类型   
      DWORD   dwValue;   
      DWORD   dwBufLen   =   sizeof(DWORD);   
      long   ret2=::RegQueryValueEx(hKEY,   _T("Count"),   NULL,   &Type,   (BYTE*)&dwValue,   &dwBufLen);   
      if(ret2!=ERROR_SUCCESS)   
      {   
      //MessageBox("找不到磁盘的个数","提示",MB_OK);   
      return   FALSE;//失败   
      }   
      for   (UINT   k=0;   k<dwValue;   k++)   
      {       
      ///////////接收字符型/////////////   
      char   str[256];   
      DWORD     sl   =   256;       
      CString   nDisk;   
      nDisk.Format("%u",k);   
      RegQueryValueEx(hKEY,     nDisk,     NULL,     NULL,     (LPBYTE)str,     &sl);   //注意第三项必须设为NULL,否则接收到的字符数据出错     
      CString   temp=str;   
      if   (temp.Left(3)=="IDE")   
      {   
      IDESeqNum=k;//IDE的序号   
      FindIDE=TRUE;   
      }   
        
      }   
      if   (!FindIDE)       
      return   FALSE;       //     IDESeqNum=0;   
      RegCloseKey(hKEY);       
        
      CString   temp;   
      temp.Format("%u",IDESeqNum);   
      temp="\\\\.\\PHYSICALDRIVE"+temp;//为下一步检测作准备   
      //////////////////22222222222222222222222222222222222222222   /////////////////////////////////////////   
        
        
      HANDLE   hDevice   =   NULL;   
      DWORD   nDiskBytesRead   =   0;//预设为0,当缓冲区的长度不够时,该值为所需的缓冲区的长度   
      DWORD   nDiskBufferSize   =   sizeof(DRIVE_LAYOUT_INFORMATION)   +   sizeof(PARTITION_INFORMATION)*104;//26*4   
      PDRIVE_LAYOUT_INFORMATION   lpDiskPartInfo   =   (PDRIVE_LAYOUT_INFORMATION)malloc(nDiskBufferSize);   
        
      if(lpDiskPartInfo   ==   NULL)   
      {   
      //MessageBox("缓冲区分配出错!","失败!",MB_OK);   
      return   FALSE;   
      }   
      memset(lpDiskPartInfo,   0,   nDiskBufferSize);//将缓冲区lpDiskPartInfo的内容设为nDiskBufferSize个NULL   
        
      //////////////////////获得所有分区的信息///////////////////////////////////////   
      hDevice   =   CreateFile(LPCTSTR(temp),//注意一定要是\\\\.\\的形式,CreateFile的要求   ""\\??\\Volume{e9233817-90be-11d6-88b7-00e04c3de005}   
      GENERIC_READ,   
      FILE_SHARE_READ   |   FILE_SHARE_WRITE,   
      NULL,   OPEN_EXISTING,   
      0,   NULL);   
        
      if(hDevice   ==   NULL)   
      {   
      //MessageBox("CreateFile出错!","失败!",MB_OK);   
      return   FALSE;   
      }   
        
      /////////////获得某磁盘上的所有分区信息/////////////////////////   
      BOOL   ret=DeviceIoControl(   
      hDevice,   
      IOCTL_DISK_GET_DRIVE_LAYOUT,   
      NULL,   
      0,   
      (LPVOID)   lpDiskPartInfo,   
      (DWORD)   nDiskBufferSize,   
      (LPDWORD)   &nDiskBytesRead,   
      NULL   
      );   
        
      if   (!ret)   
      {   
      LPVOID   lpMsgBuf;   
      FormatMessage(     
      FORMAT_MESSAGE_ALLOCATE_BUFFER   |     
      FORMAT_MESSAGE_FROM_SYSTEM   |     
      FORMAT_MESSAGE_IGNORE_INSERTS,   
      NULL,   
      GetLastError(),   
      MAKELANGID(LANG_NEUTRAL,   SUBLANG_DEFAULT),   //   Default   language   
      (LPTSTR)   &lpMsgBuf,   
      0,   
      NULL     
      );   
      //MessageBox(   (LPCTSTR)lpMsgBuf,   "Error",   MB_OK   |   MB_ICONINFORMATION   );   
      LocalFree(   lpMsgBuf   );   
      //MessageBox("DeviceIoControl出错!","失败!",MB_OK);   
      return   FALSE;   
      }   
        
      }
      

  8.   


      //////////////////////////////导出分区信息///////////////////////////////////////   
      DWORD   PartitionCount=lpDiskPartInfo->PartitionCount;     //永远是实际的分区数的4倍,不能用的分区将会显示类型PARTITION_ENTRY_UNUSED,即分区类型为0   
      ///////////////////依次获取导出某分区信息,并与目的驱动器进行比较///////////////////////////////////   
      for   (UINT   i=0;   i<PartitionCount;   i=i+4)//+4是因为只有下标为4的整数倍的值才是正确的引用   
      {   
      PARTITION_INFORMATION   DiskPartInfo=lpDiskPartInfo->PartitionEntry[i];//0为C:,4为D:,8为e:,12为F   
        
      LARGE_INTEGER   DiskStartingOffset   =   DiskPartInfo.StartingOffset;   
      LONGLONG   DiskQuadPart   =   DiskStartingOffset.QuadPart; //取上面的值之一情形,支持64位整型   
      LARGE_INTEGER   DiskPartitionLength   =   DiskPartInfo.PartitionLength;   
      LONGLONG   DiskQuadPart1   =   DiskPartitionLength.QuadPart; //取上面的值之一情形,支持64位整型   
      DWORD   DiskHiddenSectors   =   DiskPartInfo.HiddenSectors;   
      DWORD   DiskPartitionNumber   =   DiskPartInfo.PartitionNumber;   
      BYTE     DiskPartitionType   =   DiskPartInfo.PartitionType;   
      BOOLEAN   DiskBootIndicator   =   DiskPartInfo.BootIndicator;   
      BOOLEAN   DiskRecognizedPartition   =   DiskPartInfo.RecognizedPartition;   
      BOOLEAN   DiskRewritePartition   =   DiskPartInfo.RewritePartition;   
      if     ((DiskQuadPart==QuadPart)   &&   (DiskQuadPart1==QuadPart1)   
      &&   (DiskHiddenSectors==HiddenSectors)   &&   (DiskPartitionNumber==PartitionNumber)   
      &&   (DiskPartitionType==PartitionType   )   &&   (DiskBootIndicator==BootIndicator)   
      &&   (DiskRecognizedPartition==RecognizedPartition)   &&   (DiskRewritePartition==RewritePartition))   
      {   
      free(lpDiskPartInfo);   
      CloseHandle(hDevice);   
      ::MessageBox(NULL,"属于本地驱动器!","提示",MB_OK);   
      return   TRUE;   
      }   
      }   
      free(lpDiskPartInfo);   
      CloseHandle(hDevice);   
      ::MessageBox(NULL,"非本地驱动器!","提示",MB_OK);//改为return   IDCANCEL;   
      return   FALSE;   
      

  9.   

    1.移动硬盘获取多个盘符,但是只能接受系统的一个消息吧。  ------- 每个逻辑都会出来一个事件的.所以你可以一个一个盘符的处理的.
    2.我用DDK的方法可以区分是否为移动盘符的.我写的USBLOCK程序就是这么区别分的,如果是U盘或移动硬盘就再读其GUID,如果是已注册的硬件就可以使用,否则如果管理员输入了密码也可以使用到指定的时间为止,否则自动弹出.但现在出差了,手头上没有代码.
      

  10.   

    这个……根据DISK和Volume的GUID,用SetupDi函数族去取得设备的描述信息,然后判断哪些卷带有USB字样就可以了。
    /*************************************************************************
    * Function Name : GetDeviceInfo(LPGUID, vector<DEVICE_DESCRIPTOR>&)
    *
    * Introduction : Get storage device description
    *
    * Input parameter : lpGuid, DeviceVect
    *
    * Output parameter :None
    *
    * Return : None
    *************************************************************************/
    DWORD GetDeviceInfo(LPGUID lpGuid, vector<DEVICE_DESCRIPTOR>& DeviceVector)
    {
    SP_INTERFACE_DEVICE_DATA InterfaceData = {0}; //存储设备接口信息的结构体
    PSP_INTERFACE_DEVICE_DETAIL_DATA_W pDetail = NULL;

    SP_DEVINFO_DATA DevInfoData = {0};
    HDEVINFO hDevInfoSet = NULL;
    DWORD dwErrorCount = 0;
    DWORD dwDevIndex = 0;
    DEVINST ParentInstance = 0;
    BOOL bResult = FALSE;
    DEVICE_DESCRIPTOR tmpDevInfo;
    DWORD dwNeededSize = 0;

    //SetupDiEnumDeviceInterfaces函数取得设备属性集中某个设备接口的上下文环境
    //每次调用都返回一个设备接口的相关信息.此函数可以被再三调用以获取一或多个
    //设备暴露的、数个接口的信息,这里我们用来枚举符合该GUID的设备接口,调用成功
    //的话,ifdata中将得到一个完成的SP_DEVICE_INTERFACE_DATA结构,该结构体将指明
    //和枚举参数对应的,设备的接口信息.在调用该参数之前,必须填写ifdata的cbSize域
    hDevInfoSet = SetupDiGetClassDevsW(
        lpGuid, // 设备类的GUID 
        NULL,   // 不指定关键字
        NULL,   // 不指定父窗口句柄
        DIGCF_PRESENT| // 只枚举目前存在的设备
    DIGCF_INTERFACEDEVICE //取得接口信息
          );
    if(hDevInfoSet == INVALID_HANDLE_VALUE) //失败??
    {
    MessageBox(NULL,"Sorry,Failed to retrive information set!","Error",MB_OK|MB_ICONERROR);
    return 0;
    }
    // 成功!填写InterfaceData的cbSize域,准备调用SetupDiEnumDeviceInterfaces
    InterfaceData.cbSize = sizeof(InterfaceData);
    dwDevIndex = 0;
    do
    {
    bResult = SetupDiEnumDeviceInterfaces(
                                       hDevInfoSet,   // 设备信息集句柄
       NULL,          // 不需额外的设备描述
       lpGuid,        // GUID
       dwDevIndex,    // 设备信息集里的设备序号
       &InterfaceData // 设备接口信息(出口buffer)
     );
    if(!bResult) //失败?
    {
    break;
    }

    //成功,继续进行下列操作
    dwNeededSize = 0;

    //如果在调用SetupDiGetDeviceInterfaceDetail函数时,指定DeviceInterfaceDetailData,
    //DeviceInterfaceDetailDataSize为NULL,并且RequiredSize变量有效的话,将得到需要的
    //出口缓冲区的大小
    SetupDiGetDeviceInterfaceDetailW(
    hDevInfoSet,
    &InterfaceData,
    NULL,
    0,
    &dwNeededSize,
    NULL
    );

    //上一次调用,我们在dwNeededSize中得到了PSP_DEVICE_INTERFACE_DETAIL_DATA
    //结构体需要的缓冲区的大小,现在我们分配并初始化之.
    pDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA_W)new char[dwNeededSize];
    pDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA_W);
    DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

    //OK,分配完毕,再次调用SetupDiGetDeviceInterfaceDetail得到特定接口的详细信息
    bResult = SetupDiGetDeviceInterfaceDetailW
    (
    hDevInfoSet, // 设备信息集句柄,包含接口和下层设备信息(入口)
    &InterfaceData, // 设备接口信息,表明我们要获取哪个接口的信息(入口)
    pDetail, // 存储要查询的设备接口的详细细节(设备路径,出口)
    dwNeededSize, // 指定输出缓冲区大小(入口)
    &dwNeededSize,  // 不需计算输出缓冲区大小(直接用设定值,出口)
    &DevInfoData // 不需额外的设备描述(出口)
    );
    if(!bResult) //失败,则清场
    {
    dwErrorCount++;
    delete []pDetail;
    pDetail = NULL;
    dwNeededSize = 0;
    continue;
    }
    //取出设备路径(3环的应用程序所看到的设备路径)
    tmpDevInfo.wstrRing3Interface = pDetail->DevicePath;
    delete [](char*)pDetail;
    pDetail = NULL;

    dwNeededSize = 0;

    tmpDevInfo.wstrFriendlyName = GetRegistryPropertyW(hDevInfoSet,DevInfoData,SPDRP_FRIENDLYNAME);
    tmpDevInfo.wstrDeviceDesc = GetRegistryPropertyW(hDevInfoSet,DevInfoData,SPDRP_DEVICEDESC);
    tmpDevInfo.wstrPhysicalDeviceObjectName = GetRegistryPropertyW(hDevInfoSet,DevInfoData,SPDRP_PHYSICAL_DEVICE_OBJECT_NAME);
    tmpDevInfo.wstrService = GetRegistryPropertyW(hDevInfoSet,DevInfoData,SPDRP_SERVICE);

    //获取本地设备树中父节点的ID
    GetParentID(
     DevInfoData.DevInst,
     ParentInstance,
     tmpDevInfo.wstrParentInstanceID,
     tmpDevInfo.wstrParentDeviceDesc
       );

    GetStorageInfo(
    tmpDevInfo.wstrRing3Interface,
    tmpDevInfo.dwStorageDeviceNumber,
    tmpDevInfo.wstrStorageManagerName
      );

    dwDevIndex++; DeviceVector.push_back(tmpDevInfo);
    }while(bResult);

    SetupDiDestroyDeviceInfoList(hDevInfoSet);
    return dwErrorCount;
    }
      

  11.   


    typedef struct _DEVICE_DESCRIPTOR
    {
    wstring wstrRing3Interface;
    wstring wstrFriendlyName;
    wstring wstrDeviceDesc;
    wstring wstrPhysicalDeviceObjectName;
    wstring wstrService;
    wstring wstrParentInstanceID;
    wstring wstrParentDeviceDesc;
    wstring wstrStorageManagerName;
    DWORD dwStorageDeviceNumber;
    DWORD dwSectors;
    DWORD dwBytesPerSector;
    DISK_PARAMETER DiskGeometry;
    }DEVICE_DESCRIPTOR, *PDEVICE_DESCRIPTOR;
      

  12.   

    在wstrParentInstanceID中查找是否有USB字样就能判断是否是USB设备,同时能找到PID和VID。
    6年前写的代码,一下子拖出来我自己也没怎么细看,lz将就着看看吧。
      

  13.   

    另外请教一下你是怎么锁盘的?能防住直接下SCSI命令吗?
      

  14.   

    写驱动直接在Storage device stack中发送scsi命令能防住么?
      

  15.   

    CString GetDiskNumber(CString name)
    {
        HKEY hkey;
        char sz[256];
        DWORD dwtype,sl = 256;
        int number=0;

    // 确定选择的磁盘
    for(int i=1;i<8;i++)
    {
    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",\
    NULL,KEY_ALL_ACCESS,&hkey)==ERROR_SUCCESS)
    {
    CString id;
    id.Format("%d",i);
    if(RegQueryValueEx(hkey,id,NULL,&dwtype,(LPBYTE)sz,&sl)==ERROR_SUCCESS)
    {
    CString str=(CString)sz;
    if(str.Compare(name)==0)
    {
    number=i;
    break;
    }
    }
    }
    }
    CString driver="\\\\.\\PHYSICALDRIVE";
    CString num;
    num.Format("%d",number);
    driver+=num;
    return driver;
    }

    // 确定选择的磁盘
    driver=GetDiskNumber(name);
    ////////////////////////////////////////////////////////////////////////
    U盘返回值
    name  = {"USBSTOR\Disk&Ven_CBM&Prod_Flash_Disk&Rev_5.00\0210010065721303&0"}
    driver = {"\\.\PHYSICALDRIVE1"}移动硬盘返回值
    name  = {"USBSTOR\Disk&Ven_Hitachi&Prod_HTS542516K9SA00&Rev_0002\000000000033&0"}
    driver = {"\\.\PHYSICALDRIVE1"}//////添加下面几行代码,来锁优盘和移动硬盘是否可行
    logicalDisk = driver;    //物理驱动,之前用的是逻辑驱动
    hDevice = CreateFile(
    logicalDisk,                                 //要打开的驱动名称
    GENERIC_READ|GENERIC_WRITE,                  //访问方式
    FILE_SHARE_READ|FILE_SHARE_WRITE,            //共享方式
    NULL,                                        //安全描述符指针
    OPEN_EXISTING,                               //创建方式
    0,                                           //文件属性及标志
    NULL                                         //模板文件的句柄
    );
    bResult = DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&dwOutBytes,(LPOVERLAPPED)NULL);
    cloResult= CloseHandle(hDevice);
    ////////////////////////////////////////////////////////////////////////
      

  16.   


    加上8楼朋友提供的判断是否本地硬盘的代码,
    现在可以锁住移动硬盘的第一个盘符,第二个盘符锁不住。
    //获取移动磁盘的盘符
    CString CusbmngDlg::FindFdisk()
    {
    CString strdir;
    CString ret_mobiledir;
    bool is_ide = true; for(char cc='A';cc<='Z';cc++)
    {
    strdir.Format(L"%c:",cc); if(GetDriveType((LPCTSTR)strdir)==DRIVE_REMOVABLE)    //获取U盘的盘符
    {
    return strdir;
    }
            
    else if(GetDriveType((LPCTSTR)strdir)==DRIVE_FIXED)   //获取移动硬盘的盘符
    {
         //判断该盘符是否为USB盘符
                 is_ide = IsIDE(strdir);
                 if (is_ide == false)
     {
     return strdir;
     }
    }
        } return strdir ="";
    }//回调函数的实现
    LRESULT CusbmngDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
    {
    if(message == WM_DEVICECHANGE)  
    {  
    switch(wParam)  
    {  
    case DBT_DEVICEARRIVAL:         //判断是否有设备插入的消息
    {
    HANDLE hDevice;
    DWORD dwOutBytes;
    bool bResult;
    bool lock_flag = false;
                CString logicalDisk;    //有设备插入,则跳转到该行

        //查注册表
                     HKEY hkey;
    char sz[256];
    DWORD dwtype,sl = 256; for(int i=1;i<8;i++)
    {
    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"SYSTEM\\CurrentControlSet\\Services\\Disk\\Enum",\
    NULL, KEY_ALL_ACCESS, &hkey)==ERROR_SUCCESS)
    {
    CString id;
    id.Format(L"%d",i); if(RegQueryValueEx(hkey,id,NULL,&dwtype,(LPBYTE)sz,&sl)==ERROR_SUCCESS)
    {
    LPCTSTR str = (LPCTSTR)sz;
    m_select.AddString(str);
    }
    }
    }
    RegCloseKey(hkey); if(m_select.GetCount()==0)
    {
                        lock_flag = false;
    SetDlgItemText(IDC_EDIT_DRIVERNAME,L"没有发现移动设备...."); } if(m_select.GetCount()>0)
    {
    lock_flag = true;
    SetDlgItemText(IDC_EDIT_DRIVERNAME,L"发现移动设备....");                     
    }
                    
                    if (lock_flag == true)
    {
    m_NewFdisk = FindFdisk(); if (m_NewFdisk !="")
    {  
    logicalDisk = L"\\\\.\\"+m_NewFdisk;     hDevice = CreateFile(
    logicalDisk,                                 //驱动器名称
    GENERIC_READ|GENERIC_WRITE,                  //打开方式(可读可写)
    FILE_SHARE_READ|FILE_SHARE_WRITE,            //共享方式
    NULL,                                        //安全描述符指针
    OPEN_EXISTING,                               //创建方式
    0,                                           //文件属性及标志
    NULL                                         //模板文件的句柄
    );

                       //锁移动设备卷标
       bResult = DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&dwOutBytes,(LPOVERLAPPED)NULL); 
    } //end of if (m_NewFdisk !="") if(m_NewFdisk!="")
    {
    m_OldFdisk=m_NewFdisk;
    }
    else
    {
    m_OldFdisk="";
    }
    } //end of if (lock_flag == true)
    } // end of case DBT_DEVICEARRIVAL: 
    //break;  
    } //end of switch(wParam)  
    } //end of if(message == WM_DEVICECHANGE) 

    return CDialog::WindowProc(message, wParam, lParam);
    }
      

  17.   

    [b]发表于:2009-05-03 13:34:293楼 得分:0 
    GetDriveType是针对逻辑盘符的。依靠我的记忆,DBT_DEVICEARRIVAL也是对应逻辑盘符的,有几个盘符就有几次消息。 
    GetDriveType(strdir)的参数strdir请用“X:\\”的形式,所以逻辑盘符都能得到属性,与是否移动硬盘没有关系 另外给你个建议用GetLogicalDrives可以带到当前的所有逻辑盘符,不需要用for(char cc='A';cc <='Z';cc++) 全部循环 [/b]使用For循环,只能获取移动硬盘的第一个盘符,两次接收的消息,都锁第一个盘符。
    如何使用GetDriveType,获取移动硬盘的多个盘符?谢谢
      

  18.   

    GetLogicalDrives()   
        该函数功能是返回一个代表当前变量磁盘驱动器的位掩码;   
        该函数原型为:DWORD   GetLogicalDrives(VOID);   
        该函数如果调用成功,返回值为一个代表当前变量磁盘驱动器的位屏蔽掩码,位的位置0为驱动器A,1为驱动器B,2为驱动器C等。如果函数调用失败,返回值为0。   
        
        举例:如果某台电脑上驱动器为A、C、D、E,则函数调用成功后的返回值是00011101,其中最低位代表驱动器A,由A存在所以该位掩码为1,而由于B不存在,所以倒数第二位掩码为0。 
      

  19.   

    CreateFile在管理员权限下可以使用,
    但是在普通用户权限下不可以使用
      

  20.   

    http://hi.baidu.com/nmn714/blog/item/cf193959d8c7393c2934f051.html