天天看点

对PassThru中的Protocol.c的注释

#include "precomp.h"

#pragma hdrstop

#define MAX_PACKET_POOL_SIZE 0x0000FFFF//最大64K

#define MIN_PACKET_POOL_SIZE 0x000000FF//最小256字节

//------------------------------------------------------------------------

VOID

PtBindAdapter(

              OUT PNDIS_STATUS Status,

              IN NDIS_HANDLE BindContext,

              IN PNDIS_STRING DeviceName,

              IN PVOID SystemSpecific1,

              IN PVOID SystemSpecific2

              )

{

    NDIS_HANDLE ConfigHandle = NULL;

    PNDIS_CONFIGURATION_PARAMETER Param;

    NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings");

    PADAPT pAdapt = NULL;

    NDIS_STATUS Sts;

    UINT MediumIndex;

    PNDIS_CONFIGURATION_PARAMETER BundleParam;

    NDIS_STRING BundleStr = NDIS_STRING_CONST("BundleId");

    NDIS_STATUS BundleStatus;

    DBGPRINT("==> Passthru Protocol Initialize/n");

    do

    {

        // Start off by opening the config section and reading our instance which we want

        // to export for this binding

        //获取中间层驱动程序存储与适配器相关信息的注册表键句柄

        NdisOpenProtocolConfiguration(Status,

            &ConfigHandle,//获得句柄

            SystemSpecific1);

        if (*Status != NDIS_STATUS_SUCCESS)

        {

            break;

        }

        //读取获得的句柄下的信息

        NdisReadConfiguration(Status,

            &Param,

            ConfigHandle,

            &DeviceStr,

            NdisParameterString);

        if (*Status != NDIS_STATUS_SUCCESS)

        {

            break;

        }

        //为Adapter structure分配内存,

        //当微端口初始化后它表现为协议相关(protocol-context)和adapter structure两个方面。

        NdisAllocateMemoryWithTag(&pAdapt, sizeof(ADAPT), TAG);

        if (pAdapt == NULL)

        {

            *Status = NDIS_STATUS_RESOURCES;

            break;

        }

        //零初始化ADAPT结构

        NdisZeroMemory(pAdapt, sizeof(ADAPT));

        //利用注册来存储字符串,将被用于从注册处读取数据

        NdisAllocateMemoryWithTag( &(pAdapt->BundleUniString.Buffer), MAX_BUNDLEID_LENGTH ,TAG);

        if (pAdapt->BundleUniString.Buffer == NULL)

        {

            *Status = NDIS_STATUS_RESOURCES;

            break;

        }

        pAdapt->BundleUniString.MaximumLength = MAX_BUNDLEID_LENGTH ;

        //读取键值信息

        NdisReadConfiguration(&BundleStatus,

            &BundleParam,

            ConfigHandle,

            &BundleStr,

            NdisParameterString);

        if (BundleStatus == NDIS_STATUS_SUCCESS)

        {

            //拷贝包描述符到自己的内存

            ASSERT(pAdapt->BundleUniString.MaximumLength >= BundleParam->ParameterData.StringData.Length);

            pAdapt->BundleUniString.Length = BundleParam->ParameterData.StringData.Length;

            RtlCopyUnicodeString(&pAdapt->BundleUniString, &BundleParam->ParameterData.StringData);

        }

        else

        { // We do not have a bundle id entry in the registry. To play safe we will enter

            // make the escape sequence the Bundle Id, This ensures that no bundle id's are

            // spuriously formed

            //我们没有一个包标志进入注册,为了显示安全,我们将包标志倒序,这确保了没有包标志被伪造

            NDIS_STRING NoBundle = NDIS_STRING_CONST ("<no-bundle>");

            RtlCopyUnicodeString(&pAdapt->BundleUniString, &NoBundle);

        }

        //初始化事件和自旋锁

        NdisInitializeEvent(&pAdapt->Event);

        KeInitializeSpinLock(&pAdapt->SpinLock);

        // Allocate a packet pool for sends. We need this to pass sends down. We cannot use the same

        // packet descriptor that came down to our send handler

        //为发送分配数据包池。

        //我们需要这个来向下传递发送数据。我们不能使用到达我们的发送函数的同样的包描述符。

        NdisAllocatePacketPoolEx(Status,

            &pAdapt->SendPacketPoolHandle,

            MIN_PACKET_POOL_SIZE,

            MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,

            sizeof(RSVD));

        if (*Status != NDIS_STATUS_SUCCESS)

        {

            break;

        }

        //为接收开辟数据包池,我们需要这样指示接收

        NdisAllocatePacketPoolEx(Status,

            &pAdapt->RecvPacketPoolHandle,

            MIN_PACKET_POOL_SIZE,

            MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,

            sizeof(RSVD));

        if (*Status != NDIS_STATUS_SUCCESS)

        {

            break;

        }

        //调用NdisOpenAdapter进行绑定

        NdisOpenAdapter(Status,

            &Sts,

            &pAdapt->BindingHandle,

            &MediumIndex,

            MediumArray,

            sizeof(MediumArray)/sizeof(NDIS_MEDIUM),

            ProtHandle,

            pAdapt,

            DeviceName,

            0,

            NULL);

        if(*Status == NDIS_STATUS_PENDING)

        {

            NdisWaitEvent(&pAdapt->Event, 0);

            *Status = pAdapt->Status;

        }

        if(*Status != NDIS_STATUS_SUCCESS)

        {

            break;

        }

        pAdapt->Medium = MediumArray[MediumIndex];

        //微端口初始化(可初始化多个)

        NdisIMInitializeDeviceInstanceEx(DriverHandle,

            &Param->ParameterData.StringData,

            pAdapt);

    } while(FALSE);

    if (ConfigHandle != NULL)

    { //关闭表键

        NdisCloseConfiguration(ConfigHandle);

    }

    //如果分配资源失败,则释放分配的资源

    if (*Status != NDIS_STATUS_SUCCESS)

    {

        if (pAdapt != NULL)

        {

            if (pAdapt->SendPacketPoolHandle != NULL)

            {

                NdisFreePacketPool(pAdapt->SendPacketPoolHandle);

            }

            if (pAdapt->RecvPacketPoolHandle != NULL)

            {

                NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);

            }

            NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);

        }

    }

    DBGPRINT("<== Passthru Protocol Initialize/n");

}

