`
yexin218
  • 浏览: 970762 次
  • 性别: 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进行通信(直接方式)

    本文将详细探讨如何使用`DeviceIoControl`进行直接方式的通信,以及在WDM(Windows Driver Model)驱动程序中的应用。 首先,我们需要理解WDM驱动模型。WDM是微软为Windows操作系统设计的一种驱动程序模型,它支持...

    实战DeviceIoControl:通过API访问设备驱动程序.rar

    在Windows操作系统中,DeviceIoControl是一个非常重要的API,它提供了应用程序与设备驱动程序之间通信的桥梁。本实战教程将深入探讨如何使用DeviceIoControl来直接操控设备,从而实现对硬件的高级控制。以下是对这个...

    passthru使用DeviceIoControl进行高层与底层的交互

    在Windows驱动程序开发中,`passthru`是一种常见的技术,用于实现高层应用程序与底层硬件驱动之间的通信。本文将深入探讨`passthru`技术,以及如何利用`DeviceIoControl`函数来实现这种交互,同时关注`NDIS`(网络...

    实战DeviceIoControl.rar_deviceiocontrol_driver.IoControl_pdiusbd12

    在Windows操作系统中,DeviceIoControl是一个非常重要的API函数,它为用户模式的应用程序提供了一种与设备驱动程序进行通信的方法。这个函数允许应用程序发送特定的I/O控制代码(IOCTLs)到设备,从而实现对硬件的...

    DeviceIoControl详解及例程

    DeviceIoControl的使用涉及到三个关键元素:控制代码、输入缓冲区和输出缓冲区。 1. 控制代码(IOCTL): IOCTL是Input/Output Control的缩写,它是DeviceIoControl中的关键参数。每个IOCTL代码都对应一个特定的...

    Filter驱动开发笔记

    使用DeviceIoControl通信 - **DeviceIoControl**:用于与设备驱动程序进行交互。 - **通信方式**:通过发送IOCTL命令来实现驱动与应用程序之间的通信。 #### 37. 纵横捭阖C++之从异步谈起 - **异步编程**:一种...

    KernelIoControl和DeviceIoControl的区别

    DeviceIoControl是一个广泛使用的API函数,用于应用程序与设备驱动程序之间的通信。它为应用程序提供了一种向驱动程序发送控制码的方式,从而实现了应用程序对硬件设备的直接控制。 ##### 3.2 使用场景 ...

    实战DeviceIoControl.rar

    DeviceIoControl函数是Windows API提供的一种通信方式,允许应用程序与设备驱动程序进行通信,执行特定的设备控制操作。其基本语法如下: ```c BOOL DeviceIoControl( HANDLE DeviceHandle, DWORD IoControlCode,...

    DeviceIoControl

    在Windows操作系统中,`DeviceIoControl`函数是进行设备控制的主要接口,它允许应用程序与驱动程序之间进行低级别通信,执行各种设备特定的操作。本文将深入探讨`DeviceIoControl`函数的原理、参数、使用方法,并...

    DeviceIOControl函数实战演示及源代码

    通过实战演示,我们可以更好地理解和掌握DeviceIOControl的使用技巧,了解如何与各种硬件设备进行有效的通信。在分析提供的源代码时,我们可以学习到如何构建正确的请求结构,以及如何正确处理设备返回的信息。这...

    实战DeviceIoControl全集

    DeviceIoControl是Windows API提供的一种高级机制,允许应用程序与设备驱动程序进行通信,执行特定的设备操作,如配置硬件、读取硬件状态、控制设备功能等。在Windows系统开发中,熟练掌握DeviceIoControl对于驱动...

    DeviceIoControl读取无线网卡mac完整工程实例

    在Windows操作系统中,`DeviceIoControl`函数是一个非常重要的API,用于与设备驱动程序进行通信。这个函数允许用户模式的应用程序向设备发送控制代码,从而实现对硬件的直接操作。在本实例中,我们将深入探讨如何...

    实战DeviceIoControl

    在驱动开发领域,`DeviceIoControl`函数是一个非常重要的API,它主要用于实现用户模式应用程序与内核模式驱动程序之间的通信。通过这个函数,用户空间的应用程序可以向驱动程序发送控制代码,并接收相应的数据。下面...

    windows 驱动 应用层与驱动层通信(读、写文件) 源码

    3. 在应用层使用DeviceIoControl函数,传入设备句柄和控制代码,以及可能的数据缓冲区。 4. 驱动处理控制请求后,通过IoCompleteRequest或WdfRequestComplete返回结果。 总之,Windows驱动程序开发是一个复杂而重要...

    设备驱动接口函数DeviceIoControl使用实例.docx

    【设备驱动接口函数DeviceIoControl使用实例】 在Windows操作系统中,设备驱动接口函数DeviceIoControl是应用程序与设备驱动程序通信的重要途径。这个函数允许应用程序发送特定的控制代码到设备驱动,从而执行各种...

Global site tag (gtag.js) - Google Analytics