2013年10月22日星期二

NDIS过滤驱动在绑定的时候获取一些信息

NDIS过滤驱动在绑定的时候获取一些信息.
同理:minifilter的PFLT_INSTANCE_SETUP_CALLBACK也可以获取类似的信息.
     wfp和wsk也应该有.
此文虽然简单,仅仅3行代码,但是自己的所得,无人指导.

VOID PtBindAdapter(OUT PNDIS_STATUS Status, IN  NDIS_HANDLE BindContext, IN  PNDIS_STRING DeviceName, IN  PVOID SystemSpecific1, IN  PVOID SystemSpecific2)
/*++
Routine Description:Called by NDIS to bind to a miniport below.
Arguments:
    Status            - Return status of bind here.
    BindContext        - Can be passed to NdisCompleteBindAdapter if this call is pended.
    DeviceName         - Device name to bind to. This is passed to NdisOpenAdapter.例如:"\DEVICE\NDISWANIPV6","\DEVICE\NDISWANBH"
    SystemSpecific1    - Can be passed to NdisOpenProtocolConfiguration to read per-binding information.其内容为:"PASSTHRU\Parameters\Adapters\NDISWANIPV6".
    SystemSpecific2    - Unused
Return Value:
    NDIS_STATUS_PENDING    if this call is pended. In this case call NdisCompleteBindAdapter to complete.
    Anything else          Completes this call synchronously
--*/
{
    NDIS_HANDLE                     ConfigHandle = NULL;
    PNDIS_CONFIGURATION_PARAMETER   Param;
    NDIS_STRING                     DeviceStr = NDIS_STRING_CONST("UpperBindings");
    NDIS_STRING                     NdisVersionStr = NDIS_STRING_CONST("NdisVersion");
    PADAPT                          pAdapt = NULL;
    NDIS_STATUS                     Sts;
    UINT                            MediumIndex;
    ULONG                           TotalSize;

    UNREFERENCED_PARAMETER(BindContext);
    UNREFERENCED_PARAMETER(SystemSpecific2);

    NdisOpenProtocolConfiguration(Status, &ConfigHandle, SystemSpecific1);// Access the configuration section for our binding-specific parameters.
    if (*Status != NDIS_STATUS_SUCCESS) {//SystemSpecific1的内容是:"PASSTHRU\Parameters\Adapters\NDISWANIPV6"
        return;
    }

    if (NdisDotSysVersion == 0) //初始化是0.
    {
        NdisReadConfiguration(Status, &Param, ConfigHandle, &NdisVersionStr, NdisParameterInteger);//最后一个参数的值是0.
        if (*Status != NDIS_STATUS_SUCCESS)  {
            NdisCloseConfiguration(ConfigHandle);
            return;
        }          
        NdisDotSysVersion = Param->ParameterData.IntegerData;//设置值.
    }

    // Read the "UpperBindings" reserved key that contains a list of device names representing our miniport instances corresponding to this lower binding.
    // Since this is a 1:1 IM driver, this key contains exactly one name.

    // If we want to implement a N:1 mux driver (N adapter instances over a single lower binding),
    // then UpperBindings will be a MULTI_SZ containing a list of device names - we would loop through this list,calling NdisIMInitializeDeviceInstanceEx once for each name in it.
    NdisReadConfiguration(Status, &Param, ConfigHandle, &DeviceStr, NdisParameterString);//最后一个参数的值是2.
    if (*Status != NDIS_STATUS_SUCCESS) {
        NdisCloseConfiguration(ConfigHandle);
        return;
    }

    // Allocate memory for the Adapter structure. This represents both the protocol context as well as the adapter structure when the miniport is initialized.
    // In addition to the base structure, allocate space for the device instance string.
    TotalSize = sizeof(ADAPT) + Param->ParameterData.StringData.MaximumLength;
    NdisAllocateMemoryWithTag(&pAdapt, TotalSize, TAG);
    if (pAdapt == NULL) {
        *Status = NDIS_STATUS_RESOURCES;
        NdisCloseConfiguration(ConfigHandle);
        return;
    }

    // Initialize the adapter structure. We copy in the IM device name as well, because we may need to use it in a call to NdisIMCancelInitializeDeviceInstance.
    // The string returned by NdisReadConfiguration is active (i.e. available) only for the duration of this call to our BindAdapter handler.
    NdisZeroMemory(pAdapt, TotalSize);
    pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength;
    pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length;
    pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(ADAPT));//要移动的内容是:"\Device\{F3A2DED5-DB38-4164-9CF1-48149A08DC7A}".
    NdisMoveMemory(pAdapt->DeviceName.Buffer, Param->ParameterData.StringData.Buffer, Param->ParameterData.StringData.MaximumLength);

    KdPrint(("Name: %wZ\n", DeviceName));
    KdPrint(("Name: %wZ\n", SystemSpecific1));
    KdPrint(("Name: %wZ\n", &(pAdapt->DeviceName)));

    NdisInitializeEvent(&pAdapt->Event);
    NdisAllocateSpinLock(&pAdapt->Lock);

    // Allocate a packet pool for sends. We need this to pass sends down.We cannot use the same packet descriptor that came down to our send handler (see also NDIS 5.1 packet stacking).
    NdisAllocatePacketPoolEx(Status, &pAdapt->SendPacketPoolHandle, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, sizeof(SEND_RSVD));
    if (*Status != NDIS_STATUS_SUCCESS)  {
        NdisCloseConfiguration(ConfigHandle);
        return;
    }

    // Allocate a packet pool for receives. We need this to indicate receives.Same consideration as sends (see also NDIS 5.1 packet stacking).
    NdisAllocatePacketPoolEx(Status, &pAdapt->RecvPacketPoolHandle, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET);
    if (*Status != NDIS_STATUS_SUCCESS)  {
        NdisCloseConfiguration(ConfigHandle);
        return;
    }

    //Now open the adapter below and complete the initialization.得到了设备的类型,及网卡的类型绑定句柄等信息.
    NdisOpenAdapter(Status, &Sts, &pAdapt->BindingHandle,&MediumIndex, MediumArray, sizeof(MediumArray)/sizeof(NDIS_MEDIUM), ProtHandle, pAdapt, DeviceName, 0, NULL);
    if (*Status == NDIS_STATUS_PENDING) {
        NdisWaitEvent(&pAdapt->Event, 0);
        *Status = pAdapt->Status;
    }

    if (*Status != NDIS_STATUS_SUCCESS) {
        NdisCloseConfiguration(ConfigHandle);
        return;
    }

    PtReferenceAdapt(pAdapt);//自己写的函数.

