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

📄 ndiswdm.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) Microsoft Corporation.  All rights reserved.

    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    PURPOSE.

Module Name:

   NDISWDM.C

Abstract:

    This sample provides an example of minimal driver intended for education
    purposes. Neither the driver or its sample test programs are intended
    for use in a production environment. 

Author:  Eliyas Yakub (Jan 11, 2003)

Revision History:

Notes:

--*/
#include "ndiswdm.h"

//
// Functions that are not tagged PAGEABLE by the pragma as shown below are
// by default resident (NONPAGEABLE) in memory. Make sure you don't acquire 
// spinlock or raise the IRQL in a pageable function. It's okay to call
// another nonpageable function that runs at DISPATCH_LEVEL from a
// pageable function.
//
#pragma NDIS_INIT_FUNCTION(DriverEntry)
#pragma NDIS_PAGEABLE_FUNCTION(MPInitialize)
#pragma NDIS_PAGEABLE_FUNCTION(MPHalt)
#pragma NDIS_PAGEABLE_FUNCTION(MPUnload)

#ifdef NDIS51_MINIPORT   
#pragma NDIS_PAGEABLE_FUNCTION(MPPnPEventNotify)
#endif    

MP_GLOBAL_DATA  GlobalData;
INT             MPDebugLevel = MP_INFO;
NDIS_HANDLE     NdisWrapperHandle;

NDIS_STATUS 
DriverEntry(
    PVOID DriverObject,
    PVOID RegistryPath)
/*++
Routine Description:

    In the context of its DriverEntry function, a miniport driver associates
    itself with NDIS, specifies the NDIS version that it is using, and 
    registers its entry points. 


Arguments:
    PVOID DriverObject - pointer to the driver object. 
    PVOID RegistryPath - pointer to the driver registry path.

    Return Value:
    
    NDIS_STATUS_xxx code

--*/
{

    NDIS_STATUS                   Status;
    NDIS_MINIPORT_CHARACTERISTICS MPChar;

    DEBUGP(MP_INFO, ("---> DriverEntry built on "__DATE__" at "__TIME__ "\n"));

    //
    // Associate the miniport driver with NDIS by calling the 
    // NdisMInitializeWrapper. This function allocates a structure
    // to represent this association, stores the miniport driver-
    // specific information that the NDIS Library needs in this 
    // structure, and returns NdisWrapperHandle. The driver must retain and 
    // pass this handle to NdisMRegisterMiniport when it registers its entry 
    // points. NDIS will use NdisWrapperHandle to identify the miniport driver. 
    // The miniport driver must retain this handle but it should never attempt
    // to access or interpret this handle.
    //
    NdisMInitializeWrapper(
            &NdisWrapperHandle,
            DriverObject,
            RegistryPath,
            NULL
            );
    if(!NdisWrapperHandle){
        DEBUGP(MP_ERROR, ("NdisMInitializeWrapper failed\n"));
        return NDIS_STATUS_FAILURE;
    }
    //
    // Fill in the Miniport characteristics structure with the version numbers 
    // and the entry points for driver-supplied MiniportXxx 
    //
    NdisZeroMemory(&MPChar, sizeof(MPChar));
    
    //
    // The NDIS version number, in addition to being included in 
    // NDIS_MINIPORT_CHARACTERISTICS, must also be specified when the 
    // miniport driver source code is compiled.
    //
    MPChar.MajorNdisVersion          = MP_NDIS_MAJOR_VERSION;
    MPChar.MinorNdisVersion          = MP_NDIS_MINOR_VERSION;
    
    MPChar.InitializeHandler         = MPInitialize;
    MPChar.HaltHandler               = MPHalt;
    
    MPChar.SetInformationHandler     = MPSetInformation;
    MPChar.QueryInformationHandler   = MPQueryInformation;
    
    MPChar.SendPacketsHandler        = MPSendPackets;
    MPChar.ReturnPacketHandler       = MPReturnPacket;

    MPChar.ResetHandler              = MPReset;
    MPChar.CheckForHangHandler       = MPCheckForHang; //optional

#ifdef NDIS51_MINIPORT
    MPChar.CancelSendPacketsHandler = MPCancelSendPackets;
    MPChar.PnPEventNotifyHandler    = MPPnPEventNotify;
    MPChar.AdapterShutdownHandler   = MPShutdown;
#endif


    DEBUGP(MP_LOUD, ("Calling NdisMRegisterMiniport...\n"));

    //
    // Registers miniport's entry points with the NDIS library as the first
    // step in NIC driver initialization. The NDIS will call the 
    // MiniportInitialize when the device is actually started by the PNP
    // manager.
    //
    Status = NdisMRegisterMiniport(
                    NdisWrapperHandle,
                    &MPChar,
                    sizeof(NDIS_MINIPORT_CHARACTERISTICS));
    if (Status != NDIS_STATUS_SUCCESS) {
        
        DEBUGP(MP_ERROR, ("Status = 0x%08x\n", Status));
        NdisTerminateWrapper(NdisWrapperHandle, NULL);
        
    } else {
        //
        // Initialize the global variables. The ApaterList in the
        // GloablData structure is used to track the multiple instances
        // of the same adapter. Make sure you do that before registering
        // the unload handler.
        //
        NdisAllocateSpinLock(&GlobalData.Lock);
        NdisInitializeListHead(&GlobalData.AdapterList);        
        //
        // Register an Unload handler for global data cleanup. The unload handler
        // has a more global scope, whereas the scope of the MiniportHalt function
        // is restricted to a particular miniport instance.
        //
        NdisMRegisterUnloadHandler(NdisWrapperHandle, MPUnload);
    }

    
    DEBUGP(MP_TRACE, ("<--- DriverEntry\n"));
    return Status;
    
}

