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

Filter发送OID请求[解决蓝屏]

阅读更多

想从Filter发送一个OID请求到Miniport.

 case IOCTL_FILTER_CREATE_NEW_MAC: //Add by leyond to request miniport to create a new MAC
        InputBuffer = OutputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
        InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
        OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
		InfoLength = sizeof(USHORT);

        if(InfoLength < InputBufferLength){
		  InfoLength =  InputBufferLength;
		}
		pInfo = InputBuffer;
		DEBUGP(DL_TEST,("The input length is %u, and inputdata is%s ",InputBufferLength,InputBuffer));
		
	    FILTER_ACQUIRE_LOCK(&FilterListLock, FALSE);
		Link = FilterModuleList.Flink;
        Oid = OID_DOT11_CREATE_MAC;//OID used to create a new MAC
		/*************************************************************************
		actually, I don't understand why the following code is a while structure.
        do we really need to send the request to miniport to crate a new MAC for each 
		each filter? But usually, I think there is only one filter in the FilterModulerLink.
		And we have a test the number of filter is 3! 
		Warn:
		     Miniport couldn't crate more than 3 MAC entities!
		*********************************************************************************/
		#if DBG
		   _asm int 3
		#endif
        pFilter = CONTAINING_RECORD(Link, MS_FILTER, FilterModuleLink);
		//pFilter = (PMS_FILTER)IrpSp->FileObject->FsContext;
	    //DEBUGP(DL_TEST, ("IOCTL:FileObject %p, Open %p\n", IrpSp->FileObject, pFilter));
        Status = filterDoInternalRequest(pFilter,
	                                 NdisRequestMethod,
									 Oid,
									 &InformationBuffer,
									 sizeof(InformationBuffer),
									 sizeof(InformationBuffer),
									 MethodId,
									 &BytesProcessed); 		
		if(Status == NDIS_STATUS_SUCCESS){
          DEBUGP(DL_TEST,("Creae a new mac successfully!\n"));
		}else{
          DEBUGP(DL_TEST,("Creae a new mac Fail!\n"));
		} 
	    FILTER_RELEASE_LOCK(&FilterListLock, FALSE);
        break;
             
        default:
            break;
    }

 然后是filterDoInternalRequest函数体:

NDIS_STATUS
filterDoInternalRequest(
    IN PMS_FILTER                   FilterModuleContext,
    IN NDIS_REQUEST_TYPE            RequestType,
    IN NDIS_OID                     Oid,
    IN PVOID                        InformationBuffer,
    IN ULONG                        InformationBufferLength,
    IN ULONG                        OutputBufferLength, OPTIONAL
    IN ULONG                        MethodId, OPTIONAL
    OUT PULONG                      pBytesProcessed
    )