#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW, "Ndis guarantees MediumIndex to be within bounds");
    pAdapt->Medium = MediumArray[MediumIndex];

    // Now ask NDIS to initialize our miniport (upper) edge.
    // Set the flag below to synchronize with a possible call to our protocol Unbind handler that may come in before our miniport initialization happens.
    pAdapt->MiniportInitPending = TRUE;
    NdisInitializeEvent(&pAdapt->MiniportInitEvent);

    PtReferenceAdapt(pAdapt);//自己写的函数.

    *Status = NdisIMInitializeDeviceInstanceEx(DriverHandle, &pAdapt->DeviceName, pAdapt);//导致调用MPInitialize函数。
    if (*Status != NDIS_STATUS_SUCCESS)
    {//如果失败了.
        DBGPRINT(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n", pAdapt, *Status));
        if (pAdapt->MiniportIsHalted == TRUE)
        {
            if (pAdapt != NULL && pAdapt->BindingHandle != NULL)
            {
                NDIS_STATUS    LocalStatus;              
                NdisResetEvent(&pAdapt->Event);// Close the binding we opened above.              
                NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle);
                pAdapt->BindingHandle = NULL;
                if (LocalStatus == NDIS_STATUS_PENDING) {
                    NdisWaitEvent(&pAdapt->Event, 0);
                    LocalStatus = pAdapt->Status;                  
                }
                if (PtDereferenceAdapt(pAdapt))  {
                    pAdapt = NULL;
                }
            }
        }          

        NdisCloseConfiguration(ConfigHandle);
    }    

    PtDereferenceAdapt(pAdapt);//自己写的函数.

    DBGPRINT(("Protocol BindAdapter:Status %x\n", *Status));
}

