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

📄 ndisbind.c

📁 ndis协议驱动编程
💻 C
📖 第 1 页 / 共 4 页
字号:
/*++

Copyright (c) 2000  Microsoft Corporation

Module Name:

    ndisbind.c

Abstract:

    NDIS protocol entry points and utility routines to handle binding
    and unbinding from adapters.

Environment:

    Kernel mode only.

Revision History:

    arvindm     4/5/2000    Created

--*/


#include "precomp.h"

#define __FILENUMBER 'DNIB'


VOID
NdisuioBindAdapter(
    OUT PNDIS_STATUS                pStatus,
    IN NDIS_HANDLE                  BindContext,
    IN PNDIS_STRING                 pDeviceName,
    IN PVOID                        SystemSpecific1,
    IN PVOID                        SystemSpecific2
    )
/*++

Routine Description:

    Protocol Bind Handler entry point called when NDIS wants us
    to bind to an adapter. We go ahead and set up a binding.
    An OPEN_CONTEXT structure is allocated to keep state about
    this binding.

Arguments:

    pStatus - place to return bind status
    BindContext - handle to use with NdisCompleteBindAdapter
    DeviceName - adapter to bind to
    SystemSpecific1 - used to access protocol-specific registry
                 key for this binding
    SystemSpecific2 - unused

Return Value:

    None

--*/
{
    PNDISUIO_OPEN_CONTEXT           pOpenContext;
    NDIS_STATUS                     Status, ConfigStatus;
    NDIS_HANDLE                     ConfigHandle;

    do
    {
        //
        //  Allocate our context for this open.
        //
        NUIO_ALLOC_MEM(pOpenContext, sizeof(NDISUIO_OPEN_CONTEXT));
        if (pOpenContext == NULL)
        {
            Status = NDIS_STATUS_RESOURCES;
            break;
        }

        //
        //  Initialize it.
        //
        NUIO_ZERO_MEM(pOpenContext, sizeof(NDISUIO_OPEN_CONTEXT));
        NUIO_SET_SIGNATURE(pOpenContext, oc);

        NUIO_INIT_LOCK(&pOpenContext->Lock);
        NUIO_INIT_LIST_HEAD(&pOpenContext->PendedReads);
        NUIO_INIT_LIST_HEAD(&pOpenContext->PendedWrites);
        NUIO_INIT_LIST_HEAD(&pOpenContext->RecvPktQueue);
        NUIO_INIT_EVENT(&pOpenContext->PoweredUpEvent);

        //
        //  Start off by assuming that the device below is powered up.
        //
        NUIO_SIGNAL_EVENT(&pOpenContext->PoweredUpEvent);

        //
        //  Determine the platform we are running on.
        //
        pOpenContext->bRunningOnWin9x = TRUE;

        NdisOpenProtocolConfiguration(
            &ConfigStatus,
            &ConfigHandle,
            (PNDIS_STRING)SystemSpecific1);
        
        if (ConfigStatus == NDIS_STATUS_SUCCESS)
        {
            PNDIS_CONFIGURATION_PARAMETER   pParameter;
            NDIS_STRING                     VersionKey = NDIS_STRING_CONST("Environment");

            NdisReadConfiguration(
                &ConfigStatus,
                &pParameter,
                ConfigHandle,
                &VersionKey,
                NdisParameterInteger);
            
            if ((ConfigStatus == NDIS_STATUS_SUCCESS) &&
                ((pParameter->ParameterType == NdisParameterInteger) ||
                 (pParameter->ParameterType == NdisParameterHexInteger)))
            {
                pOpenContext->bRunningOnWin9x =
                    (pParameter->ParameterData.IntegerData == NdisEnvironmentWindows);
            }

            NdisCloseConfiguration(ConfigHandle);
        }

        NUIO_REF_OPEN(pOpenContext); // Bind

        //
        //  Add it to the global list.
        //
        NUIO_ACQUIRE_LOCK(&Globals.GlobalLock);

        NUIO_INSERT_TAIL_LIST(&Globals.OpenList,
                             &pOpenContext->Link);

        NUIO_RELEASE_LOCK(&Globals.GlobalLock);

        //
        //  Set up the NDIS binding.
        //
        Status = ndisuioCreateBinding(
                     pOpenContext,
                     (PUCHAR)pDeviceName->Buffer,
                     pDeviceName->Length);
        
        if (Status != NDIS_STATUS_SUCCESS)
        {
            break;
        }
    }
    while (FALSE);

    *pStatus = Status;

    return;
}


