Windows系统U盘的检测

 一、注册表中与U盘相关的键

1. \\HKEY_LOCAL_MACHINESYSTEM\\CurrentControlSet\\Services\\USBSTOR\\Enum ,该键中有本机连接的所有U盘的设备路径,Count为U盘的数量,数字键对应的值为U盘的设备路径,形如:USB\VID_1E3D&PID_2096\CCBB123456EE012B;

2. \\HKEY_LOCAL_MACHINESYSTEM\\CurrentControlSet\\Services\\disk\\Enum,该键中存储有物理磁盘设备的路径;count为磁盘数量,数字键对应的值为设备路径,形如:USBSTOR\Disk&Ven_2.0&Prod_Flash_Disk&Rev_2.61\CCBB123456EE012B&1;

3. \\HKEY_LOCAL_MACHINESYSTEM\\CurrentControlSet\\Services\\cdrom\\Enum,该键中存储有光驱的设备路径,Count为数量,数字键名对应的键值为设备路径,形如:USBSTOR\CdRom&Ven_2.0&Prod_Flash_Disk&Rev_2.60\CCBB123456EE012B&0;

4. \\HKEY_LOCAL_MACHINESYSTEM\\MountedDevices,该键中有\DosDevices\X:的键名,X为盘符,其值为对应设备的路径,如:“\DosDevices\E:”的键值为:\??\USBSTOR#CdRom&Ven_2.0&Prod_Flash_Disk&Rev_2.60#CCBB123456EE012B&0#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b},“\DosDevices\F:”的键值为:_??_USBSTOR#Disk&Ven_2.0&Prod_Flash_Disk&Rev_2.61#CCBB123456EE012B&1#{53f56307-b6bf-11d0-94f2-00a0c91efb8b};

 二、检测U盘的流程

1. 查询上述1-3所有的键值,存储在三个vector<string>中,然后逐个遍历通过关键字找出各自的对应关系,把对应的值存入USBNod中,USBNode定义如下:

struct UsbNod               //检索本机U盘节点,通过检索注册表获取
{
    LPCTSTR usb;            //U盘的对应USB设备
    LPCTSTR cdrom;          //U盘对应的光驱设备路径
    string cdvol;           //U盘对应的光驱盘符
    LPCTSTR disk;           //U盘对应的大容量磁盘设备路径
    string diskvol;         //U盘对应的盘符
};

遍历对应关系的代码如下:

//构造系统USB设备的节点数组
char* USBSTOR_key = "SYSTEM\\CurrentControlSet\\Services\\USBSTOR\\Enum";
vector<string> USBSTOR_vals;
getRegEnumValues(USBSTOR_key , USBSTOR_vals);

char* USBDISK_key = "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum";
vector<string> USBDISK_vals;
getRegEnumValues(USBDISK_key , USBDISK_vals);

char* USBCDROM_key = "SYSTEM\\CurrentControlSet\\Services\\cdrom\\Enum";	
vector<string> USBCDROM_vals;
getRegEnumValues(USBCDROM_key , USBCDROM_vals);

UsbNod usbdisknod[26];
int count = 0;
for (unsigned int i = 0; i < USBCDROM_vals.size(); i++)
{
    int pos = USBCDROM_vals.at(i).rfind('\\') + 1;
    string serialnum = USBCDROM_vals.at(i).substr(pos, USBCDROM_vals.at(i).size());
    serialnum = serialnum.substr(0,serialnum.size() - 2);
    for (unsigned int j = 0; j < USBSTOR_vals.size(); j++)
    {
        if (USBSTOR_vals.at(j).find(serialnum) == -1)
            continue;
        for (unsigned int k = 0; k < USBDISK_vals.size(); k++)
        {
            if (USBDISK_vals.at(k).find(serialnum) == -1)
                continue;
            usbdisknod[count].cdrom = USBCDROM_vals.at(i).data();
            usbdisknod[count].disk = USBDISK_vals.at(k).data();
            usbdisknod[count].usb = USBSTOR_vals.at(j).data();
            usbdisknod[count].diskvol = getVolFromDevicePath(USBDISK_vals.at(k));
            usbdisknod[count].cdvol = getVolFromDevicePath(USBCDROM_vals.at(i));
            count++;
        }
    }
}