NDIS_STATUS 
MPInitialize(
    OUT PNDIS_STATUS OpenErrorStatus,
    OUT PUINT SelectedMediumIndex,
    IN PNDIS_MEDIUM MediumArray,
    IN UINT MediumArraySize,
    IN NDIS_HANDLE MiniportAdapterHandle,
    IN NDIS_HANDLE WrapperConfigurationContext)
/*++
Routine Description:

    The MiniportInitialize function is a required function that sets up a 
    NIC (or virtual NIC) for network I/O operations, claims all hardware 
    resources necessary to the NIC in the registry, and allocates resources
    the driver needs to carry out network I/O operations.

    MiniportInitialize runs at IRQL = PASSIVE_LEVEL.
    
Arguments:

    Return Value:
    
    NDIS_STATUS_xxx code

--*/
{
    NDIS_STATUS         Status = NDIS_STATUS_SUCCESS;
    PMP_ADAPTER         Adapter=NULL;
    NDIS_HANDLE         ConfigurationHandle;
    UINT                index;
    NTSTATUS            ntStatus;
    ULONG               nameLength;
    
    DEBUGP(MP_TRACE, ("---> MPInitialize\n"));

    PAGED_CODE();

    do {
        //
        // Check to see if our media type exists in an array of supported 
        // media types provided by NDIS.
        //
        for(index = 0; index < MediumArraySize; ++index)
        {
            if(MediumArray[index] == NIC_MEDIA_TYPE) {
                break;
            }
        }

        if(index == MediumArraySize)
        {
            DEBUGP(MP_ERROR, ("Expected media is not in MediumArray.\n"));
            Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
            break;
        }

        //
        // Set the index value as the selected medium for our device.
        //
        *SelectedMediumIndex = index;

        //
        // Allocate adapter context structure and initialize all the 
        // memory resources for sending and receiving packets.
        //
        Status = NICAllocAdapter(&Adapter);
        if(Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        MP_INC_REF(Adapter);  

        //
        // NdisMGetDeviceProperty function enables us to get the:
        // PDO - created by the bus driver to represent our device.
        // FDO - created by NDIS to represent our miniport as a function 
        //              driver.
        // NextDeviceObject - deviceobject of another driver (filter)
        //                      attached to us at the bottom.
        // Since our driver is talking to NDISPROT, the NextDeviceObject
        // is not useful. But if we were to talk to a driver that we
        // are attached to as part of the devicestack then NextDeviceObject
        // would be our target DeviceObject for sending read/write IRPs.
        //

        NdisMGetDeviceProperty(MiniportAdapterHandle,
                           &Adapter->Pdo,
                           &Adapter->Fdo,
                           &Adapter->NextDeviceObject,
                           NULL,
                           NULL);

        ntStatus = IoGetDeviceProperty (Adapter->Pdo,
                                      DevicePropertyDeviceDescription,
                                      NIC_ADAPTER_NAME_SIZE,
                                      Adapter->AdapterDesc,
                                      &nameLength);

        if (!NT_SUCCESS (ntStatus))
        {
            DEBUGP (MP_ERROR, ("IoGetDeviceProperty failed (0x%x)\n", 
                                            ntStatus));
            Status = NDIS_STATUS_FAILURE;
            break;
        }

        Adapter->AdapterHandle = MiniportAdapterHandle;

        MP_SET_FLAG(Adapter, fMP_INIT_IN_PROGRESS);
        
        //
        // Read Advanced configuration information from the registry
        //
        
        Status = NICReadRegParameters(Adapter, WrapperConfigurationContext);
        if(Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        //
        // Inform NDIS about significant features of the NIC. A 
        // MiniportInitialize function must call NdisMSetAttributesEx 
        // (or NdisMSetAttributes) before calling any other NdisMRegisterXxx 
        // or NdisXxx function that claims hardware resources. If your 
        // hardware supports busmaster DMA, you must specify 
        // NDIS_ATTRIBUTE_BUS_MASTER.
        // If this is NDIS51 miniport, it should use safe APIs. But if this 
        // is NDIS 5.0, NDIS might assume that we are not using safe APIs 
        // and try to map every send buffer MDLs. As a result, let us tell 
        // NDIS, even though we are NDIS 5.0, we use safe buffer APIs by 
        // setting the flag NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS
        //
        NdisMSetAttributesEx(
            MiniportAdapterHandle,
            (NDIS_HANDLE) Adapter,
            0,
#ifdef NDIS50_MINIPORT            
            NDIS_ATTRIBUTE_DESERIALIZE | 
            NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS,
#else
            NDIS_ATTRIBUTE_DESERIALIZE, 
#endif               
            NIC_INTERFACE_TYPE);

        // 
        // Get the Adapter Resources & Initialize the hardware.
        //
        
        Status = NICInitializeAdapter(Adapter, WrapperConfigurationContext);
        if(Status != NDIS_STATUS_SUCCESS) {
            Status = NDIS_STATUS_FAILURE;
            break;
        }

      
        
        
    } while(FALSE);

    if(Status == NDIS_STATUS_SUCCESS) {
        //
        // Attach this Adapter to the global list of adapters managed by
        // this driver.
        //
        NICAttachAdapter(Adapter);
    }
    else {
        if(Adapter){
            MPHalt(Adapter);
        }
    }

    DEBUGP(MP_TRACE, ("<--- MPInitialize Status = 0x%08x%\n", Status));

    return Status;

}



VOID 
MPHalt(
    IN  NDIS_HANDLE MiniportAdapterContext
    )
/*++

Routine Description:

    Halt handler is called when NDIS receives IRP_MN_STOP_DEVICE,
    IRP_MN_SUPRISE_REMOVE or IRP_MN_REMOVE_DEVICE requests from the 
    PNP manager. Here, the driver should free all the resources acquired
    in MiniportInitialize and stop access to the hardware. NDIS will
    not submit any further request once this handler is invoked.

    1) Free and unmap all I/O resources.
    2) Disable interrupt and deregister interrupt handler.
    3) Deregister shutdown handler regsitered by 
        NdisMRegisterAdapterShutdownHandler.
    4) Cancel all queued up timer callbacks.
    5) Finally wait indefinitely for all the outstanding receive 
        packets indicated to the protocol to return. 

    MiniportHalt runs at IRQL = PASSIVE_LEVEL. 


Arguments:

    MiniportAdapterContext	Pointer to the Adapter

Return Value:

    None.

--*/
{
    PMP_ADAPTER       Adapter = (PMP_ADAPTER) MiniportAdapterContext;
    BOOLEAN           bDone=TRUE;
    BOOLEAN           bCancelled;
    LONG              nHaltCount = 0;
                 
    DEBUGP(MP_WARNING, ("---> MPHalt\n"));

    PAGED_CODE();

    MP_SET_FLAG(Adapter, fMP_HALT_IN_PROGRESS);
    
    MP_CLEAR_FLAG(Adapter, fMP_POST_WRITES);
    MP_CLEAR_FLAG(Adapter, fMP_POST_READS);

    NICUnregisterExCallback(Adapter);
    
    //
    // Call Shutdown handler to disable interrupt and turn the hardware off 
    // by issuing a full reset
    //
#if defined(NDIS50_MINIPORT)

    MPShutdown(MiniportAdapterContext);

#elif defined(NDIS51_MINIPORT)

    //
    // On XP and later, NDIS notifies our PNP event handler the 
    // reason for calling Halt. So before accessing the device, check to see
    // if the device is surprise removed, if so don't bother calling
    // the shutdown handler to stop the hardware because it doesn't exist.
    //
    if(!MP_TEST_FLAG(Adapter, fMP_SURPRISE_REMOVED)) {       
        MPShutdown(MiniportAdapterContext);
    } 
    
#endif

    //
    // Free the packets on SendWaitList 
    //
    NICFreeQueuedSendPackets(Adapter);

    NICFreeBusyRecvPackets(Adapter);

    NICFreeBusySendPackets(Adapter);

    NICCancelStatusIndicationIrp(Adapter);
    
#ifdef INTERFACE_WITH_NDISPROT

    if(Adapter->FileHandle) {
        ZwClose(Adapter->FileHandle);
        Adapter->FileHandle = NULL;
    }        

    if (Adapter->FileObject) {
        ObDereferenceObject(Adapter->FileObject);
        Adapter->FileObject = NULL;
    }
#endif

    //
    // Decrement the ref count which was incremented in MPInitialize
    //

    MP_DEC_REF(Adapter);

    //
    // Possible non-zero ref counts mean one or more of the following conditions: 
    // 1) Reset DPC is not finished.
    // 2) Receive Indication DPC is not finished.
    //
    
    DEBUGP(MP_INFO, ("RefCount=%d --- waiting!\n", MP_GET_REF(Adapter)));

    NdisWaitEvent(&Adapter->HaltEvent, 0);
        

    while(TRUE)
    {
        bDone = TRUE;
       
        
        //
        // Are all the packets indicated up returned?

⌨️ 快捷键说明

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