{
    FILTER_REQUEST              FilterRequest;
    PNDIS_OID_REQUEST           NdisRequest = &FilterRequest.Request;
    NDIS_STATUS                 Status = NDIS_STATUS_SUCCESS;

    DEBUGP(DL_TEST,("==>filterDoInternalRequest\n"));
    NdisZeroMemory(NdisRequest, sizeof(NDIS_OID_REQUEST));

    NdisInitializeEvent(&FilterRequest.ReqEvent);
    
    NdisRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST;
    NdisRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1;
    NdisRequest->Header.Size = sizeof(NDIS_OID_REQUEST);
    NdisRequest->RequestType = RequestType;

    switch (RequestType)
    {
        case NdisRequestQueryInformation:
             NdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
             NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
                                    InformationBuffer;
             NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
                                    InformationBufferLength;
            break;

        case NdisRequestSetInformation:
             NdisRequest->DATA.SET_INFORMATION.Oid = Oid;
             NdisRequest->DATA.SET_INFORMATION.InformationBuffer =
                                    InformationBuffer;
             NdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
                                    InformationBufferLength;
            break;

        case NdisRequestMethod:
             NdisRequest->DATA.METHOD_INFORMATION.Oid = Oid;
             NdisRequest->DATA.METHOD_INFORMATION.MethodId = MethodId;
             NdisRequest->DATA.METHOD_INFORMATION.InformationBuffer =
                                    InformationBuffer;
             NdisRequest->DATA.METHOD_INFORMATION.InputBufferLength =
                                    InformationBufferLength;
             NdisRequest->DATA.METHOD_INFORMATION.OutputBufferLength = OutputBufferLength;
             break;
             
                

        default:
            FILTER_ASSERT(FALSE);
            break;
    }
    DEBUGP(DL_TEST,("Everything is ok before NdisOidRequest!\n "));
    DEBUGP(DL_TEST,("FilterModululeContext->FilterHandle is%p\n",FilterModuleContext->FilterHandle));
    #if DBG
	    _asm int 3
    #endif
    NdisRequest->RequestId = (PVOID)FILTER_REQUEST_ID;
    Status = NdisFOidRequest(FilterModuleContext->FilterHandle,
                           NdisRequest);
    
    if (Status == NDIS_STATUS_PENDING)
    {
       DEBUGP(DL_TEST,("Everything is NDIS_STATUS_PENDING!\n "));
       NdisWaitEvent(&FilterRequest.ReqEvent, 0);
       Status = FilterRequest.Status;
    }


    if (Status == NDIS_STATUS_SUCCESS)
    {
       if (RequestType == NdisRequestSetInformation)
       {
           *pBytesProcessed = NdisRequest->DATA.SET_INFORMATION.BytesRead;
       }

       if (RequestType == NdisRequestQueryInformation)
       {
           *pBytesProcessed = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
       }

       if (RequestType == NdisRequestMethod)
       {
           *pBytesProcessed = NdisRequest->DATA.METHOD_INFORMATION.BytesWritten;
       }
       
       
       // The driver below should set the correct value to BytesWritten 
       // or BytesRead. But now, we just truncate the value to InformationBufferLength
       
       if (RequestType == NdisRequestMethod)
       {
           if (*pBytesProcessed > OutputBufferLength)
           {
               *pBytesProcessed = OutputBufferLength;
           }
       }
       else
       {
           
           if (*pBytesProcessed > InformationBufferLength)
           {
               *pBytesProcessed = InformationBufferLength;
           }
       }
    } 


    return (Status);
}

 现在问题来了:

        在函数NdisFOidRequest()发送OID到miniport之后,返回的状态为:NDIS_STATUS_PENDING。然后进阶进入执行:NdisWaitEvent(&FilterRequest.ReqEvent, 0); 之后就蓝屏了。下面是调试信息:

FOLLOWUP_IP:
ndislwf!filterDoInternalRequest+1c1
[c:\users\leyond\desktop\filter_leyond_beta\src\filter\filter.c @ 2012]
93b882f1 8b4df4          mov     ecx,dword ptr [ebp-0Ch]