//----------------------------------------------------------------------

VOID

PtOpenAdapterComplete(

                      IN NDIS_HANDLE ProtocolBindingContext,

                      IN NDIS_STATUS Status,

                      IN NDIS_STATUS OpenErrorStatus

                      )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    DBGPRINT("==> Passthru PtOpenAdapterComplete/n");

    pAdapt->Status = Status;

    NdisSetEvent(&pAdapt->Event);

}

//------------------------------------------------------------------------------

VOID

PtUnbindAdapter(

                OUT PNDIS_STATUS Status,

                IN NDIS_HANDLE ProtocolBindingContext,

                IN NDIS_HANDLE UnbindContext

                )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    NDIS_HANDLE BindingHandle = pAdapt->BindingHandle;

    DBGPRINT("==> Passthru PtUnbindAdapter/n");

    if (pAdapt->QueuedRequest == TRUE)

    {

        pAdapt->QueuedRequest = FALSE;

        PtRequestComplete (pAdapt,

            &pAdapt->Request,

            NDIS_STATUS_FAILURE );

    }

    //调用NDIS卸载驱动设备实例,我们在HaltHandler中实现大部分功能。

    //如果passthru的小端口的Halt Handler被调用,或IM设备从未被初始化,这个句柄将为空。

    if(pAdapt->MiniportHandle != NULL)

    {

        *Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle);

        if(*Status != NDIS_STATUS_SUCCESS)

        {

            *Status = NDIS_STATUS_FAILURE;

        }

    }

    else

    {

        // We need to do some work here.

        //关闭对下层绑定并且释放分配的内存

        if(pAdapt->BindingHandle != NULL)

        {

            NdisResetEvent(&pAdapt->Event);

            NdisCloseAdapter(Status, pAdapt->BindingHandle);

            //等待关闭完成

            if(*Status == NDIS_STATUS_PENDING)

            {

                NdisWaitEvent(&pAdapt->Event, 0);

                *Status = pAdapt->Status;

            }

        }

        else

        {

            //MiniportHandle和Binding Handle均不能为空

            *Status = NDIS_STATUS_FAILURE;

            ASSERT(0);

        }

        //此处释放早期调用HaltHandler时未能释放的内存

        NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);

    }

    DBGPRINT("<==Passthru UnbindAdapter/n");

}

