息集句柄 hdevinfoset = ::setupdigetclassdevs(lpguid, // class guid null, // 无关键字 null, // 不指定父窗口句柄 digcf_present | digcf_deviceinterface); // 目前存在的设备 // 失败... if (hdevinfoset == invalid_handle_value) { return 0; } // 申请设备接口数据空间 pdetail = (psp_device_interface_detail_data)::globalalloc(lmem_zeroinit, interface_detail_size); pdetail->cbsize = sizeof(sp_device_interface_detail_data); ncount = 0; bresult = true; // 设备序号=0,1,2... 逐一测试设备接口,到失败为止 while (bresult) { ifdata.cbsize = sizeof(ifdata); // 枚举符合该guid的设备接口 bresult = ::setupdienumdeviceinterfaces( hdevinfoset, // 设备信息集句柄 null, // 不需额外的设备描述 lpguid, // guid (ulong)ncount, // 设备信息集里的设备序号 &ifdata); // 设备接口信息 if (bresult) { // 取得该设备接口的细节(设备路径) bresult = setupdigetinterfacedevicedetail( hdevinfoset, // 设备信息集句柄 &ifdata, // 设备接口信息 pdetail, // 设备接口细节(设备路径) interface_detail_size, // 输出缓冲区大小 null, // 不需计算输出缓冲区大小(直接用设定值) null); // 不需额外的设备描述 if (bresult) { // 复制设备路径到输出缓冲区 ::strcpy(pszdevicepath[ncount], pdetail->devicepath); // 调整计数值 ncount++; } } } // 释放设备接口数据空间 ::globalfree(pdetail); // 关闭设备信息集句柄 ::setupdidestroydeviceinfolist(hdevinfoset); return ncount; }
调用getdevicepath函数时要注意,pszdevicepath是个指向字符串指针的指针,例如可以这样
int i;
char* szdevicepath[max_device]; // 设备路径
// 分配需要的空间
for (i = 0; i < max_device; i++)
{
szdevicepath[i] = new char[256];
}
// 取设备路径
ndevice = ::getdevicepath((lpguid)&diskclassguid, szdevicepath);
// 逐一获取设备信息
for (i = 0; i < ndevice; i++)
{
// 打开设备
hdevice = ::opendevice(szdevicepath[i]);
if (hdevice != invalid_handle_value)
{
... ... // i/o操作
::closehandle(hdevice);
}
}
// 释放空间
for (i = 0; i & lt; max_device; i++)
{
delete []szdevicepath[i];
}
本例的project中除了要包含winioctl.h外,还要包含initguid.h,setupapi.h,以及连接setupapi.lib。
q 得到设备路径后,就可以到下一步,用createfile打开设备,然后用deviceiocontrol进行读写了吧?
a 是的。尽管该设备路径与以前我们接触的那些不太一样。本是“\\.\physicaldrive0”,现在鸟枪换炮,变成了类似这样的一副尊容:
“\\?\ide#diskmaxtor_2f040j0__________________________vam51jj0#3146563447534558202020202020202020202020#{53f56307-b6bf-11d0-94f2-00a0c91efb8b}”。
其实这个设备名在注册表的某处可以找到,例如在win2000中这个名字可以位于
hkey_local_machine\system\currentcontrolset\services\disk\enum\0,
只不过“#”换成了“\”。分析一下这样的设备路径,你会发现很有趣的东西,它们是由接口类型、产品型号、固件版本、序列号、计算机名、guid等信息组合而成的。当然,它是没有规范的,不能指望从这里面得到你希望知道的东西。
用createfile打开设备后,对于存储设备,ioctl_disk_get_drive_geometry,ioctl_storage_get_media_types_ex等i/o控制码照常使用。
今天我们讨论一个新的控制码:ioctl_storage_query_property,获取设备属性信息,希望得到系统中所安装的各种固定的和可移动的硬盘、优盘和cd/dvd-rom/r/w的接口类型、序列号、产品id等信息。
// ioctl控制码
#define ioctl_storage_query_property ctl_code(ioctl_storage_base, 0x0500, method_buffered, file_an