VOID
NdisuioOpenAdapterComplete(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN NDIS_STATUS                  Status,
    IN NDIS_STATUS                  OpenErrorCode
    )
/*++

Routine Description:

    Completion routine called by NDIS if our call to NdisOpenAdapter
    pends. Wake up the thread that called NdisOpenAdapter.

Arguments:

    ProtocolBindingContext - pointer to open context structure
    Status - status of the open
    OpenErrorCode - if unsuccessful, additional information

Return Value:

    None

--*/
{
    PNDISUIO_OPEN_CONTEXT           pOpenContext;

    pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
    NUIO_STRUCT_ASSERT(pOpenContext, oc);

    pOpenContext->BindStatus = Status;

    NUIO_SIGNAL_EVENT(&pOpenContext->BindEvent);
}


VOID
NdisuioUnbindAdapter(
    OUT PNDIS_STATUS                pStatus,
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN NDIS_HANDLE                  UnbindContext
    )
/*++

Routine Description:

    NDIS calls this when it wants us to close the binding to an adapter.

Arguments:

    pStatus - place to return status of Unbind
    ProtocolBindingContext - pointer to open context structure
    UnbindContext - to use in NdisCompleteUnbindAdapter if we return pending

Return Value:

    None

--*/
{
    PNDISUIO_OPEN_CONTEXT           pOpenContext;

    pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
    NUIO_STRUCT_ASSERT(pOpenContext, oc);

    //
    //  Mark this open as having seen an Unbind.
    //
    NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);

    NUIO_SET_FLAGS(pOpenContext->Flags, NUIOO_UNBIND_FLAGS, NUIOO_UNBIND_RECEIVED);

    //
    //  In case we had threads blocked for the device below to be powered
    //  up, wake them up.
    //
    NUIO_SIGNAL_EVENT(&pOpenContext->PoweredUpEvent);

    NUIO_RELEASE_LOCK(&pOpenContext->Lock);

    ndisuioShutdownBinding(pOpenContext);

    *pStatus = NDIS_STATUS_SUCCESS;
    return;
}


VOID
NdisuioCloseAdapterComplete(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN NDIS_STATUS                  Status
    )
/*++

Routine Description:

    Called by NDIS to complete a pended call to NdisCloseAdapter.
    We wake up the thread waiting for this completion.

Arguments:

    ProtocolBindingContext - pointer to open context structure
    Status - Completion status of NdisCloseAdapter

Return Value:

    None

--*/
{
    PNDISUIO_OPEN_CONTEXT           pOpenContext;

    pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
    NUIO_STRUCT_ASSERT(pOpenContext, oc);

    pOpenContext->BindStatus = Status;

    NUIO_SIGNAL_EVENT(&pOpenContext->BindEvent);
}

    
NDIS_STATUS
NdisuioPnPEventHandler(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN PNET_PNP_EVENT               pNetPnPEvent
    )