读取注册表键值构造vector的函数

//检索Emnu类型的USB设备相关的注册表键值,返回获取到的数量,循环读取内容内容保存在 vector<string> &values
int getRegEnumValues(LPCTSTR key, vector<string> &values)
{
    values.clear();
    CRegKey usbreg;
    long rt = usbreg.Open(HKEY_LOCAL_MACHINE, key, KEY_READ | KEY_ALL_ACCESS);
    if (rt != ERROR_SUCCESS)  return 0;
    DWORD count = 0;
    usbreg.QueryDWORDValue("Count", count);
    if (count == 0) return 0;
    DWORD i, j = 0;
    for (i = 0; i<count; i++)
    {
        char vname[2];
        sprintf_s(vname, "%d", i);
        DWORD len = 256;
        char kValue[256];
        if (usbreg.QueryStringValue(vname, kValue, &len) == ERROR_SUCCESS)
        {
            string v(kValue);
            if (v.find("USB") != -1)
            {
                values.push_back(kValue);
                //printf("%s\n",kValue);
                j++;
            }
        }
    }
    usbreg.Close();
    return j;
}

2. 获取U盘对应光盘与磁盘盘符的方法

//根据设备路径获取其对应的盘符
string getVolFromDevicePath(string pDPath)
{
    string::iterator it = pDPath.begin();
    for (; it != pDPath.end(); it++)
        if (*it == '\\') *it = '#';
    
    int DeviceNum = 1001;
    if (pDPath.find("Disk") != -1)    //如果设备路径中有disk字符,则构造如下路径
    {	
        char ph_Path[MAX_PATH];
        sprintf_s(ph_Path, "\\\\?\\%s#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}", pDPath.data());
        DeviceNum = GetPhysicalDriveFromDevicePath(ph_Path);
        //获取磁盘设备地址对应的物理磁盘号
    }
    
    string vol;			//得到U盘盘符;    
    LPTSTR lpDrives = new TCHAR[MAX_PATH];
    DWORD dwLen = ::GetLogicalDriveStrings(MAX_PATH, lpDrives);
    char* sDrives[26] = { "" };
    for (DWORD nIndex = 0; nIndex < dwLen / 4; nIndex++)
    {
        UINT dType = ::GetDriveType(lpDrives + nIndex * 4);
        if (dType == DRIVE_REMOVABLE || dType == DRIVE_CDROM)
        {
            sDrives[nIndex] = (lpDrives + nIndex * 4);
            if (sDrives[nIndex] != "A:\\" && sDrives[nIndex] != "B:\\")
            {
                //获取盘符对应的MountedDevices中对应的键值
                string volkey = getVolKey(sDrives[nIndex][0]);
                int pnum = 1002;
                //该判断增加对XP系统的支持,在XP中U盘盘符对应的MountedDevices
                //的键值与以上2中值不同需要通过获取其物理磁盘号进行比较
                if (dType == DRIVE_REMOVABLE)
                    pnum = GetPhysicalDriveFromPartitionLetter(sDrives[nIndex][0]);
                if (pnum == DeviceNum || volkey.find(pDPath) != -1)
                {
                    vol = string(sDrives[nIndex]);
                }
            }
        }
    }
    delete lpDrives;
    return vol;
}

以上注册表键值由windows系统服务维持,经使用还是比较可靠的,未尽问题是对于U盘仅检测有一个U盘盘符的情况,多个U盘盘符未做处理,不过根据源码应该很容易写出。

通过CSDN学习了很多,今天终于自己写了一点东西,不对之处欢迎拍砖。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值