打印信息如下:
Name: \DEVICE\NDISWANIPV6
Name: PASSTHRU\Parameters\Adapters\NDISWANIPV6
Name: \Device\{3AD1CC5D-C784-4EBB-9B1B-79F27229CA27}
Protocol BindAdapter:Status 0
Name: \DEVICE\NDISWANIP
Name: PASSTHRU\Parameters\Adapters\NDISWANIP
Name: \Device\{ADA93AA1-A280-42DC-9F39-16F5C1A0EC40}
Protocol BindAdapter:Status 0
Name: \DEVICE\NDISWANBH
Name: PASSTHRU\Parameters\Adapters\NDISWANBH
Name: \Device\{1AF4AD0B-9975-414F-A514-E2776F1F1750}
Protocol BindAdapter:Status 0
Name: \DEVICE\{D0144834-7DC9-4868-A5E8-33D878317E4E}
Name: PASSTHRU\Parameters\Adapters\{D0144834-7DC9-4868-A5E8-33D878317E4E}
Name: \Device\{9720D192-57F6-46FC-8ECF-32A67E0AA3C6}
Protocol BindAdapter:Status 0

made by correy
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

改进版的如下:
添加个友好名字:

VOID PtBindAdapter(OUT PNDIS_STATUS Status, IN  NDIS_HANDLE BindContext, IN  PNDIS_STRING DeviceName, IN  PVOID SystemSpecific1, IN  PVOID SystemSpecific2)
/*++
Routine Description:
    Called by NDIS to bind to a miniport below.
    此函数会调用多次,根据注册表的配置而定,由NdisRegisterProtocol引起,调用时机可能在驱动入口和ADDdevice函数运行完毕之后.
    绑定DeviceName(SystemSpecific1)的网卡.
Arguments:
    Status             - Return status of bind here.
    BindContext        - Can be passed to NdisCompleteBindAdapter if this call is pended.
    DeviceName         - Device name to bind to. This is passed to NdisOpenAdapter.值为:"\DEVICE\NDISWANIPV6" 或者"\DEVICE\{B80E2F34-2A57-4862-8D52-0EED3B6BB4F0}".
    SystemSpecific1    - Can be passed to NdisOpenProtocolConfiguration to read per-binding information.
                         值为: "PASSTHRU\Parameters\Adapters\NDISWANIPV6"或者"PASSTHRU\Parameters\Adapters\{B80E2F34-2A57-4862-8D52-0EED3B6BB4F0}".
    SystemSpecific2    - Unused
Return Value:
    NDIS_STATUS_PENDING    if this call is pended. In this case call NdisCompleteBindAdapter to complete.
    Anything else          Completes this call synchronously
--*/
{
    NDIS_HANDLE                     ConfigHandle = NULL;
    PNDIS_CONFIGURATION_PARAMETER   Param;
    NDIS_STRING                     DeviceStr = NDIS_STRING_CONST("UpperBindings");
    NDIS_STRING                     NdisVersionStr = NDIS_STRING_CONST("NdisVersion");
    PADAPT                          pAdapt = NULL;
    NDIS_STATUS                     Sts;
    UINT                            MediumIndex;
    ULONG                           TotalSize;
    BOOLEAN                         NoCleanUpNeeded = FALSE;
    NDIS_STRING                    AdapterInstanceName;

    UNREFERENCED_PARAMETER(BindContext);
    UNREFERENCED_PARAMETER(SystemSpecific2);
   
    DBGPRINT(("绑定网卡:==> Protocol BindAdapter\n"));//第一个调用的函数

    do
    {      
        NdisOpenProtocolConfiguration(Status, &ConfigHandle, SystemSpecific1);//获取配置句柄. Access the configuration section for our binding-specific parameters.
        if (*Status != NDIS_STATUS_SUCCESS) {
            break;
        }

        if (NdisDotSysVersion == 0) //这个变量的初始值为0
        {
            NdisReadConfiguration(Status, &Param, ConfigHandle, &NdisVersionStr, NdisParameterInteger);
            if (*Status != NDIS_STATUS_SUCCESS)  {
                break;
            }          
            NdisDotSysVersion = Param->ParameterData.IntegerData;//==0x60014
        }
           
        // Read the "UpperBindings" reserved key that contains a list of device names representing our miniport instances corresponding to this lower binding.
        // Since this is a 1:1 IM driver, this key contains exactly one name.
        //
        // If we want to implement a N:1 mux driver (N adapter instances over a single lower binding),
        // then UpperBindings will be a MULTI_SZ containing a list of device names - we would loop through this list,
        // calling NdisIMInitializeDeviceInstanceEx once for each name in it.
        NdisReadConfiguration(Status, &Param, ConfigHandle, &DeviceStr, NdisParameterString);//获取到第二个参数的一个成员的值是"\Device\{A58AE6BC-1CE1-4EEC-AAEC-59AB2DAFE408}"
        if (*Status != NDIS_STATUS_SUCCESS) {
            break;
        }

        // Allocate memory for the Adapter structure.
        // This represents both the protocol context as well as the adapter structure when the miniport is initialized.
        // In addition to the base structure, allocate space for the device instance string.
        TotalSize = sizeof(ADAPT) + Param->ParameterData.StringData.MaximumLength;
        NdisAllocateMemoryWithTag(&pAdapt, TotalSize, TAG);
        if (pAdapt == NULL) {
            *Status = NDIS_STATUS_RESOURCES;
            break;
        }
        // Initialize the adapter structure.
        // We copy in the IM device name as well, because we may need to use it in a call to NdisIMCancelInitializeDeviceInstance.
        // The string returned by NdisReadConfiguration is active (i.e. available) only for the duration of this call to our BindAdapter handler.
        NdisZeroMemory(pAdapt, TotalSize);
        pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength;
        pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length;
        pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(ADAPT));
        NdisMoveMemory(pAdapt->DeviceName.Buffer, Param->ParameterData.StringData.Buffer, Param->ParameterData.StringData.MaximumLength);//复制上面的字符串.

        NdisInitializeEvent(&pAdapt->Event);
        NdisAllocateSpinLock(&pAdapt->Lock);

        // Allocate a packet pool for sends.
        // We need this to pass sends down.We cannot use the same packet descriptor that came down to our send handler (see also NDIS 5.1 packet stacking).
        NdisAllocatePacketPoolEx(Status, &pAdapt->SendPacketPoolHandle, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, sizeof(SEND_RSVD));//获取内存句柄.
        if (*Status != NDIS_STATUS_SUCCESS)  {
            break;
        }
        // Allocate a packet pool for receives.
        // We need this to indicate receives.Same consideration as sends (see also NDIS 5.1 packet stacking).
        NdisAllocatePacketPoolEx(Status, &pAdapt->RecvPacketPoolHandle, MIN_PACKET_POOL_SIZE, MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE, PROTOCOL_RESERVED_SIZE_IN_PACKET);
        if (*Status != NDIS_STATUS_SUCCESS)  {
            break;
        }

        // Now open the adapter below and complete the initialization
        NdisOpenAdapter(Status, &Sts, &pAdapt->BindingHandle,&MediumIndex, MediumArray, sizeof(MediumArray)/sizeof(NDIS_MEDIUM), ProtHandle, pAdapt, DeviceName, 0, NULL);
        if (*Status == NDIS_STATUS_PENDING) {//注意返回的第三个和第四个参数.
            NdisWaitEvent(&pAdapt->Event, 0);
            *Status = pAdapt->Status;
        }
        if (*Status != NDIS_STATUS_SUCCESS) {
            break;
        }

        PtReferenceAdapt(pAdapt);//自己实现的函数.

        NdisQueryAdapterInstanceName(&AdapterInstanceName, pAdapt->BindingHandle);//注意这一行的位置,不然这里蓝屏.

        KdPrint(("DeviceName: %wZ\n", DeviceName));
        KdPrint(("相对注册表路径: %wZ\n", SystemSpecific1));
        KdPrint(("DeviceName(UUID): %wZ\n", &(pAdapt->DeviceName)));
        KdPrint(("Friendly names: %wZ\n", &AdapterInstanceName));      

        NdisFreeMemory(AdapterInstanceName.Buffer, 0, 0);
        AdapterInstanceName.Buffer = NULL;

#pragma prefast(suppress: __WARNING_POTENTIAL_BUFFER_OVERFLOW, "Ndis guarantees MediumIndex to be within bounds");
        pAdapt->Medium = MediumArray[MediumIndex];
        // Now ask NDIS to initialize our miniport (upper) edge.
        // Set the flag below to synchronize with a possible call to our protocol Unbind handler that may come in before our miniport initialization happens.
        pAdapt->MiniportInitPending = TRUE;
        NdisInitializeEvent(&pAdapt->MiniportInitEvent);
        PtReferenceAdapt(pAdapt);//自己实现的函数.

        *Status = NdisIMInitializeDeviceInstanceEx(DriverHandle, &pAdapt->DeviceName, pAdapt);//导致调用MPInitialize函数。
        if (*Status != NDIS_STATUS_SUCCESS) //失败的处理,主要是释放和设置.
        {
            if (pAdapt->MiniportIsHalted == TRUE)  {
                NoCleanUpNeeded = TRUE;
            }          
            DBGPRINT(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n", pAdapt, *Status));          
            if (PtDereferenceAdapt(pAdapt))  {//自己实现的函数.
                pAdapt = NULL;
            }          
            break;
        }
       
        PtDereferenceAdapt(pAdapt);//自己实现的函数.
    } while(FALSE);
   
    if (ConfigHandle != NULL) {// Close the configuration handle now - see comments above with the call to NdisIMInitializeDeviceInstanceEx.
        NdisCloseConfiguration(ConfigHandle);//不再用的句柄的释放.
    }

    if ((*Status != NDIS_STATUS_SUCCESS) && (NoCleanUpNeeded == FALSE))//失败的处理
    {
        if (pAdapt != NULL)
        {
            if (pAdapt->BindingHandle != NULL)
            {
                NDIS_STATUS    LocalStatus;  
               
                NdisResetEvent(&pAdapt->Event);// Close the binding we opened above.              
                NdisCloseAdapter(&LocalStatus, pAdapt->BindingHandle);
                pAdapt->BindingHandle = NULL;

                if (LocalStatus == NDIS_STATUS_PENDING) {
                     NdisWaitEvent(&pAdapt->Event, 0);
                     LocalStatus = pAdapt->Status;                  
                }

                if (PtDereferenceAdapt(pAdapt))  {
                     pAdapt = NULL;
                }
            }
        }
    }

    DBGPRINT(("<== Protocol BindAdapter: pAdapt %p, Status %x\n", pAdapt, *Status));
    KdPrint(("\n"));
}

