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

  • Post author:
  • Post category:其他



目录


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 版权协议,转载请附上原文出处链接和本声明。