代码先锋网 代码片段及技术文章聚合

NDIS协议驱动学习二——协议驱动DriverEntry

技术标签: windows内核编程  windows  内核  驱动程序

 

目录

 

1 生成控制设备

1.1DriverEntry函数原型

1.2.注册一个协议

1.2.1 定义需要用到的变量

 1.2.2 生成控制设备和该设备的符号链接

1.2.3.注册协议  填写协议特征(回调函数)

1.2.4 DriverEntry收尾工作


1 生成控制设备

1.1DriverEntry函数原型

NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT   pDriverObject,
    IN PUNICODE_STRING  pRegistryPath
    );
/*
Routine Description:

    Called on loading. We create a device object to handle user-mode requests
    on, and register ourselves as a protocol with NDIS.

Arguments:

    pDriverObject - Pointer to driver object created by system.

    pRegistryPath - Pointer to the Unicode name of the registry path
        for this driver.

Return Value:

    NT Status code*/

1.2.注册一个协议

1.2.1 定义需要用到的变量

  //协议驱动的协议特征
    NDIS_PROTOCOL_CHARACTERISTICS   protocolChar;
    //状态变量,当返回值用
    NTSTATUS                        status = STATUS_SUCCESS;
    //NDIS_STRING其实就是UNICODE_STRING 
    NDIS_STRING                     protoName = NDIS_STRING_CONST("NdisProt");     
    UNICODE_STRING                  ntDeviceName;
    UNICODE_STRING                  win32DeviceName;
    BOOLEAN                         fSymbolicLink = FALSE;
    PDEVICE_OBJECT                  deviceObject = NULL;
    //用宏避免出现参数未使用警告 这个语句非常重要,因为我们经常不会用到pRegistryPath
    UNREFERENCED_PARAMETER(pRegistryPath);

    DEBUGP(DL_LOUD, ("DriverEntry\n"));
    //在全局变量中记录驱动对象指针,也就是DriverEntry用到的本驱动对象指针
    Globals.pDriverObject = pDriverObject;
    //初始化一个事件
    NPROT_INIT_EVENT(&Globals.BindsComplete);

 1.2.2 生成控制设备和该设备的符号链接

    do
    {

        //
        // Create our device object using which an application can
        // access NDIS devices.
        //
      //初始化控制设备名 #define NT_DEVICE_NAME          L"\\Device\\NdisProt"
        RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);
        //不同系统下创建新的设备对象
#ifndef WIN9X
        status = IoCreateDeviceSecure(pDriverObject,
                                 0,
                                 &ntDeviceName,
                                 FILE_DEVICE_NETWORK,
                                 FILE_DEVICE_SECURE_OPEN,
                                 FALSE,
                                 &SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
                                 NULL,
                                 &deviceObject);

#else     
        status = IoCreateDevice(pDriverObject,
                                 0,
                                 &ntDeviceName,
                                 FILE_DEVICE_NETWORK,
                                 FILE_DEVICE_SECURE_OPEN,
                                 FALSE,
                                 &deviceObject);
#endif
        if (!NT_SUCCESS (status))
        {
            //
            // Either not enough memory to create a deviceobject or another
            // deviceobject with the same name exits. This could happen
            // if you install another instance of this device.
            //
            break;
        }

        //初始化符号链接 #define DOS_DEVICE_NAME         L"\\DosDevices\\NdisProt"
        RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
        //生成符号链接
        status = IoCreateSymbolicLink(&win32DeviceName, &ntDeviceName);

        if (!NT_SUCCESS(status))
        {
            break;
        }

        fSymbolicLink = TRUE;
        //设备采用直接IO通信方式
        deviceObject->Flags |= DO_DIRECT_IO;
        //在全局变量中记下控制设备对象指针
        Globals.ControlDeviceObject = deviceObject;

        NPROT_INIT_LIST_HEAD(&Globals.OpenList);
        NPROT_INIT_LOCK(&Globals.GlobalLock);

 

1.2.3.注册协议  填写协议特征(回调函数)

很简单 只要将协议特征与我们所要填写的API函数名对应起来就行了,和一般的过滤设备绑定是一个套路

//填写协议特征        
NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

        protocolChar.MajorNdisVersion            = 5;
        protocolChar.MinorNdisVersion            = 0;
        protocolChar.Name                        = protoName;
        protocolChar.OpenAdapterCompleteHandler  = NdisProtOpenAdapterComplete;
        protocolChar.CloseAdapterCompleteHandler = NdisProtCloseAdapterComplete;
        protocolChar.SendCompleteHandler         = NdisProtSendComplete;
        protocolChar.TransferDataCompleteHandler = NdisProtTransferDataComplete;
        protocolChar.ResetCompleteHandler        = NdisProtResetComplete;
        protocolChar.RequestCompleteHandler      = NdisProtRequestComplete;
        protocolChar.ReceiveHandler              = NdisProtReceive;
        protocolChar.ReceiveCompleteHandler      = NdisProtReceiveComplete;
        protocolChar.StatusHandler               = NdisProtStatus;
        protocolChar.StatusCompleteHandler       = NdisProtStatusComplete;
        protocolChar.BindAdapterHandler          = NdisProtBindAdapter;
        protocolChar.UnbindAdapterHandler        = NdisProtUnbindAdapter;
        protocolChar.UnloadHandler               = NULL;
        protocolChar.ReceivePacketHandler        = NdisProtReceivePacket;
        protocolChar.PnPEventHandler             = NdisProtPnPEventHandler;

        //
        // 注册协议
        //
    
        NdisRegisterProtocol(
            (PNDIS_STATUS)&status,
            &Globals.NdisProtocolHandle,
            &protocolChar,
            sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

        if (status != NDIS_STATUS_SUCCESS)
        {
            DEBUGP(DL_WARN, ("Failed to register protocol with NDIS\n"));
            status = STATUS_UNSUCCESSFUL;
            break;
        }

#ifdef NDIS51
        Globals.PartialCancelId = NdisGeneratePartialCancelId();
        Globals.PartialCancelId <<= ((sizeof(PVOID) - 1) * 8);
        DEBUGP(DL_LOUD, ("DriverEntry: CancelId %lx\n", Globals.PartialCancelId));
#endif

        //
        // 填写本驱动所需要的分发函数(仅仅用于控制设备)
        //
        pDriverObject->MajorFunction[IRP_MJ_CREATE] = NdisProtOpen;
        pDriverObject->MajorFunction[IRP_MJ_CLOSE]  = NdisProtClose;
        pDriverObject->MajorFunction[IRP_MJ_READ]   = NdisProtRead;
        pDriverObject->MajorFunction[IRP_MJ_WRITE]  = NdisProtWrite;
        pDriverObject->MajorFunction[IRP_MJ_CLEANUP]  = NdisProtCleanup;
        pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = NdisProtIoControl;
        pDriverObject->DriverUnload = NdisProtUnload;

        status = STATUS_SUCCESS;
        
    }
    while (FALSE);