打印的效果如下:

绑定网卡:==> Protocol BindAdapter
DeviceName: \DEVICE\NDISWANIPV6
相对注册表路径: PASSTHRU\Parameters\Adapters\NDISWANIPV6
DeviceName(UUID): \Device\{6192A548-9667-4920-9B23-6F286485D740}
Friendly names: WAN Miniport (IPv6)
<== Protocol BindAdapter: pAdapt FFFFFA80060CFB60, Status 0

绑定网卡:==> Protocol BindAdapter
DeviceName: \DEVICE\NDISWANIP
相对注册表路径: PASSTHRU\Parameters\Adapters\NDISWANIP
DeviceName(UUID): \Device\{A811A14F-46BE-4EED-8EB9-75C03FC32A0A}
Friendly names: WAN Miniport (IP)
<== Protocol BindAdapter: pAdapt FFFFFA80068EB010, Status 0

绑定网卡:==> Protocol BindAdapter
DeviceName: \DEVICE\NDISWANBH
相对注册表路径: PASSTHRU\Parameters\Adapters\NDISWANBH
DeviceName(UUID): \Device\{F68E4046-F7BD-4C59-BCB3-EB9CAB539544}
Friendly names: WAN Miniport (Network Monitor)
<== Protocol BindAdapter: pAdapt FFFFFA8005DCD790, Status 0

绑定网卡:==> Protocol BindAdapter
DeviceName: \DEVICE\{D0144834-7DC9-4868-A5E8-33D878317E4E}
相对注册表路径: PASSTHRU\Parameters\Adapters\{D0144834-7DC9-4868-A5E8-33D878317E4E}
DeviceName(UUID): \Device\{BDE90A81-773E-4A27-B577-5AFB5634CE40}
Friendly names: 基于 Marvell Yukon 88E8057 PCI-E 的通用千兆以太网控制器
<== Protocol BindAdapter: pAdapt FFFFFA80052D3450, Status 0

made at 2014.05.02

没有评论:

发表评论