//----------------------------------------------------------------------------

VOID

PtUnload(

         IN PDRIVER_OBJECT DriverObject

         )

{

    NDIS_STATUS Status;

    //释放注册时分配的空间

    NdisDeregisterProtocol(&Status, ProtHandle);

}

//----------------------------------------------------------------------------

VOID

PtCloseAdapterComplete(

    IN NDIS_HANDLE ProtocolBindingContext,

    IN NDIS_STATUS Status

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    pAdapt->Status = Status;

    NdisSetEvent(&pAdapt->Event);

}

VOID

PtResetComplete(

    IN NDIS_HANDLE ProtocolBindingContext,

    IN NDIS_STATUS Status

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    //我们这个程序不产生复位,所以不到达这里

    ASSERT(0);

}

VOID

PtRequestComplete(

    IN NDIS_HANDLE ProtocolBindingContext,

    IN PNDIS_REQUEST NdisRequest,

    IN NDIS_STATUS Status

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    NDIS_OID Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;

    //

    // Change to the pAdapt for which the request originated

    //转换到最初请求的pAdapt

    if(MPIsSendOID(Oid))

    {

        pAdapt = pAdapt->pPrimaryAdapt;

        //如果没有捆绑则指向它自己(参看初始化)

    }

    // Since our request is not outstanding anymore

    //以后我们的请求不再突出(传递)

    pAdapt->OutstandingRequests = FALSE;

    //

    // Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.

    //完成Set或者Query,如果需要则填充OID_PNP_CAPABILITIES的缓冲区

    switch(NdisRequest->RequestType)

    {

    case NdisRequestQueryInformation:

        //这将不会被传递到下面的微端口

        ASSERT(Oid != OID_PNP_QUERY_POWER);

        // 如果oid == OID_PNP_CAPABILITIES并且查询成功,则用请求的值填充缓冲区。

        if(Oid == OID_PNP_CAPABILITIES && Status == NDIS_STATUS_SUCCESS)

        {

            MPQueryPNPCapbilities(pAdapt,&Status);

        }

        *pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;

        *pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;

        NdisMQueryInformationComplete(pAdapt->MiniportHandle,

            Status);

        break;

    case NdisRequestSetInformation:

        ASSERT( Oid != OID_PNP_SET_POWER);

        *pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;

        *pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;

        NdisMSetInformationComplete(pAdapt->MiniportHandle,

            Status);

        break;

    default:

        ASSERT(0);

        break;

    }

}

//--------------------------------------------------------------------------------

VOID

PtStatus(

    IN NDIS_HANDLE ProtocolBindingContext,

    IN NDIS_STATUS GeneralStatus,

    IN PVOID StatusBuffer,

    IN UINT StatusBufferSize

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    //如果我们在微端口被初始化前得到一个状态指示,忽略它

    //如果SampleIM没有打开,我们不传递状态指示

    if(pAdapt->MiniportHandle != NULL &&

        pAdapt->MPDeviceState == NdisDeviceStateD0 &&

        pAdapt->PTDeviceState == NdisDeviceStateD0 )

    {

        NdisMIndicateStatus(pAdapt->MiniportHandle,

            GeneralStatus,

            StatusBuffer,

            StatusBufferSize);

    }

}

//----------------------------------------------------------------------------------

VOID

PtStatusComplete(

    IN NDIS_HANDLE ProtocolBindingContext

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    //如果我们在微端口被初始化前得到一个状态指示,忽略。

    if(pAdapt->MiniportHandle != NULL &&

        pAdapt->MPDeviceState == NdisDeviceStateD0 &&

        pAdapt->PTDeviceState == NdisDeviceStateD0 )

    {

        NdisMIndicateStatusComplete(pAdapt->MiniportHandle);

    }

}

VOID