FAULTING_SOURCE_CODE: 
  2008:     if (Status == NDIS_STATUS_PENDING)
  2009:     {
  2010:       
  2011:        NdisWaitEvent(&FilterRequest.ReqEvent, 0);//应该着这里返回错误了
> 2012:        Status = FilterRequest.Status;
  2013:     }
  2014:
  2015:
  2016:     if (Status == NDIS_STATUS_SUCCESS)
  2017:     {

接着看:

Debug Mesage:
 *** Fatal System Error: 0x0000007c
        (0x00000014,0x00000002,0x00000000,0x00000000)

Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.
BugCheck 7C, {14, 2, 0, 0}
..BUGCODE_NDIS_DRIVER (7c)
注意那四个参数:

0x14 The current IRQL value 0 0 An NDIS driver called NdisWaitEvent at IRQL > PASSIVE_LEVEL. The function must be called at IRQL = PASSIVE_LEVEL.

这里我们找到了蓝屏的真正理由:是 NdisWaitEvent 的IRQl>期望的PASSIVE_LEVEL. 为什么会这样的呢?我也没有找到理由。

从某位大牛Thomas Divine得到的回复是:

   Since this is in a NDIS driver one of the most common mistakes is to make a call to NdisOidRequest (or some other function with a completion routine...) and immediately wait for completion - at raised IRQL. The solution to this is NOT to wait. Instead, do the work in the completion routine when it is called.

 MSDN上面说NdisWaitEvent()函数的作用在于puts the caller into a wait state until the given event is set to the Signaled state or the wait times out.如果是因为等待参数为0,而需要提高IRQL。那么改成手动调用FilterOidRequestComplete函数看看了...结果未知。

还有一位大牛Tim Roberts的回复:

This is a relatively common misunderstanding, so I want to make sure
it's clear.  A lot of people come up against this restriction and say to
themselves "I need to wait in a DISPATCH_LEVEL function, so I'll just
temporarily change myself to non-dispatch," but that's the wrong way to
think about it.  As soon as you drop yourself below dispatch, you lose
the guarantees that you needed to be dispatch in the first place.
Spinlocks and synchronization will break, for example.

The solution is to remember that, in Windows, DISPATCH_LEVEL routines
cannot block, for any reason.  If you need to wait for something, you
need to spin off separate code at PASSIVE_LEVEL to do the wait.  That
means you have to think about WHY the routine was dispatch in the first
place.  Are you holding a spinlock?  If so, you'll have to find some
other way to protect the resource.

 所以他认为问题在于调用NdisFoidRequest时是否已经拿到spinLock.这下我恍然大悟。 FILTER_ACQUIRE_LOCK(&FilterListLock, FALSE); 就是这一句还有对应的释放lock的一句导致了后面返回 NDIS_STATUS_PENDING 的时候,调用NdisWaitEvent,由于无法及时返回就无法释放锁,导致其他进程无法访问某些资源,迫使增加IRQL值,一边第一时间执行。所以注释掉这两句就没有问题了。 非常感谢 Roberts.

-----------------------------------------------------------------------------

DDK文档中明确指出支持例程的IRQL限定。例如,KeWaitForSingleObject 例程有两个限 定:

  • 调用者必须运行在低于或等于DISPATCH_LEVEL级上。
  • 如果调用中指定了非0的超时,那么调用者必须严格地运行在低于DISPATCH_LEVEL的IRQL上。

上面这两行想要说明的是:如果KeWaitForSingleObject真的被阻塞了指定长的时间(你指定的非0超时),那么你必定运行在低于 DISPATCH_LEVEL的IRQL上,因为只有在这样的IRQL上线程阻塞才是允许的.

-----------------------------------------------------------------------------

附: Bug Check 0x7C: BUGCODE_NDIS_DRIVER

1
1
分享到:
评论

相关推荐

    基于win 10的 NDIS 6.0 Filter 驱动,新增加了收发数据包以及查询网卡Mac地址的代码

    操作系统: win 10 x64 ...1. 发送OID请求; 2. 发送自定义数据包,以ICMP数据包为例; 3. 接收数据包; 可以从代码中学习: 1. 内核OID的请求发送和接收; 2. 内核资源的分配和回收; 3. 数据包的发送和接受;

    Java实现SNMP获得OId值

    - 在接收到的响应中检查是否存在更多数据,如果有,则更新OID并再次发送GETNEXT请求。 - 当遍历结束时,响应中将不再有新的OID,此时结束循环。 #### 总结 通过以上分析,我们可以看到Java结合`Snmp4j`库在实现...

    SNMP一些常用OID

    - **1.3.6.1.2.1.1.1.0**: 这个OID用于获取系统的基本信息,如设备型号、硬件版本、软件版本等,通常返回一个字符串值,通过`GET`请求可获取。 - **1.3.6.1.2.1.1.3.0**: 监控系统自启动以来的运行时间,即`...

    OID编解码工具

    OID,全称Object Identifier,是网络协议中用于唯一标识对象的一种编码方式。它在各种网络标准、证书、协议中广泛使用,比如SNMP(简单网络管理协议)和X.509数字证书。OID编解码工具是针对这种编码方式进行操作的...

    基于C#编写的通过OID获取SNMP

    以上代码片段展示了如何使用C#和SnmpSharpNet库发送一个GET请求并获取OID对应的值。在实际大型项目中,可能需要处理更复杂的场景,如错误处理、定时轮询、批量查询等。SnmpSharpNet库提供了丰富的功能,能够满足这些...

    snmp_SNMP_oid_snmp查内存oid_使用snmp_

    4. **执行查询**:使用SNMP工具,指定目标主机的IP地址、社区字符串以及要查询的OID,发送SNMP GET请求。对于Java环境,可以使用如`snmp4j`这样的库来编写SNMP查询代码。 5. **解析响应**:收到SNMP响应后,解析...

    OID编码规则

    在微软的证书请求中,OID 编码规则被广泛应用,用于标识证书请求中的各种对象,例如客户端 ID、证书颁发机构 ID 等。OID 编码规则也可以用于实现身份验证、加密和数字签名等功能。 常见的 OID 编码规则示例如下: ...

    OID扫描软件

    2. **OID遍历**:软件发送GET-BULK或GET-NEXT请求,逐个获取OID值,这有助于遍历整个MIB树。 3. **数据解析**:接收到的OID值会被解析为有意义的信息,如设备型号、固件版本、接口状态等。 4. **展示与分析**:扫描...

    F5 SNMP OID说明

    取得指的是网管工作站发送请求,代理根据这个请求回送相应的数据,设置是网管工作站设置管理对象(也就是代理)的值,接收收代理发送的意外信息(Trap)是指代理可以在网管工作站未请求的状态下向网管工作站报告发生...

    通过snmp的OID获取对方主机的内存利用率及CPU的使用率

    总结来说,通过SNMP获取远程主机的内存利用率和CPU使用率涉及SNMP协议的理解、OID的选择、以及使用像SNMP4J这样的库来构建SNMP请求和解析响应。在Java程序中,这通常包括建立SNMP会话、构造PDU、发送GET请求以及解析...

    CISCO OID,测试可用

    同时,某些OID还支持设置阈值告警,当CPU或内存使用超过预设限制时,系统会自动发送通知,帮助快速响应潜在问题。 总之,Cisco的OID系统是其网络设备管理和监控的核心组成部分,它提供了丰富的数据点来监测设备性能...

    Sonix 二代OID驱动原码

    《Sonix二代OID驱动原码解析与应用》 在嵌入式系统开发中,驱动程序是连接硬件设备和操作系统的关键部分,它使得操作系统能够有效地控制和管理硬件资源。本篇文章将详细探讨“Sonix二代OID驱动原码”,这是针对松翰...

    SNMP常用OID,zabbix监控交换机

    SNMP(Simple Network Management Protocol,简单网络管理协议)是一种广泛应用于网络设备管理的标准协议,...理解并掌握常用OID的含义和用途,对于网络管理员来说是至关重要的,能够帮助他们及时发现和解决网络问题。

    查看电脑OID 工具

    OID,全称Object Identifier,是网络管理中的一个重要概念,它在网络管理系统中用于唯一标识网络对象。OID是一个层次化的数字序列,用于在SNMP(简单网络管理协议)中定位和识别网络资源,比如设备、接口、服务等。...

    基于java的Oid获取软件

    通过发送SNMP请求,该Java软件能够查询并解析出网络设备的OID值,从而帮助管理员监控和管理网络状态。 【描述】中的“有源码”意味着这个软件不仅提供可执行程序,还附带了源代码,这对于学习和理解SNMP协议以及...

    mib、snmp、oid相关介绍

    1. **轮询(Polling)**:SNMP管理器定期向SNMP代理发送GET请求,以检查设备的状态信息。这种方式提供了主动监控的能力,即管理器可以即时获取设备状态更新,同时也能检测到代理未响应的情况,指示可能存在的网络...

    windows上snmp自定义oid工具

    计数器文件定义了要收集的性能数据,而陷阱文件定义了在特定事件发生时发送的通知。了解如何编写和配置这些文件对于定制SNMP服务至关重要。 "license.txt"包含了软件的许可条款,确保你在法律允许的范围内使用这些...

    NDIS Filter Drivers指南

    9. **OID 请求**:Filter Drivers 可以过滤或发起 OID (OID Object Identifier) 请求,这些请求通常用于配置和查询网络适配器的状态。 10. **PnP 事件通知**:Filter Drivers 可以接收 PnP (Plug and Play) 事件...

    点读笔通用OID铺码工具

    最后,"通用码铺码工具说明.pdf"是对整个工具的使用手册,用户可以通过阅读这份文档了解每个功能的详细操作方法,以及解决可能出现的问题。 总的来说,这款点读笔通用OID铺码工具是教育科技领域的一个重要辅助工具...

    用snmp4j获取本地所有oid

    然后,通过发送一个GETBULK请求来获取所有OID,以提高性能。收到响应后,遍历并打印每个OID及其对应的值。 除了直接获取所有OID,还可以使用Snmp4j提供的`SnmpUtilites`类,这个类包含了各种实用工具方法,如解析...

Global site tag (gtag.js) - Google Analytics