驱动开发之 应用程序通过设备接口打开设备

来源:互联网 发布:python cgi环境搭建 编辑:程序博客网 时间:2024/05/16 14:16

应用程序和设备之间有两种联系方式: 1. 符号链接; 2. 设备接口。

第一种方式符号链接有潜在的安全问题。因为任何内核模式或用户模式程序都能使用这个符号连接打开设备的句柄。

第二种方式设备接口是一种新的设备命名方案,该方案是语言中立的、易于扩展的、可用于许多硬件和软件厂商,并且易于文档化。

现在就来讨论一下怎么利用设备接口使应用程序打开设备


驱动程序中:

1.生成GUID,可利用工具UUIDGEN。GUID(全局唯一标识符),是一种由算法生成的唯一标识。GUID的主要目的是产生完全唯一的数字。在理想情况下,任何计算机和计算机集群都不会生成两个相同的GUID。



先点击New GUID,再点击Copy,然后粘贴到代码中。选择GUID Format 2 ,会生成如下形式的语句
// {3049C680-D73A-4EF6-AA44-AB2EC46F29B7}

DEFINE_GUID(<<name>>,
0x3049c680, 0xd73a, 0x4ef6, 0xaa, 0x44, 0xab, 0x2e, 0xc4, 0x6f, 0x29, 0xb7);

把<<name>>替换为你自己起的名字
DEFINE_GUID(My_Guid, 
0x3049c680, 0xd73a, 0x4ef6, 0xaa, 0x44, 0xab, 0x2e, 0xc4, 0x6f, 0x29, 0xb7);

 
2.注册设备接口
一般在ADDDevice函数中调用
status = IoRegisterDeviceInterface(pdo,&My_Guid,NULL,&deviceExtension->ustrSymLinkName);

3.使能接口
当响应PnP请求IRP_MN_START_DEVICE时,驱动程序将调用IoSetDeviceInterfaceState函数“使能”该接口

status = IoSetDeviceInterfaceState(&deviceExtension->ustrSymLinkName, TRUE);

在响应这个调用过程中,I/O管理器将创建一个指向设备PDO的符号连接对象。以后,驱动程序会执行一个功能相反的调用禁止该接口(用FALSE做参数调用IoSetDeviceInterfaceState)。最后,I/O管理器删除符号连接对象,但它保留了注册表项,即这个名字将总与设备的这个实例关联;但符号连接对象与硬件一同到来或消失。
因为接口名最终指向PDO,所以PDO的安全描述符将最终控制设备的访问权限。这样比较好,因为只有管理员才可以通过控制台控制PDO的安全属性。

禁用接口时调用:status = IoSetDeviceInterfaceState(&deviceExtension->ustrSymLinkName, FALSE);


应用程序中:

//获得类信息      HDEVINFO DevInfo = SetupDiGetClassDevs(&My_Guid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE); if(DevInfo==INVALID_HANDLE_VALUE)  {   printf("SetupDiGetClassDevs error : %d\n", GetLastError() );  return 1;   }// Get interface data for the requested instance  SP_INTERFACE_DEVICE_DATA InterfaceData;  InterfaceData.cbSize = sizeof(InterfaceData);   if(!SetupDiEnumDeviceInterfaces(DevInfo, NULL, &My_Guid, 0, &InterfaceData))  {   printf("SetupDiEnumDeviceInterfaces error : %d\n", GetLastError() );     SetupDiDestroyDeviceInfoList(DevInfo);   return 1;   }     // 得到 symbolic link name  的长度DWORD ReqLen;   SetupDiGetDeviceInterfaceDetail(DevInfo, &InterfaceData, NULL, 0, &ReqLen, NULL);  PSP_INTERFACE_DEVICE_DETAIL_DATA InterfaceDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)(new char[ReqLen]);   if( InterfaceDetail==NULL)  {   SetupDiDestroyDeviceInfoList(DevInfo);   return 1;   }     // 得到 symbolic link name   InterfaceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);   if( !SetupDiGetDeviceInterfaceDetail(DevInfo, &InterfaceData, InterfaceDetail, ReqLen, NULL, NULL))  {   SetupDiDestroyDeviceInfoList(DevInfo);   delete InterfaceDetail;   return 1;   }    printf("Symbolic link is %s\n",InterfaceDetail->DevicePath);   // 现在可以通过InterfaceDetail->DevicePath打开设备了HANDLE hDevice = CreateFile(InterfaceDetail->DevicePath,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_READ,// share mode noneNULL,// no securityOPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL );// no templateprintf("hDevice = %p\n",hDevice);if (hDevice == INVALID_HANDLE_VALUE){printf("Failed to obtain file handle to device: ""with Win32 error code: %d\n", GetLastError() );getchar();return 1;}



0 0
原创粉丝点击