PtSendComplete(

    IN NDIS_HANDLE ProtocolBindingContext,

    IN PNDIS_PACKET Packet,

    IN NDIS_STATUS Status

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    PNDIS_PACKET Pkt;

    PRSVD Rsvd;

    //

    // Returning the Send on the Primary, will point to itself if there is no bundle

    //返回在主程序中的发送,如果没有绑定则指向它自己

    pAdapt = pAdapt->pPrimaryAdapt;

    Rsvd =(PRSVD)(Packet->ProtocolReserved);

    Pkt = Rsvd->OriginalPkt;

    NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);

    NdisDprFreePacket(Packet);

    NdisMSendComplete(pAdapt->MiniportHandle,

        Pkt,

        Status);

}

VOID

PtTransferDataComplete(

    IN NDIS_HANDLE ProtocolBindingContext,

    IN PNDIS_PACKET Packet,

    IN NDIS_STATUS Status,

    IN UINT BytesTransferred

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    // Returning the Send on the Primary, will point to itself if there is no LBFO

    //返回在主程序中的发送,如果没有LBFO将指向它自己。

    pAdapt = pAdapt->pPrimaryAdapt;

    if(pAdapt->MiniportHandle)

    {

        NdisMTransferDataComplete(pAdapt->MiniportHandle,

            Packet,

            Status,

            BytesTransferred);

    }

}

//---------------------------------------------------------------------------------

NDIS_STATUS

PtReceive(

    IN NDIS_HANDLE ProtocolBindingContext,

    IN NDIS_HANDLE MacReceiveContext,

    IN PVOID HeaderBuffer,

    IN UINT HeaderBufferSize,

    IN PVOID LookAheadBuffer,

    IN UINT LookAheadBufferSize,

    IN UINT PacketSize

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    PNDIS_PACKET MyPacket, Packet;

    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;

    if(!pAdapt->MiniportHandle)

    {

        Status = NDIS_STATUS_FAILURE;

    }

    else do

    {

        //

        // We should not be getting Receives on a Secondary, this is just specific to our LBFO driver

        //

        if(pAdapt->isSecondary)

        {

            DBGPRINT("PASSTHRU GETTING RECIEVES ON SECONDARY/n");

            ASSERT(0);

        }

        //

        // If this was indicated by the miniport below as a packet, then get that packet pointer and indicate

        // it as a packet as well(with appropriate status). This way the OOB stuff is accessible to the

        // transport above us.

        //

        Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);

        if(Packet != NULL)

        {

            //

            // Get a packet off the pool and indicate that up

            //

            NdisDprAllocatePacket(&Status,

                &MyPacket,

                pAdapt->RecvPacketPoolHandle);

            if(Status == NDIS_STATUS_SUCCESS)

            {

                MyPacket->Private.Head = Packet->Private.Head;

                MyPacket->Private.Tail = Packet->Private.Tail;

                //

                // Get the original packet(it could be the same packet as one received or a different one

                // based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible

                // correctly at the top.

                //

                NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));

                NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);

                //

                // Set Packet Flags

                //

                NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

                //

                // Make sure the status is set to NDIS_STATUS_RESOURCES.

                //

                NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);

                NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);

                ASSERT(NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);

                NdisDprFreePacket(MyPacket);

                break;

            }

        }

        //

        // Fall through if the miniport below us has either not indicated a packet or we could not

        // allocate one

        //

        pAdapt->IndicateRcvComplete = TRUE;

        switch(pAdapt->Medium)

        {

        case NdisMedium802_3:

            NdisMEthIndicateReceive(pAdapt->MiniportHandle,

                MacReceiveContext,

                HeaderBuffer,

                HeaderBufferSize,

                LookAheadBuffer,

                LookAheadBufferSize,

                PacketSize);

            break;

        case NdisMedium802_5:

            NdisMTrIndicateReceive(pAdapt->MiniportHandle,

                MacReceiveContext,

                HeaderBuffer,

                HeaderBufferSize,

                LookAheadBuffer,

                LookAheadBufferSize,

                PacketSize);

            break;

        case NdisMediumFddi:

            NdisMFddiIndicateReceive(pAdapt->MiniportHandle,

                MacReceiveContext,

                HeaderBuffer,

                HeaderBufferSize,

                LookAheadBuffer,

                LookAheadBufferSize,

                PacketSize);

            break;

        default:

            ASSERT(0);

            break;

        }

    } while(FALSE);

    return Status;

}

