⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packet.c

📁 使用NDIS协议完成的一个较为简单的驱动程序编程范例(windons驱动程序编程)
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c) 1990-2000  Microsoft Corporation

Module Name:

    packet.c

Abstract:


Author:


Environment:

    Kernel mode only.

Notes:


Future:



Revision History:

  Fixed bugs and converted to NDIS 5.0. This driver handles 
  dynamic binding and unbinding to underlying NICs, receives
  pnp and power management callbacks, and implements 
  ReceivePacketHandler. 
                            - Eliyas Yakub June, 1999
  
--*/
#include "ntddk.h"
#include "ndis.h"
#include "ntddpack.h"
#include "packet.h"
#include "stdio.h"


NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )

/*++

Routine Description:

    This routine initializes the Packet driver.
	本例程用于初始化本驱动程序

Arguments:

    DriverObject - Pointer to driver object created by system.

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

Return Value:

    NT Status code
    
--*/

{

    NDIS_PROTOCOL_CHARACTERISTICS   protocolChar;
    NTSTATUS                        status = STATUS_SUCCESS;
    NDIS_STRING                     protoName = NDIS_STRING_CONST("Packet");     
    UNICODE_STRING                  ntDeviceName;
    UNICODE_STRING                  win32DeviceName;
    BOOLEAN                         fSymbolicLink = FALSE;
    PDEVICE_OBJECT                  deviceObject;

    DebugPrint(("\n\nDriverEntry\n"));
    
    Globals.DriverObject = DriverObject;
    
	//
    // Save the RegistryPath.
    // 保存注册路径
	//
    Globals.RegistryPath.MaximumLength = RegistryPath->Length +
                                          sizeof(UNICODE_NULL);
    Globals.RegistryPath.Length = RegistryPath->Length;
    Globals.RegistryPath.Buffer = ExAllocatePool(
                                       PagedPool,
                                       Globals.RegistryPath.MaximumLength
                                       );    

    if (!Globals.RegistryPath.Buffer) {

        DebugPrint (("Couldn't allocate pool for registry path."));

        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);

    RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);

    //
    // Create a control device object for this driver.
    // Application can send an IOCTL to this device to get 
    // bound adapter information.
    // 为本驱动程序创建一个控制设备对象,用户应用程序可以
	// 发送的控制命令被发送到该对象,它帮助用户进行参数设定
	// 以及获取适配器信息等操作.
	//
    status = IoCreateDevice (DriverObject,
                             0,
                             &ntDeviceName,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             FALSE,
                             &deviceObject);

    
    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.
        // 出现这种创建控制对象不成功的原因可能是:不存在足够的内存来
		// 创建该对象,也可能是已经有相同名字的对象已经存在;后者可能是
		// 由于机器上已经安装了本设备的一个实例.
		//
        goto ERROR;
    }

    RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);

    status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );

    if (!NT_SUCCESS(status))    // If we couldn't create the link then
    {                           //  abort installation.
        goto ERROR;
    }

    fSymbolicLink = TRUE; // symboliclink is created
    
    deviceObject->Flags |= DO_BUFFERED_IO;
    Globals.ControlDeviceObject = deviceObject;

    InitializeListHead(&Globals.AdapterList);
    KeInitializeSpinLock(&Globals.GlobalLock);

    //
    // Initialize the protocol characterstic structure
    //
    
    NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

    protocolChar.MajorNdisVersion            = 5;
    protocolChar.MinorNdisVersion            = 0;
    protocolChar.Name                        = protoName;
    protocolChar.OpenAdapterCompleteHandler  = PacketOpenAdapterComplete;
    protocolChar.CloseAdapterCompleteHandler = PacketCloseAdapterComplete;
    protocolChar.SendCompleteHandler         = PacketSendComplete;
    protocolChar.TransferDataCompleteHandler = PacketTransferDataComplete;
    protocolChar.ResetCompleteHandler        = PacketResetComplete;
    protocolChar.RequestCompleteHandler      = PacketRequestComplete;
    protocolChar.ReceiveHandler              = PacketReceiveIndicate;
    protocolChar.ReceiveCompleteHandler      = PacketReceiveComplete;
    protocolChar.StatusHandler               = PacketStatus;
    protocolChar.StatusCompleteHandler       = PacketStatusComplete;
    protocolChar.BindAdapterHandler          = PacketBindAdapter;
    protocolChar.UnbindAdapterHandler        = PacketUnbindAdapter;
    protocolChar.UnloadHandler               = NULL;
    protocolChar.ReceivePacketHandler        = PacketReceivePacket;
    protocolChar.PnPEventHandler             = PacketPNPHandler;

    //
    // Register as a protocol driver
    //
    
    NdisRegisterProtocol(
        &status,
        &Globals.NdisProtocolHandle,
        &protocolChar,
        sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

    if (status != NDIS_STATUS_SUCCESS) {
        DebugPrint(("Failed to register protocol with NDIS\n"));
        status = STATUS_UNSUCCESSFUL;
        goto ERROR;        
    }
    
    //
    // Now set only the dispatch points we would like to handle.
    // 设定我们需要的分发例程,这些分发例程是本实验的关键所在.
	//

    DriverObject->MajorFunction[IRP_MJ_CREATE] = PacketOpen;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = PacketClose;
    DriverObject->MajorFunction[IRP_MJ_READ]   = PacketRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE]  = PacketWrite;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP]  = PacketCleanup;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = PacketIoControl;
    DriverObject->DriverUnload = PacketUnload;
       
    return(STATUS_SUCCESS);