1.2.4 DriverEntry收尾工作

收尾无非就是如果status状态不为success就释放掉上文创建的资源;如果成功则返回status结束DriverEntry

    if (!NT_SUCCESS(status))
    {
        if (deviceObject)
        {
            IoDeleteDevice(deviceObject);
            Globals.ControlDeviceObject = NULL;
        }

        if (fSymbolicLink)
        {
            IoDeleteSymbolicLink(&win32DeviceName);
        }
        
    }
    
    return status;

 

 

 

 

 

 

 

 

 

 

 

版权声明:本文为weixin_42709632原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42709632/article/details/106636487

智能推荐

Ndis网卡驱动是如何操控硬件的

在 DriverEntry 里设置一个_NDIS_MINIPORT_DRIVER_CHARACTERISTICS结构,初作为参数提供给 NdisMRegisterMiniportDriver 函数 系统会调用上面的初始化handle, 函数的模型如下 其中 _NDIS_MINIPORT_INIT_PARAMETERS 结构里包含一项(PNDIS_RESOURCE_LIST AllocatedRes...

linux 内核协议栈收报流程(一)ixgbe网卡驱动

首先模块加载insmod ixgbe.ko 于是看pci设备的核心结构体 当设备加载成功后,会执行ixgbe_probe函数 重点看ixgbe_init_interrupt_scheme(adapter)函数,该函数里面会初始化adapter结构体以及napi相关的东西 到此为止,网卡设置初始化完毕   其中涉及到如下几个结构体   然后当我们ifconfig dev up 时,会执行d...

24CXX eeprom驱动(I2C协议)

1、IIC驱动程序 2、24CXX驱动程序  ...

SylixOS SD协议栈之五:SDM驱动管理

1. SDM的主要功能 上一篇说道,SD Core设备主要是封装了底层的细节,为应用层提供唯一的传输接口。SDM,即SD Driver Management,是用来管理SD协议栈里的驱动的,包括硬件控制器驱动和设备类驱动(这与USB协议栈的设计非常类似),以此将两者隔离开来。SDM的功能主要有以下几点: 对上,提供Client层驱动注册的接口,包括SD 基础驱动和 SDIO子设备驱动 对下,提供H...

嵌入式驱动开发常见的协议(一)

未完善初稿,后续完善添加udp,tcp网络协议。及详细时序图,参考代码 1.USART串口协议 通用同步/异步串行接收/发送器,USART是一个全双工通用同步/异步串行收发模块,该接口是一个高度灵活的串行通信设备。 区别于UART,UART是通用异步收发传输器,USART属于UART的增强型,在异步传输时没有啥区别,但是USART比UART多了同步传输功能,他可以为通信设备提供主动时钟。(由于通常...

猜你喜欢

linux驱动--多点触控协议(multi-touch-protocol)

Multi-touch-protocol Linux内核文档multi-touch-protocol.rst...

usb协议架构及驱动架构_测试驱动的基础架构

敏捷开发运营 内容系列: 此内容是#在系列的一部分#: 敏捷的DevOps https://www.ibm.com/developerworks/library/?series_title_by=agile+devops 请继续关注本系列中的其他内容。 该内容是该系列的一部分: 敏捷DevOps 请继续关注本系列中的其他内容。 在配置环境时,大多数组织都会应用反模式,这些反模式会降低创建这些环境的...

usb协议架构及驱动架构_测试驱动的基础架构

在配置环境时,大多数组织都会应用反模式,这些反模式会降低创建这些环境的可靠性和可重复性: 一些团队手动安装和配置创建环境所需的资源。 问题在于,通常需要几天,几周或几个月的时间才能使环境达到所需的状态。 在这段时间里,团队成员可能会来去去去或忘记精确的步骤,从而使任何人都无法按预期重新创建环境。 其他团队尝试记录供应环境的每个步骤。 尽管这是一项高尚的工作,并且比不记录该过程要好得多,但是该文档很...

协议(二)

协议的实现 正如你已经看到的,当你声明的类型符合协议时,你必须实现协议中声明的所有需求: Bike实现了在Vehicle中定义的所有方法。如果没有定义加速accelerate()或stop(),则会提示一个构建错误。 定义协议保证任何遵守协议的类型都将具有你在协议中定义的所有成员。 属性的实现 回想一下,协议中的属性包含get也可能包含set需求,符合条件的类型必须至少符合这些需求。 将自行车 B...