//----------------------------------------------------------------------------

VOID

PtReceiveComplete(

    IN NDIS_HANDLE ProtocolBindingContext

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    //

    // We should not be getting Receives on a Secondary, this is just specific to our LBFO driver

    //

    if(pAdapt->isSecondary)

    {

        DBGPRINT("PASSTHRU GETTING RECEIVES ON SECONDARY/n");

        ASSERT(0);

    }

    if((pAdapt->MiniportHandle != NULL) && pAdapt->IndicateRcvComplete)

    {

        switch(pAdapt->Medium)

        {

        case NdisMedium802_3:

            NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);

            break;

        case NdisMedium802_5:

            NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);

            break;

        case NdisMediumFddi:

            NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);

            break;

        default:

            ASSERT(0);

            break;

        }

    }

    pAdapt->IndicateRcvComplete = FALSE;

}

//-------------------------------------------------------------------------------------

INT

PtReceivePacket(

    IN NDIS_HANDLE ProtocolBindingContext,

    IN PNDIS_PACKET Packet       

    )

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    NDIS_STATUS Status;

    PNDIS_PACKET MyPacket;

    PRSVD Resvd;

    if(!pAdapt->MiniportHandle)

    {

        return 0;

    }

    //

    // We should not be getting Receives on a Secondary, this is just specific to our LBFO driver

    //

    if(pAdapt->isSecondary)

    {

        DBGPRINT("PASSTHRU GETTING RECEIVES ON SECONDARY/n");

        ASSERT(0);

    }

    //

    // Get a packet off the pool and indicate that up

    //

    NdisDprAllocatePacket(&Status,

        &MyPacket,

        pAdapt->RecvPacketPoolHandle);

    if(Status == NDIS_STATUS_SUCCESS)

    {

        Resvd =(PRSVD)(MyPacket->MiniportReserved);

        Resvd->OriginalPkt = Packet;

        MyPacket->Private.Head = Packet->Private.Head;

        MyPacket->Private.Tail = Packet->Private.Tail;

        //

        // Get the original packet(it could be the same packet as one received or a different one

        // based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible

        // correctly at the top.

        //

        NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));

        //

        // Set Packet Flags

        //

        NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

        Status = NDIS_GET_PACKET_STATUS(Packet);

        NDIS_SET_PACKET_STATUS(MyPacket, Status);

        NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));

        NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);

        if(Status == NDIS_STATUS_RESOURCES)

        {

            NdisDprFreePacket(MyPacket);

        }

        return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);

    }

    else

    {

        //

        // We are out of packets. Silently drop it. Alternatively we can deal with it:

        // - By keeping separate send and receive pools

        // - Dynamically allocate more pools as needed and free them when not needed

        //

        return(0);

    }

}

//--------------------------------------------------------------------------------------

NDIS_STATUS

PtPNPHandler(

    IN NDIS_HANDLE ProtocolBindingContext,

    IN PNET_PNP_EVENT pNetPnPEvent

    )   

{

    PADAPT pAdapt =(PADAPT)ProtocolBindingContext;

    NDIS_STATUS Status = NDIS_STATUS_SUCCESS;

    DBGPRINT ("PtPnPHandler");

    //

    // This will happen when all entities in the system need to be notified

    //

    switch(pNetPnPEvent->NetEvent)

    {

    case NetEventSetPower :

        Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);

        break;

    case NetEventReconfigure :

        Status = PtPnPNetEventReconfigure(pAdapt, (PCWSTR)pNetPnPEvent->Buffer);

        break;

    default :

        Status = NDIS_STATUS_SUCCESS;

        break;

    }

    return Status;

}

//----------------------------------------------------------------------------------

NDIS_STATUS

PtPnPNetEventReconfigure(

    IN PADAPT pAdapt,

    IN PCWSTR pBundleString

    )