ERROR:
    if(deviceObject)
        IoDeleteDevice(deviceObject);
    if(fSymbolicLink)
        IoDeleteSymbolicLink(&win32DeviceName);
    if(Globals.RegistryPath.Buffer)        
        ExFreePool(Globals.RegistryPath.Buffer);

    return status;


}


VOID
PacketUnload(
    IN PDRIVER_OBJECT DriverObject
    )
/*++

Routine Description:

    Free all the allocated resources, etc.

Arguments:

    DriverObject - pointer to a driver object.

Return Value:

    VOID.

--*/
{

    NDIS_STATUS        status;
    UNICODE_STRING     win32DeviceName;

    DebugPrint(("Unload Enter\n"));

    //
    // First delete the Control deviceobject and the corresponding
    // symbolicLink
    //

    RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
    IoDeleteSymbolicLink(&win32DeviceName);           
    if(Globals.ControlDeviceObject)
        IoDeleteDevice(Globals.ControlDeviceObject);
    //
    // Unbind from all the adapters. The system removes the driver code 
    // pages from the memory as soon as the unload returns. So you 
    // must wait for all the CloseAdapterCompleteHandler to finish 
    // before returning from the unload routine. You don't any callbacks
    // to trigger after the driver is unloaded.
    // 
    
    while(DriverObject->DeviceObject)
    {
        PacketUnbindAdapter(&status,
                    DriverObject->DeviceObject->DeviceExtension,
                    NULL);
    }

    if(Globals.RegistryPath.Buffer)
        ExFreePool(Globals.RegistryPath.Buffer);

    DebugPrint(("Deregister\n"));

    NdisDeregisterProtocol(
        &status,
        Globals.NdisProtocolHandle
        );
    DebugPrint(("Unload Exit\n"));

}




NTSTATUS
PacketIoControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the dispatch routine for Filter OID and Reset requests.

Arguments:

    DeviceObject - Pointer to the device object.

    Irp - Pointer to the request packet.

Return Value:

    Status is returned.

--*/

