简介
当我们把一个U盘插入到电脑的USB接口后,操作系统会读取U盘相关信息,并在注册表中生成对应注册表项,
而我们拔掉这个U盘后,相关注册表项并不会自动删除,操作系统会保留对应信息,用以再次接入时使用。
某些安全检测软件,可以检测到这些历史记录信息。有时候,我们并不想让这些安全软件检测到,这就需要
我们主动的清除这些信息。
手动操作
首先我们需要在 环境变量
中新建一个 DEVMGR_SHOW_NONPRESENT_DEVICES
项,并设置变量值为 1
然后打开 设备管理器
,并在 查看
菜单里勾选上 显示隐藏的设备
的选项
在 磁盘驱动器
和 通用串行总线控制器
两处可以看到 半透明图标
的历史设备记录
在 半透明图标
的设备上,单击鼠标右键选择 卸载
就会删除该条设备记录
编程操作
写代码实现手动卸载操作,需要用 SetupDiRemoveDevice
函数来实现
1 2 3 4
| BOOL SetupDiRemoveDevice( _In_ HDEVINFO DeviceInfoSet, _Inout_ PSP_DEVINFO_DATA DeviceInfoData );
|
其他相关函数都在 setupapi.h
头文件中定义,所以需要加载该头文件
1 2
| #include <setupapi.h> #pragma comment(lib, "setupapi.lib")
|
方法为:遍历所有 USB
设备,检查设备使用的服务是否是 USBSTOR
,是的话就删除。
对应到手动操作:在 设备管理器
中卸载 通用串行总线控制器
中的 USB 大容量存储设备
项。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| BOOL DeleteUsbHistory() { HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES); if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE; DWORD dwDevIndex = 0; char szBuffer[40] = { 0 }; SP_DEVINFO_DATA DevInfoData = { 0 }; do { ZeroMemory(&DevInfoData, sizeof(SP_DEVINFO_DATA)); DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiEnumDeviceInfo(hDevInfo, dwDevIndex, &DevInfoData)) break; dwDevIndex++; ZeroMemory(szBuffer, sizeof(szBuffer)); if (!SetupDiGetDeviceRegistryProperty(hDevInfo, &DevInfoData, SPDRP_SERVICE, NULL, (PBYTE)szBuffer, sizeof(szBuffer), NULL)) continue; if ((_stricmp(szBuffer, "USBSTOR") != 0) && (_stricmp(szBuffer, "UASPStor") != 0)) continue; SetupDiRemoveDevice(hDevInfo, &DevInfoData); } while (1); SetupDiDestroyDeviceInfoList(hDevInfo); return TRUE; }
|
删除 磁盘驱动器
中的USB相关存储设备,需要遍历所有 USBSTOR
设备,直接删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| BOOL DeleteUsbStorHistory() { HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, "USBSTOR", NULL, DIGCF_ALLCLASSES); if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE; DWORD dwDevIndex = 0; char szBuffer[40] = { 0 }; SP_DEVINFO_DATA DevInfoData = { 0 }; do { ZeroMemory(&DevInfoData, sizeof(SP_DEVINFO_DATA)); DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiEnumDeviceInfo(hDevInfo, dwDevIndex, &DevInfoData)) break; dwDevIndex++; SetupDiRemoveDevice(hDevInfo, &DevInfoData); } while (1); SetupDiDestroyDeviceInfoList(hDevInfo); return TRUE; }
|
从Win8开始,操作系统提供了一种新的UASP协议。使用该协议时,对应的服务就变为 UASPStor
,
该协议没有专门的设备类,需要在 SCSI
类中处理,然后再查询对应的父设备
是否是 UASPStor
服务
获取父设备以及查询对应服务,相关函数在 cfgmgr32.h
中定义,但是使用 VS2013
时,选择兼容XP系统
编译,就会提示找不到 cfgmgr32.lib
,所以就需要我们从WDK7.1中手动拷贝对应XP系统的库到工程中
1 2
| #include <cfgmgr32.h> #pragma comment(lib, "cfgmgr32.lib")
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| BOOL DeleteUaspStorHistory() { HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, "SCSI", NULL, DIGCF_ALLCLASSES); if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE; DWORD dwDevIndex = 0; char szBuffer[40] = { 0 }; SP_DEVINFO_DATA DevInfoData = { 0 }; DEVINST DevInstParent = 0; ULONG ulLength = 0; do { ZeroMemory(&DevInfoData, sizeof(SP_DEVINFO_DATA)); DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if (!SetupDiEnumDeviceInfo(hDevInfo, dwDevIndex, &DevInfoData)) break; dwDevIndex++; DevInstParent = 0; if (CM_Get_Parent(&DevInstParent, DevInfoData.DevInst, 0) != CR_SUCCESS) continue; ulLength = sizeof(szBuffer); if (CM_Get_DevNode_Registry_Property(DevInstParent, CM_DRP_SERVICE, NULL, szBuffer, &ulLength, 0) != CR_SUCCESS) continue;; if ((_stricmp(szBuffer, "UASPStor") != 0)) continue; SetupDiRemoveDevice(hDevInfo, &DevInfoData); } while (1); SetupDiDestroyDeviceInfoList(hDevInfo); return TRUE; }
|