{

    NDIS_STATUS BundleStatus = NDIS_STATUS_SUCCESS;

    NDIS_STRING NewBundleUniString;

    if(pAdapt == NULL)

    {

        NdisReEnumerateProtocolBindings (ProtHandle);

        return BundleStatus;

    }

    if (pBundleString == NULL)

    {

        return BundleStatus;

    }

    NdisInitUnicodeString( &NewBundleUniString, pBundleString);

    do

    {

        //

        // If the bundle Identifier was not changed, do not do anything

        //

        if(NdisEqualUnicodeString(&NewBundleUniString, &pAdapt->BundleUniString, TRUE))

        {

            break;

        }

        //

        // We have a new bundle id , copy it and do the necessary bundling work

        //

        RtlCopyUnicodeString(&pAdapt->BundleUniString , &NewBundleUniString);

        //

        // If we are part of a bundle and our bundle id was changed, either the primary or the secondary

        // will get promoted

        // If we are the secondary of a bundle promote ourselves

        //

        if(pAdapt->isSecondary)

        {

            PADAPT pPrimaryAdapt = pAdapt->pPrimaryAdapt;

            BundleStatus = MPPromoteSecondary(pAdapt);

            if(BundleStatus != NDIS_STATUS_SUCCESS)

            {

                ASSERT(0);

                break;

            }

            //

            // resetting all the internal variables of the primary Adapter structure

            //

            pPrimaryAdapt->pPrimaryAdapt = pPrimaryAdapt;

            pPrimaryAdapt->pSecondaryAdapt = pPrimaryAdapt;

            pPrimaryAdapt->isSecondary = FALSE;

        }

        else

        {

            if(pAdapt->pSecondaryAdapt != pAdapt)

            {

                BundleStatus = MPPromoteSecondary(pAdapt->pSecondaryAdapt);

                if(BundleStatus != NDIS_STATUS_SUCCESS)

                {

                    ASSERT(0);

                    break;

                }

                //

                // resetting all our internal variables

                //

                pAdapt->pSecondaryAdapt = pAdapt;

                pAdapt->pPrimaryAdapt = pAdapt;

                pAdapt->isSecondary = FALSE ;

            }

        }

        BundleStatus = MPBundleSearchAndSetSecondary(pAdapt);

    } while(FALSE) ;

    DBGPRINT("<==PtPNPNetEventReconfigure/n");

    return BundleStatus;

}

//--------------------------------------------------------------------------------------

NDIS_STATUS

PtPnPNetEventSetPower(

    IN PADAPT pAdapt,

    IN PNET_PNP_EVENT pNetPnPEvent

    )

{

    PNDIS_DEVICE_POWER_STATE pDeviceState =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);

    NDIS_DEVICE_POWER_STATE PrevDeviceState = pAdapt->PTDeviceState;

    NDIS_STATUS Status ;

    //设置内部设备状态,这个支撑所有新的发送或接收。

    pAdapt->PTDeviceState = *pDeviceState;

    //如果正在被送到standby(if we are being sent to standby),阻塞正在处理的请求和发送

    if(*pDeviceState > NdisDeviceStateD0)

    {

        //如果物理微端口将要备用(standby),所有到来的请求无效。

        if (PrevDeviceState == NdisDeviceStateD0)

        {

            pAdapt->StandingBy = TRUE;

        }

        while(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) != 0)

        {

            //等待到正在处理的发送完成。

            NdisMSleep(10);

        }

        while(pAdapt->OutstandingRequests == TRUE)

        {

            //等待到正在处理的请求完成。

            NdisMSleep(10);

        }

        ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);

        ASSERT(pAdapt->OutstandingRequests == FALSE);

    }

    else

    {

        //协议被打开,一个待处理请求必须结束

        if (pAdapt->QueuedRequest == TRUE)

        {

            pAdapt->QueuedRequest = FALSE;

            NdisRequest(&Status,

                pAdapt->BindingHandle,

                &pAdapt->Request);

            //下面的微端口同步地完成同步请求,IM需要完成它早期未决的请求。

            if (Status != NDIS_STATUS_PENDING)

            {

                PtRequestComplete(pAdapt,

                    &pAdapt->Request,

                    Status);

            }

        }

        //如果物理微端口功率正在增大(is powering up)(从低功率到D0),清空标志

        if (PrevDeviceState > NdisDeviceStateD0)

        {

            pAdapt->StandingBy = FALSE;

        }

    }

    Status = NDIS_STATUS_SUCCESS;

    return Status;

}