/*++

Routine Description:

    Called by NDIS to notify us of a PNP event. The most significant
    one for us is power state change.

Arguments:

    ProtocolBindingContext - pointer to open context structure
                this is NULL for global reconfig events.

    pNetPnPEvent - pointer to the PNP event

Return Value:

    Our processing status for the PNP event.

--*/
{
    PNDISUIO_OPEN_CONTEXT           pOpenContext;
    NDIS_STATUS                     Status;

    pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;

    switch (pNetPnPEvent->NetEvent)
    {
        case NetEventSetPower:
            NUIO_STRUCT_ASSERT(pOpenContext, oc);
            pOpenContext->PowerState = *(PNET_DEVICE_POWER_STATE)pNetPnPEvent->Buffer;

            if (pOpenContext->PowerState > NetDeviceStateD0)
            {
                //
                //  The device below is transitioning to a low power state.
                //  Block any threads attempting to query the device while
                //  in this state.
                //
                NUIO_INIT_EVENT(&pOpenContext->PoweredUpEvent);

                //
                //  Wait for any I/O in progress to complete.
                //
                ndisuioWaitForPendingIO(pOpenContext, FALSE);

                //
                //  Return any receives that we had queued up.
                //
                ndisuioFlushReceiveQueue(pOpenContext);
                DEBUGP(DL_INFO, ("PnPEvent: Open %p, SetPower to %d\n",
                    pOpenContext, pOpenContext->PowerState));
            }
            else
            {
                //
                //  The device below is powered up.
                //
                DEBUGP(DL_INFO, ("PnPEvent: Open %p, SetPower ON: %d\n",
                    pOpenContext, pOpenContext->PowerState));
                NUIO_SIGNAL_EVENT(&pOpenContext->PoweredUpEvent);
            }

            Status = NDIS_STATUS_SUCCESS;
            break;

        case NetEventQueryPower:
            Status = NDIS_STATUS_SUCCESS;
            break;

        case NetEventBindsComplete:
            NUIO_SIGNAL_EVENT(&Globals.BindsComplete);
            Status = NDIS_STATUS_SUCCESS;
            break;

        case NetEventQueryRemoveDevice:
        case NetEventCancelRemoveDevice:
        case NetEventReconfigure:
        case NetEventBindList:
        case NetEventPnPCapabilities:
            Status = NDIS_STATUS_SUCCESS;
            break;

        default:
            Status = NDIS_STATUS_NOT_SUPPORTED;
            break;
    }

    DEBUGP(DL_INFO, ("PnPEvent: Open %p, Event %d, Status %x\n",
            pOpenContext, pNetPnPEvent->NetEvent, Status));

    return (Status);
}
    
VOID
NdisuioProtocolUnloadHandler(
    VOID
    )
/*++

Routine Description:

    NDIS calls this on a usermode request to uninstall us.

Arguments:

    None

Return Value:

    None

--*/
{
    ndisuioDoProtocolUnload();
}

NDIS_STATUS
ndisuioCreateBinding(
    IN PNDISUIO_OPEN_CONTEXT        pOpenContext,
    IN PUCHAR                       pBindingInfo,
    IN ULONG                        BindingInfoLength
    )
/*++

Routine Description:

    Utility function to create an NDIS binding to the indicated device,
    if no such binding exists.

    Here is where we also allocate additional resources (e.g. packet pool)
    for the binding.

    Things to take care of:
    1. Is another thread doing this (or has finished binding) already?
    2. Is the binding being closed at this time?
    3. NDIS calls our Unbind handler while we are doing this.

    These precautions are not needed if this routine is only called from
    the context of our BindAdapter handler, but they are here in case
    we initiate binding from elsewhere (e.g. on processing a user command).

    NOTE: this function blocks and finishes synchronously.

Arguments:

    pOpenContext - pointer to open context block
    pBindingInfo - pointer to unicode device name string
    BindingInfoLength - length in bytes of the above.

Return Value:

    NDIS_STATUS_SUCCESS if a binding was successfully set up.
    NDIS_STATUS_XXX error code on any failure.

--*/
{
    NDIS_STATUS             Status;
    NDIS_STATUS             OpenErrorCode;
    UNICODE_STRING          DeviceName;
    PLIST_ENTRY             pEnt;
    NDIS_MEDIUM             MediumArray[1] = {NdisMedium802_3};
    UINT                    SelectedMediumIndex;
    PNDISUIO_OPEN_CONTEXT   pTmpOpenContext;
    BOOLEAN                 fDoNotDisturb = FALSE;
    BOOLEAN                 fOpenComplete = FALSE;
    ULONG                   BytesProcessed;
    ULONG                   GenericUlong = 0;

    DEBUGP(DL_LOUD, ("CreateBinding: open %p/%x, device [%ws]\n",
                pOpenContext, pOpenContext->Flags, pBindingInfo));

    Status = NDIS_STATUS_SUCCESS;

    do
    {
        //

⌨️ 快捷键说明

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