`
yexin218
  • 浏览: 958189 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

使用DeviceIoControl通信

阅读更多

   在很多时候,某些用户需要与底层驱动有一个交互式的操作,所以需要寻找一个架构能够做到应用程程序和驱动程序进行有效的沟通,而Microsoft Windows 家族操作系统通过发送 I/O 请求数据包 (IRP) 与驱动程序通信。所以今天我们介绍Windows如何使用DeviceIoControl以及IRP进行User层和Kernel层的数据交流。

  首先,为了比较完整的介绍这个部分,我们先看看一些准备工作。要访问底层驱动,我们应该先得到该驱可访问的句柄(Handle)。这里我们使用到了函数CreateFile。

HANDLE CreateFile(
  LPCTSTR lpFileName,  // 文件名
  DWORD dwDesiredAccess,  // 访问方式
  DWORD dwShareMode,  // 共享模式
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,  // 设为NULL
  DWORD dwCreationDisposition,  /// 创建方式
  DWORD dwFlagsAndAttributes,  // 属性
  HANDLE hTemplateFile
); 

 之后,我们在简单介绍下IOCTL,IOCTL通常用于驱动和应用程序的交流,其功能不限于读写数据。更多的时候,驱动都会定义一些列的IOCTL和数据结构来满足通信需求。简单来说,我们可把处于User Level的与IOCIL相关的东西看成一个Windows 信息,该信息通知驱动完成用户预先定义的某种请求。接下来先看看如何顶一个IOCTL. IOCTL是一个32未的数字,头两位的那个一了传输类型(METHOD_OUT_DIRECT,METHOD_IN_DIRECT , METHOD_BUFFERED or METHOD_NEITHER ). 2-13bits定义了Function Code,其实你大可不需要在意这么多,用一个宏可以简单帮你完成任务。这个宏就是CTL_CODE.举例:我们定义一个IOCTL,用来查询MiniPort的版本号(5.1,6.0,6.20(Win7))。

#define _NDIS_CONTROL_CODE(request,method) \
            CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS)
#define IOCTL_FILTER_QUERY_DRIVER_VERSION   _NDIS_CONTROL_CODE(18, METHOD_BUFFERED)

 当然我们可能还需要预定义一些数据,比如分配输入和输出的缓冲区。输入缓冲区用于传输数据给底层驱动,输出缓冲区用于保存由底层返回的数据。而这些数据(包括IOCTL Code等)都必须由函数DeviceIoControl传递传递到底层驱动。有兴趣更深入了解的可以看看IRP。因为底层驱动是从IRP的数据结构中找到用户预先定义的数据,然后由驱动调度执行,完成用户的请求。

/**
   Rturns Ndis version of the current driver uses
   @return - TRUE - success, FALSE - failure
*/
BOOL FilterWrapper::QueryNdisVersion()
{
BOOL result = FALSE;
   LPVOID versionfoBuffer = NULL;
   DWORD bytesWritten = 0;
   //allocate new buffer to store mac info
   DWORD versionLengthBuffer = (DWORD)sizeof(USHORT);
   versionfoBuffer =  new BYTE[versionLengthBuffer];
   if(versionfoBuffer == NULL)
   {
    goto Exit;
   }
    // pass a new io control to underlying driver to create a new mac
	if(!DeviceIoControl(
                m_hFilter,
                IOCTL_FILTER_QUERY_DRIVER_VERSION,
                "Request from user mode to ger ndis version.\n",
                sizeof("Request from user mode to ger ndis version.\n"),
                versionfoBuffer,
                versionLengthBuffer,
                &bytesWritten,
                NULL))
	{
				printf("Can't get version\n");
	            goto Exit;
				
	}
	 printf("Successfylly get ndis version! And Version Info:\n");
     if(!ParseVersionBuffer(versionfoBuffer, bytesWritten))
        goto Exit;
     result = TRUE;
Exit:
    delete[] versionfoBuffer;
   return result;;
}

 接下来,我们看看底层驱动是如何调度执行的。刚才说过了,所有的数据都会保存在一个叫做IRP的数据结构里,并且完成状态也是保存在IRP结构中。

NTSTATUS
FilterDeviceIoControl(
    IN PDEVICE_OBJECT        DeviceObject,
    IN PIRP                  Irp
    )
{
PIO_STACK_LOCATION          IrpSp;
    NTSTATUS                    Status = STATUS_SUCCESS;
    PFILTER_DEVICE_EXTENSION    FilterDeviceExtension;
    PUCHAR                      InputBuffer;
    PUCHAR                      OutputBuffer;
    ULONG                       InputBufferLength, OutputBufferLength;
    PLIST_ENTRY                 Link;
    PUCHAR                      pInfo;
    ULONG                       InfoLength = 0;
    PMS_FILTER                  pFilter = NULL;
    UINT                        iCnt = 0, iPCnt = 0;
    PUCHAR                      temp;
	//Following variables are add by leyond
    NDIS_OID                    Oid;
    USHORT                      VersionBuffer = 0;//USHORT for getting version
	ULONG                       MethodId = 0;
	ULONG                       BytesProcessed = 0;
  UNREFERENCED_PARAMETER(DeviceObject);
    DEBUGP(DL_TEST,("==>Filter IO Control dispatch\n")); 

    IrpSp = IoGetCurrentIrpStackLocation(Irp);

    if (IrpSp->FileObject == NULL)
    {
        return(STATUS_UNSUCCESSFUL);
    }


    FilterDeviceExtension = (PFILTER_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(DeviceObject);

    ASSERT(FilterDeviceExtension->Signature == 'FTDR');
    
    Irp->IoStatus.Information = 0;

    switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
    {
case IOCTL_FILTER_QUERY_DRIVER_VERSION://get ndsi version
	    InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
        InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
        OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;

		//pInfo = OutputBuffer;
		DEBUGP(DL_TEST,("The input length is %u, and inputdata is %s ",InputBufferLength,InputBuffer));
	    InfoLength = sizeof(USHORT);
		NdisZeroMemory(OutputBuffer, OutputBufferLength);
		
	    Link = FilterModuleList.Flink;
	    pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink);
		/*Check Version */
	    Oid =  	OID_GEN_DRIVER_VERSION;
	    Status = filterDoInternalRequest(pFilter,
	                                 NdisRequestQueryInformation,
									 Oid,
									 &VersionBuffer,
									 sizeof(VersionBuffer),
									 sizeof(VersionBuffer),
									 MethodId,
									 &BytesProcessed); 
		if(Status == NDIS_STATUS_SUCCESS)
		{
          DEBUGP(DL_TEST,("Get Ndis Version successfully!\n"));
          VersionHighByte = (VersionBuffer & 0xFF00) >> 8;
		  VersionLowByte = (VersionBuffer & 0x00FF);
		  DEBUGP(DL_TEST,("Ndis version:High %d, and Low: %d\n",VersionHighByte,VersionLowByte));
		  if(InfoLength <= OutputBufferLength)
		  {
		    temp = OutputBuffer;
		    *(PUSHORT)OutputBuffer += VersionBuffer;
			OutputBuffer += sizeof(USHORT);
			OutputBuffer = temp;
		  }else
		  {
		    Status = STATUS_BUFFER_TOO_SMALL;
		  }
		Irp->IoStatus.Information = InfoLength;
		}else{
          DEBUGP(DL_TEST,("Get Version Fail\n"));
        }	

	break;
 default:
            break;
    }

    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = InfoLength;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    DEBUGP(DL_TEST,("Filter IO Control dispatch<====\n")); 
    return Status;
            

}

 总会调用IoCompleteRequest来结束IRP,返回执行结果给用户。

大概就是这样一个简单的介绍~

分享到:
评论
1 楼 zzzwwwqsqs1 2010-05-07  
你好,在WIN7上使用DeviceIoControl会有如下问题,当下发802.11的OID时,Fiter驱动会拦住这些OID,导致不能发送到设备,请问有解决办法么? 谢谢

相关推荐

    使用DeviceIoControl进行通信(直接方式)

    一个WDM驱动,然后caller使用DeviceIoControl进行和驱动的通信。输出buffer使用METHOD_IN_DIRECT进行数据传输。

    DeviceIOControl函数实战演示及源代码

    DeviceIOControl实战演示及源代码,是应用程序与设备通信很好的示例教程

    驱动和应用层的三种通信方式

    驱动程序和客户应用程序经常需要进行数据交换,但我们知道驱动程序和客户应用程序可能不在同一个地址空间,...驱动层和应用层通信,主要是靠DeviceIoControl函数,资源是三种io通信情况的例子,还有应用层的测试程序。

    Wince5下C#读写I2C-EEPROM

    使用C#在wince5.0下实现EEPROM的读写,主要技术是使用DeviceIoControl,基于友善之臂mini2440。

    应用程序与驱动程序通讯演示

    应用程序与驱动程序通讯演示,通过应用程序创建一个Event传到驱动程序中,在Event中用KeSetEvet()激发事件对象,应用程序中的线程WaifXXXXX函数即可收到此事件。用于驱动程序接收到中断信号后通知应用程序。

    易语言使用驱动打开进程

    易语言使用驱动打开进程源码,使用驱动打开进程,加载驱动_,卸载驱动_,与驱动程序通信_,键码转换,CreateServiceA,OpenServiceA,StartServiceA,CloseServiceHandle,CreateFileA,ControlService,OpenSCManagerA,...

    易语言驱动进程保护

    易语言驱动进程保护源码,驱动进程保护,取变量地址_整数型_,驱动程序通信_,CreateFileA,DeviceIoControl,CloseHandle,FindWindowA,GetForegroundWindow,GetCurrentProcessId

    Windows内核安全与驱动开发光盘源码

    13.3.2 在用户态通过DLL使用通信端口的范例 311 13.4 Minifilter的安装与加载 314 13.4.1 安装Minifilter的INF文件 314 13.4.2 启动安装完成的Minifilter 316 第14章 网络传输层过滤 317 14.1 TDI概要 317 ...

    Windows内核安全驱动开发(随书光盘)

    13.3.2 在用户态通过DLL使用通信端口的范例 311 13.4 Minifilter的安装与加载 314 13.4.1 安装Minifilter的INF文件 314 13.4.2 启动安装完成的Minifilter 316 第14章 网络传输层过滤 317 14.1 TDI概要 317 ...

    易语言驱动加载

    易语言驱动加载源码,驱动加载,加载驱动_,卸载驱动_,与驱动程序通信_,转换ASCII转Unicode,键码转换,CreateServiceA,OpenServiceA,StartServiceA,CloseServiceHandle,CreateFileA,ControlService,OpenSCManagerA,...

    易语言驱动级读写内存源码,易语言驱动级读写内存模块

    易语言驱动级读写内存模块源码,驱动级读写内存模块,加载驱动_,卸载驱动_,与驱动程序通信_,键码转换,CreateServiceA,OpenServiceA,StartServiceA,CloseServiceHandle,CreateFileA,ControlService,OpenSCManagerA,...

    易语言驱动级读写内存

    易语言驱动级读写内存源码,驱动级读写内存,加载驱动_,卸载驱动_,与驱动程序通信_,键码转换,CreateServiceA,OpenServiceA,StartServiceA,CloseServiceHandle,CreateFileA,ControlService,OpenSCManagerA,...

    易语言文件粉碎专家

    易语言文件粉碎专家源码,文件粉碎专家,取变量地址_整数型_,取变量地址_文本型_,取变量地址_字节集型_,A2W,提升进程权限,删除目录_,WndProc,驱动程序通信_,KillFile,CreateFileA,DeviceIoControl,CloseHandle,...

    寒江独钓-Windows内核安全编程(高清完整版).part1

    9.3.2 在用户态通过DLL使用通信端口的范例 290 9.4 Minifilter的安装与加载 292 9.4.1 安装Minifilter的INF文件 293 9.4.2 启动安装完成的Minifilter 294 本章的示例代码 295 练习题 295 第10章 网络传输层过滤 296 ...

    寒江独钓-Windows内核安全编程(高清完整版).part2

    9.3.2 在用户态通过DLL使用通信端口的范例 290 9.4 Minifilter的安装与加载 292 9.4.1 安装Minifilter的INF文件 293 9.4.2 启动安装完成的Minifilter 294 本章的示例代码 295 练习题 295 第10章 网络传输层过滤 296 ...

    寒江独钓-Windows内核安全编程(高清完整版).part7

    9.3.2 在用户态通过DLL使用通信端口的范例 290 9.4 Minifilter的安装与加载 292 9.4.1 安装Minifilter的INF文件 293 9.4.2 启动安装完成的Minifilter 294 本章的示例代码 295 练习题 295 第10章 网络传输层过滤 296 ...

    寒江独钓-Windows内核安全编程(高清完整版).part4

    9.3.2 在用户态通过DLL使用通信端口的范例 290 9.4 Minifilter的安装与加载 292 9.4.1 安装Minifilter的INF文件 293 9.4.2 启动安装完成的Minifilter 294 本章的示例代码 295 练习题 295 第10章 网络传输层过滤 296 ...

    寒江独钓-Windows内核安全编程(高清完整版).part6

    9.3.2 在用户态通过DLL使用通信端口的范例 290 9.4 Minifilter的安装与加载 292 9.4.1 安装Minifilter的INF文件 293 9.4.2 启动安装完成的Minifilter 294 本章的示例代码 295 练习题 295 第10章 网络传输层过滤 296 ...

    寒江独钓-Windows内核安全编程(高清完整版).part5

    9.3.2 在用户态通过DLL使用通信端口的范例 290 9.4 Minifilter的安装与加载 292 9.4.1 安装Minifilter的INF文件 293 9.4.2 启动安装完成的Minifilter 294 本章的示例代码 295 练习题 295 第10章 网络传输层过滤 296 ...

    寒江独钓-Windows内核安全编程(高清完整版).part3

    9.3.2 在用户态通过DLL使用通信端口的范例 290 9.4 Minifilter的安装与加载 292 9.4.1 安装Minifilter的INF文件 293 9.4.2 启动安装完成的Minifilter 294 本章的示例代码 295 练习题 295 第10章 网络传输层过滤 296 ...

Global site tag (gtag.js) - Google Analytics