{

    POPEN_INSTANCE      open;
    PIO_STACK_LOCATION  irpSp;
    PINTERNAL_REQUEST   pRequest;
    ULONG               functionCode;
    NDIS_STATUS         status;
    ULONG               dataLength =0;

    DebugPrint(("IoControl\n"));
    
    irpSp = IoGetCurrentIrpStackLocation(Irp);

    functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode;

    //
    // Check whether this request is to get bound adapter list.
    //判断是否请求枚举适配器
	//
    if (functionCode == IOCTL_ENUM_ADAPTERS) {
        //
        // If the request is not made to the controlobject, fail
        // the request.
        //
        if(DeviceObject != Globals.ControlDeviceObject) {
            status = STATUS_INVALID_DEVICE_REQUEST;
        } else {
            status = PacketGetAdapterList(
                            Irp->AssociatedIrp.SystemBuffer, 
                            irpSp->Parameters.DeviceIoControl.OutputBufferLength,
                            &dataLength
                            );        
        }
        Irp->IoStatus.Status = status;
        Irp->IoStatus.Information = dataLength;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }

    //
    // Increment the outstanding IRP count.
    //
    open =  DeviceObject->DeviceExtension;
    IoIncrement(open);

    //
    // Check to see whether you are still bound to the adapter
    //

    if(!open->Bound)
    {
        Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        IoDecrement(open);
        return status;
    }


    DebugPrint(("Function code is %08lx  buff size=%08lx  %08lx\n",
            functionCode,irpSp->Parameters.DeviceIoControl.InputBufferLength,
            irpSp->Parameters.DeviceIoControl.OutputBufferLength));

    //
    // Important: Since we have marked the IRP pending, we must return 
    // STATUS_PENDING even we happen to complete the IRP synchronously.
    // 
    
    IoMarkIrpPending(Irp);

    if (functionCode == IOCTL_PROTOCOL_RESET) {


        DebugPrint(("IoControl - Reset request\n"));

        //
        // Since NDIS doesn't have an interface to cancel a request
        // pending at miniport, we cannot set a cancel routine.
        // As a result if the application that made the request
        // terminates, we wait in the Cleanup routine for all pending
        // NDIS requests to complete.
        //
        
        ExInterlockedInsertTailList(
                &open->ResetIrpList,
                &Irp->Tail.Overlay.ListEntry,
                &open->ResetQueueLock);


        NdisReset(
            &status,
            open->AdapterHandle
            );


        if (status != NDIS_STATUS_PENDING) {

            DebugPrint(("IoControl - ResetComplete being called\n"));

            PacketResetComplete(
                open,
                status
                );

        }

    } else {
        //
        //  See if it is an Ndis request
        //
        PPACKET_OID_DATA    OidData=Irp->AssociatedIrp.SystemBuffer;

        pRequest = ExAllocatePool(NonPagedPool, sizeof(INTERNAL_REQUEST));

        if(NULL == pRequest)
        {
            Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
            IoCompleteRequest (Irp, IO_NO_INCREMENT);
            IoDecrement(open);
            return STATUS_PENDING;
        }         
        pRequest->Irp=Irp;

        if (((functionCode == IOCTL_PROTOCOL_SET_OID) 
                        || (functionCode == IOCTL_PROTOCOL_QUERY_OID))
            &&
            (irpSp->Parameters.DeviceIoControl.InputBufferLength 
                        == irpSp->Parameters.DeviceIoControl.OutputBufferLength)
            &&
            (irpSp->Parameters.DeviceIoControl.InputBufferLength 
                        >= sizeof(PACKET_OID_DATA))
            &&
            (irpSp->Parameters.DeviceIoControl.InputBufferLength 
                        >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {

            DebugPrint(("IoControl: Request: Oid=%08lx, Length=%08lx\n",
                            OidData->Oid,OidData->Length));

            //
            //  The buffer is valid
            //
            if (functionCode == IOCTL_PROTOCOL_SET_OID) {

                pRequest->Request.RequestType=NdisRequestSetInformation;
                pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -