Sync with the new ipfw3 version.
[ipfw.git] / original_passthru / miniport.c
diff --git a/original_passthru/miniport.c b/original_passthru/miniport.c
new file mode 100644 (file)
index 0000000..a7f3bbc
--- /dev/null
@@ -0,0 +1,1461 @@
+/*++\r
+\r
+Copyright (c) 1992-2000  Microsoft Corporation\r
+\r
+Module Name:\r
+\r
+    miniport.c\r
+\r
+Abstract:\r
+\r
+    Ndis Intermediate Miniport driver sample. This is a passthru driver.\r
+\r
+Author:\r
+\r
+Environment:\r
+\r
+\r
+Revision History:\r
+\r
+\r
+--*/\r
+\r
+#include "precomp.h"\r
+#pragma hdrstop\r
+\r
+\r
+\r
+NDIS_STATUS\r
+MPInitialize(\r
+    OUT PNDIS_STATUS             OpenErrorStatus,\r
+    OUT PUINT                    SelectedMediumIndex,\r
+    IN  PNDIS_MEDIUM             MediumArray,\r
+    IN  UINT                     MediumArraySize,\r
+    IN  NDIS_HANDLE              MiniportAdapterHandle,\r
+    IN  NDIS_HANDLE              WrapperConfigurationContext\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This is the initialize handler which gets called as a result of\r
+    the BindAdapter handler calling NdisIMInitializeDeviceInstanceEx.\r
+    The context parameter which we pass there is the adapter structure\r
+    which we retrieve here.\r
+\r
+    Arguments:\r
+\r
+    OpenErrorStatus            Not used by us.\r
+    SelectedMediumIndex        Place-holder for what media we are using\r
+    MediumArray                Array of ndis media passed down to us to pick from\r
+    MediumArraySize            Size of the array\r
+    MiniportAdapterHandle    The handle NDIS uses to refer to us\r
+    WrapperConfigurationContext    For use by NdisOpenConfiguration\r
+\r
+Return Value:\r
+\r
+    NDIS_STATUS_SUCCESS unless something goes wrong\r
+\r
+--*/\r
+{\r
+    UINT            i;\r
+    PADAPT          pAdapt;\r
+    NDIS_STATUS     Status = NDIS_STATUS_FAILURE;\r
+    NDIS_MEDIUM     Medium;\r
+\r
+    UNREFERENCED_PARAMETER(WrapperConfigurationContext);\r
+    \r
+    do\r
+    {\r
+        //\r
+        // Start off by retrieving our adapter context and storing\r
+        // the Miniport handle in it.\r
+        //\r
+        pAdapt = NdisIMGetDeviceContext(MiniportAdapterHandle);\r
+        pAdapt->MiniportIsHalted = FALSE;\r
+\r
+        DBGPRINT(("==> Miniport Initialize: Adapt %p\n", pAdapt));\r
+\r
+        //\r
+        // Usually we export the medium type of the adapter below as our\r
+        // virtual miniport's medium type. However if the adapter below us\r
+        // is a WAN device, then we claim to be of medium type 802.3.\r
+        //\r
+        Medium = pAdapt->Medium;\r
+\r
+        if (Medium == NdisMediumWan)\r
+        {\r
+            Medium = NdisMedium802_3;\r
+        }\r
+\r
+        for (i = 0; i < MediumArraySize; i++)\r
+        {\r
+            if (MediumArray[i] == Medium)\r
+            {\r
+                *SelectedMediumIndex = i;\r
+                break;\r
+            }\r
+        }\r
+\r
+        if (i == MediumArraySize)\r
+        {\r
+            Status = NDIS_STATUS_UNSUPPORTED_MEDIA;\r
+            break;\r
+        }\r
+\r
+\r
+        //\r
+        // Set the attributes now. NDIS_ATTRIBUTE_DESERIALIZE enables us\r
+        // to make up-calls to NDIS without having to call NdisIMSwitchToMiniport\r
+        // or NdisIMQueueCallBack. This also forces us to protect our data using\r
+        // spinlocks where appropriate. Also in this case NDIS does not queue\r
+        // packets on our behalf. Since this is a very simple pass-thru\r
+        // miniport, we do not have a need to protect anything. However in\r
+        // a general case there will be a need to use per-adapter spin-locks\r
+        // for the packet queues at the very least.\r
+        //\r
+        NdisMSetAttributesEx(MiniportAdapterHandle,\r
+                             pAdapt,\r
+                             0,                                        // CheckForHangTimeInSeconds\r
+                             NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT    |\r
+                                NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT|\r
+                                NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |\r
+                                NDIS_ATTRIBUTE_DESERIALIZE |\r
+                                NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,\r
+                             0);\r
+\r
+        pAdapt->MiniportHandle = MiniportAdapterHandle;\r
+        //\r
+        // Initialize LastIndicatedStatus to be NDIS_STATUS_MEDIA_CONNECT\r
+        //\r
+        pAdapt->LastIndicatedStatus = NDIS_STATUS_MEDIA_CONNECT;\r
+        \r
+        //\r
+        // Initialize the power states for both the lower binding (PTDeviceState)\r
+        // and our miniport edge to Powered On.\r
+        //\r
+        pAdapt->MPDeviceState = NdisDeviceStateD0;\r
+        pAdapt->PTDeviceState = NdisDeviceStateD0;\r
+\r
+        //\r
+        // Add this adapter to the global pAdapt List\r
+        //\r
+        NdisAcquireSpinLock(&GlobalLock);\r
+\r
+        pAdapt->Next = pAdaptList;\r
+        pAdaptList = pAdapt;\r
+\r
+        NdisReleaseSpinLock(&GlobalLock);\r
+        \r
+        //\r
+        // Create an ioctl interface\r
+        //\r
+        (VOID)PtRegisterDevice();\r
+\r
+        Status = NDIS_STATUS_SUCCESS;\r
+    }\r
+    while (FALSE);\r
+\r
+    //\r
+    // If we had received an UnbindAdapter notification on the underlying\r
+    // adapter, we would have blocked that thread waiting for the IM Init\r
+    // process to complete. Wake up any such thread.\r
+    //\r
+    ASSERT(pAdapt->MiniportInitPending == TRUE);\r
+    pAdapt->MiniportInitPending = FALSE;\r
+    NdisSetEvent(&pAdapt->MiniportInitEvent);\r
+\r
+    if (Status == NDIS_STATUS_SUCCESS)\r
+    {\r
+        PtReferenceAdapt(pAdapt);\r
+    }\r
+\r
+    DBGPRINT(("<== Miniport Initialize: Adapt %p, Status %x\n", pAdapt, Status));\r
+\r
+    *OpenErrorStatus = Status;\r
+\r
+    \r
+    return Status;\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+MPSend(\r
+    IN NDIS_HANDLE             MiniportAdapterContext,\r
+    IN PNDIS_PACKET            Packet,\r
+    IN UINT                    Flags\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Send Packet handler. Either this or our SendPackets (array) handler is called\r
+    based on which one is enabled in our Miniport Characteristics.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext    Pointer to the adapter\r
+    Packet                    Packet to send\r
+    Flags                     Unused, passed down below\r
+\r
+Return Value:\r
+\r
+    Return code from NdisSend\r
+\r
+--*/\r
+{\r
+    PADAPT              pAdapt = (PADAPT)MiniportAdapterContext;\r
+    NDIS_STATUS         Status;\r
+    PNDIS_PACKET        MyPacket;\r
+    PVOID               MediaSpecificInfo = NULL;\r
+    ULONG               MediaSpecificInfoSize = 0;\r
+\r
+    //\r
+    // The driver should fail the send if the virtual miniport is in low \r
+    // power state\r
+    //\r
+    if (pAdapt->MPDeviceState > NdisDeviceStateD0)\r
+    {\r
+         return NDIS_STATUS_FAILURE;\r
+    }\r
+\r
+#ifdef NDIS51\r
+    //\r
+    // Use NDIS 5.1 packet stacking:\r
+    //\r
+    {\r
+        PNDIS_PACKET_STACK        pStack;\r
+        BOOLEAN                   Remaining;\r
+\r
+        //\r
+        // Packet stacks: Check if we can use the same packet for sending down.\r
+        //\r
+\r
+        pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);\r
+        if (Remaining)\r
+        {\r
+            //\r
+            // We can reuse "Packet".\r
+            //\r
+            // NOTE: if we needed to keep per-packet information in packets\r
+            // sent down, we can use pStack->IMReserved[].\r
+            //\r
+            ASSERT(pStack);\r
+            //\r
+            // If the below miniport is going to low power state, stop sending down any packet.\r
+            //\r
+            NdisAcquireSpinLock(&pAdapt->Lock);\r
+            if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+            {\r
+                NdisReleaseSpinLock(&pAdapt->Lock);\r
+                return NDIS_STATUS_FAILURE;\r
+            }\r
+            pAdapt->OutstandingSends++;\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            NdisSend(&Status,\r
+                     pAdapt->BindingHandle,\r
+                     Packet);\r
+\r
+            if (Status != NDIS_STATUS_PENDING)\r
+            {\r
+                ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+            }\r
+\r
+            return(Status);\r
+        }\r
+    }\r
+#endif // NDIS51\r
+\r
+    //\r
+    // We are either not using packet stacks, or there isn't stack space\r
+    // in the original packet passed down to us. Allocate a new packet\r
+    // to wrap the data with.\r
+    //\r
+    //\r
+    // If the below miniport is going to low power state, stop sending down any packet.\r
+    //\r
+    NdisAcquireSpinLock(&pAdapt->Lock);\r
+    if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+    {\r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+        return NDIS_STATUS_FAILURE;\r
+    \r
+    }\r
+    pAdapt->OutstandingSends++;\r
+    NdisReleaseSpinLock(&pAdapt->Lock);\r
+    \r
+    NdisAllocatePacket(&Status,\r
+                       &MyPacket,\r
+                       pAdapt->SendPacketPoolHandle);\r
+\r
+    if (Status == NDIS_STATUS_SUCCESS)\r
+    {\r
+        PSEND_RSVD            SendRsvd;\r
+\r
+        //\r
+        // Save a pointer to the original packet in our reserved\r
+        // area in the new packet. This is needed so that we can\r
+        // get back to the original packet when the new packet's send\r
+        // is completed.\r
+        //\r
+        SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);\r
+        SendRsvd->OriginalPkt = Packet;\r
+\r
+        NdisGetPacketFlags(MyPacket) = Flags;\r
+\r
+        //\r
+        // Set up the new packet so that it describes the same\r
+        // data as the original packet.\r
+        //\r
+        NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);\r
+        NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);\r
+#ifdef WIN9X\r
+        //\r
+        // Work around the fact that NDIS does not initialize this\r
+        // to FALSE on Win9x.\r
+        //\r
+        NDIS_PACKET_VALID_COUNTS(MyPacket) = FALSE;\r
+#endif\r
+\r
+        //\r
+        // Copy the OOB Offset from the original packet to the new\r
+        // packet.\r
+        //\r
+        NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),\r
+                       NDIS_OOB_DATA_FROM_PACKET(Packet),\r
+                       sizeof(NDIS_PACKET_OOB_DATA));\r
+\r
+#ifndef WIN9X\r
+        //\r
+        // Copy the right parts of per packet info into the new packet.\r
+        // This API is not available on Win9x since task offload is\r
+        // not supported on that platform.\r
+        //\r
+        NdisIMCopySendPerPacketInfo(MyPacket, Packet);\r
+#endif\r
+        \r
+        //\r
+        // Copy the Media specific information\r
+        //\r
+        NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,\r
+                                            &MediaSpecificInfo,\r
+                                            &MediaSpecificInfoSize);\r
+\r
+        if (MediaSpecificInfo || MediaSpecificInfoSize)\r
+        {\r
+            NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,\r
+                                                MediaSpecificInfo,\r
+                                                MediaSpecificInfoSize);\r
+        }\r
+\r
+        NdisSend(&Status,\r
+                 pAdapt->BindingHandle,\r
+                 MyPacket);\r
+\r
+\r
+        if (Status != NDIS_STATUS_PENDING)\r
+        {\r
+#ifndef WIN9X\r
+            NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);\r
+#endif\r
+            NdisFreePacket(MyPacket);\r
+            ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+        }\r
+    }\r
+    else\r
+    {\r
+        ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+        //\r
+        // We are out of packets. Silently drop it. Alternatively we can deal with it:\r
+        //    - By keeping separate send and receive pools\r
+        //    - Dynamically allocate more pools as needed and free them when not needed\r
+        //\r
+    }\r
+\r
+    return(Status);\r
+}\r
+\r
+\r
+VOID\r
+MPSendPackets(\r
+    IN NDIS_HANDLE             MiniportAdapterContext,\r
+    IN PPNDIS_PACKET           PacketArray,\r
+    IN UINT                    NumberOfPackets\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Send Packet Array handler. Either this or our SendPacket handler is called\r
+    based on which one is enabled in our Miniport Characteristics.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext     Pointer to our adapter\r
+    PacketArray                Set of packets to send\r
+    NumberOfPackets            Self-explanatory\r
+\r
+Return Value:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+    PADAPT              pAdapt = (PADAPT)MiniportAdapterContext;\r
+    NDIS_STATUS         Status;\r
+    UINT                i;\r
+    PVOID               MediaSpecificInfo = NULL;\r
+    UINT                MediaSpecificInfoSize = 0;\r
+    \r
+\r
+    for (i = 0; i < NumberOfPackets; i++)\r
+    {\r
+        PNDIS_PACKET    Packet, MyPacket;\r
+\r
+        Packet = PacketArray[i];\r
+        //\r
+        // The driver should fail the send if the virtual miniport is in low \r
+        // power state\r
+        //\r
+        if (pAdapt->MPDeviceState > NdisDeviceStateD0)\r
+        {\r
+            NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),\r
+                            Packet,\r
+                            NDIS_STATUS_FAILURE);\r
+            continue;\r
+        }\r
+\r
+#ifdef NDIS51\r
+\r
+        //\r
+        // Use NDIS 5.1 packet stacking:\r
+        //\r
+        {\r
+            PNDIS_PACKET_STACK        pStack;\r
+            BOOLEAN                   Remaining;\r
+\r
+            //\r
+            // Packet stacks: Check if we can use the same packet for sending down.\r
+            //\r
+            pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);\r
+            if (Remaining)\r
+            {\r
+                //\r
+                // We can reuse "Packet".\r
+                //\r
+                // NOTE: if we needed to keep per-packet information in packets\r
+                // sent down, we can use pStack->IMReserved[].\r
+                //\r
+                ASSERT(pStack);\r
+                //\r
+                // If the below miniport is going to low power state, stop sending down any packet.\r
+                //\r
+                NdisAcquireSpinLock(&pAdapt->Lock);\r
+                if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+                {\r
+                    NdisReleaseSpinLock(&pAdapt->Lock);\r
+                    NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),\r
+                                        Packet,\r
+                                        NDIS_STATUS_FAILURE);\r
+                }\r
+                else\r
+                {\r
+                    pAdapt->OutstandingSends++;\r
+                    NdisReleaseSpinLock(&pAdapt->Lock);\r
+                \r
+                    NdisSend(&Status,\r
+                              pAdapt->BindingHandle,\r
+                              Packet);\r
+        \r
+                    if (Status != NDIS_STATUS_PENDING)\r
+                    {\r
+                        NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),\r
+                                            Packet,\r
+                                            Status);\r
+                   \r
+                        ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+                    }\r
+                }\r
+                continue;\r
+            }\r
+        }\r
+#endif\r
+        do \r
+        {\r
+            NdisAcquireSpinLock(&pAdapt->Lock);\r
+            //\r
+            // If the below miniport is going to low power state, stop sending down any packet.\r
+            //\r
+            if (pAdapt->PTDeviceState > NdisDeviceStateD0)\r
+            {\r
+                NdisReleaseSpinLock(&pAdapt->Lock);\r
+                Status = NDIS_STATUS_FAILURE;\r
+                break;\r
+            }\r
+            pAdapt->OutstandingSends++;\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            \r
+            NdisAllocatePacket(&Status,\r
+                               &MyPacket,\r
+                               pAdapt->SendPacketPoolHandle);\r
+\r
+            if (Status == NDIS_STATUS_SUCCESS)\r
+            {\r
+                PSEND_RSVD        SendRsvd;\r
+\r
+                SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);\r
+                SendRsvd->OriginalPkt = Packet;\r
+\r
+                NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);\r
+\r
+                NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);\r
+                NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);\r
+#ifdef WIN9X\r
+                //\r
+                // Work around the fact that NDIS does not initialize this\r
+                // to FALSE on Win9x.\r
+                //\r
+                NDIS_PACKET_VALID_COUNTS(MyPacket) = FALSE;\r
+#endif // WIN9X\r
+\r
+                //\r
+                // Copy the OOB data from the original packet to the new\r
+                // packet.\r
+                //\r
+                NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),\r
+                            NDIS_OOB_DATA_FROM_PACKET(Packet),\r
+                            sizeof(NDIS_PACKET_OOB_DATA));\r
+                //\r
+                // Copy relevant parts of the per packet info into the new packet\r
+                //\r
+#ifndef WIN9X\r
+                NdisIMCopySendPerPacketInfo(MyPacket, Packet);\r
+#endif\r
+\r
+                //\r
+                // Copy the Media specific information\r
+                //\r
+                NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,\r
+                                                    &MediaSpecificInfo,\r
+                                                    &MediaSpecificInfoSize);\r
+\r
+                if (MediaSpecificInfo || MediaSpecificInfoSize)\r
+                {\r
+                    NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,\r
+                                                        MediaSpecificInfo,\r
+                                                        MediaSpecificInfoSize);\r
+                }\r
+\r
+                NdisSend(&Status,\r
+                         pAdapt->BindingHandle,\r
+                         MyPacket);\r
+\r
+                if (Status != NDIS_STATUS_PENDING)\r
+                {\r
+#ifndef WIN9X\r
+                    NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);\r
+#endif\r
+                    NdisFreePacket(MyPacket);\r
+                    ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+                }\r
+            }\r
+            else\r
+            {\r
+                //\r
+                // The driver cannot allocate a packet.\r
+                // \r
+                ADAPT_DECR_PENDING_SENDS(pAdapt);\r
+            }\r
+        }\r
+        while (FALSE);\r
+\r
+        if (Status != NDIS_STATUS_PENDING)\r
+        {\r
+            NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt),\r
+                              Packet,\r
+                              Status);\r
+        }\r
+    }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+MPQueryInformation(\r
+    IN NDIS_HANDLE                MiniportAdapterContext,\r
+    IN NDIS_OID                   Oid,\r
+    IN PVOID                      InformationBuffer,\r
+    IN ULONG                      InformationBufferLength,\r
+    OUT PULONG                    BytesWritten,\r
+    OUT PULONG                    BytesNeeded\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Entry point called by NDIS to query for the value of the specified OID.\r
+    Typical processing is to forward the query down to the underlying miniport.\r
+\r
+    The following OIDs are filtered here:\r
+\r
+    OID_PNP_QUERY_POWER - return success right here\r
+\r
+    OID_GEN_SUPPORTED_GUIDS - do not forward, otherwise we will show up\r
+    multiple instances of private GUIDs supported by the underlying miniport.\r
+\r
+    OID_PNP_CAPABILITIES - we do send this down to the lower miniport, but\r
+    the values returned are postprocessed before we complete this request;\r
+    see PtRequestComplete.\r
+\r
+    NOTE on OID_TCP_TASK_OFFLOAD - if this IM driver modifies the contents\r
+    of data it passes through such that a lower miniport may not be able\r
+    to perform TCP task offload, then it should not forward this OID down,\r
+    but fail it here with the status NDIS_STATUS_NOT_SUPPORTED. This is to\r
+    avoid performing incorrect transformations on data.\r
+\r
+    If our miniport edge (upper edge) is at a low-power state, fail the request.\r
+\r
+    If our protocol edge (lower edge) has been notified of a low-power state,\r
+    we pend this request until the miniport below has been set to D0. Since\r
+    requests to miniports are serialized always, at most a single request will\r
+    be pended.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext    Pointer to the adapter structure\r
+    Oid                       Oid for this query\r
+    InformationBuffer         Buffer for information\r
+    InformationBufferLength   Size of this buffer\r
+    BytesWritten              Specifies how much info is written\r
+    BytesNeeded               In case the buffer is smaller than what we need, tell them how much is needed\r
+\r
+\r
+Return Value:\r
+\r
+    Return code from the NdisRequest below.\r
+\r
+--*/\r
+{\r
+    PADAPT        pAdapt = (PADAPT)MiniportAdapterContext;\r
+    NDIS_STATUS   Status = NDIS_STATUS_FAILURE;\r
+\r
+    do\r
+    {\r
+        if (Oid == OID_PNP_QUERY_POWER)\r
+        {\r
+            //\r
+            //  Do not forward this.\r
+            //\r
+            Status = NDIS_STATUS_SUCCESS;\r
+            break;\r
+        }\r
+\r
+        if (Oid == OID_GEN_SUPPORTED_GUIDS)\r
+        {\r
+            //\r
+            //  Do not forward this, otherwise we will end up with multiple\r
+            //  instances of private GUIDs that the underlying miniport\r
+            //  supports.\r
+            //\r
+            Status = NDIS_STATUS_NOT_SUPPORTED;\r
+            break;\r
+        }\r
+\r
+        if (Oid == OID_TCP_TASK_OFFLOAD)\r
+        {\r
+            //\r
+            // Fail this -if- this driver performs data transformations\r
+            // that can interfere with a lower driver's ability to offload\r
+            // TCP tasks.\r
+            //\r
+            // Status = NDIS_STATUS_NOT_SUPPORTED;\r
+            // break;\r
+            //\r
+        }\r
+        //\r
+        // If the miniport below is unbinding, just fail any request\r
+        //\r
+        NdisAcquireSpinLock(&pAdapt->Lock);\r
+        if (pAdapt->UnbindingInProcess == TRUE)\r
+        {\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            Status = NDIS_STATUS_FAILURE;\r
+            break;\r
+        }\r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+        //\r
+        // All other queries are failed, if the miniport is not at D0,\r
+        //\r
+        if (pAdapt->MPDeviceState > NdisDeviceStateD0) \r
+        {\r
+            Status = NDIS_STATUS_FAILURE;\r
+            break;\r
+        }\r
+\r
+        pAdapt->Request.RequestType = NdisRequestQueryInformation;\r
+        pAdapt->Request.DATA.QUERY_INFORMATION.Oid = Oid;\r
+        pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer = InformationBuffer;\r
+        pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength = InformationBufferLength;\r
+        pAdapt->BytesNeeded = BytesNeeded;\r
+        pAdapt->BytesReadOrWritten = BytesWritten;\r
+\r
+        //\r
+        // If the miniport below is binding, fail the request\r
+        //\r
+        NdisAcquireSpinLock(&pAdapt->Lock);\r
+            \r
+        if (pAdapt->UnbindingInProcess == TRUE)\r
+        {\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            Status = NDIS_STATUS_FAILURE;\r
+            break;\r
+        }\r
+        //\r
+        // If the Protocol device state is OFF, mark this request as being \r
+        // pended. We queue this until the device state is back to D0. \r
+        //\r
+        if ((pAdapt->PTDeviceState > NdisDeviceStateD0) \r
+                && (pAdapt->StandingBy == FALSE))\r
+        {\r
+            pAdapt->QueuedRequest = TRUE;\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            Status = NDIS_STATUS_PENDING;\r
+            break;\r
+        }\r
+        //\r
+        // This is in the process of powering down the system, always fail the request\r
+        // \r
+        if (pAdapt->StandingBy == TRUE)\r
+        {\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            Status = NDIS_STATUS_FAILURE;\r
+            break;\r
+        }\r
+        pAdapt->OutstandingRequests = TRUE;\r
+        \r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+\r
+        //\r
+        // default case, most requests will be passed to the miniport below\r
+        //\r
+        NdisRequest(&Status,\r
+                    pAdapt->BindingHandle,\r
+                    &pAdapt->Request);\r
+\r
+\r
+        if (Status != NDIS_STATUS_PENDING)\r
+        {\r
+            PtRequestComplete(pAdapt, &pAdapt->Request, Status);\r
+            Status = NDIS_STATUS_PENDING;\r
+        }\r
+\r
+    } while (FALSE);\r
+\r
+    return(Status);\r
+\r
+}\r
+\r
+\r
+VOID\r
+MPQueryPNPCapabilities(\r
+    IN OUT PADAPT            pAdapt,\r
+    OUT PNDIS_STATUS         pStatus\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Postprocess a request for OID_PNP_CAPABILITIES that was forwarded\r
+    down to the underlying miniport, and has been completed by it.\r
+\r
+Arguments:\r
+\r
+    pAdapt - Pointer to the adapter structure\r
+    pStatus - Place to return final status\r
+\r
+Return Value:\r
+\r
+    None.\r
+\r
+--*/\r
+\r
+{\r
+    PNDIS_PNP_CAPABILITIES           pPNPCapabilities;\r
+    PNDIS_PM_WAKE_UP_CAPABILITIES    pPMstruct;\r
+\r
+    if (pAdapt->Request.DATA.QUERY_INFORMATION.InformationBufferLength >= sizeof(NDIS_PNP_CAPABILITIES))\r
+    {\r
+        pPNPCapabilities = (PNDIS_PNP_CAPABILITIES)(pAdapt->Request.DATA.QUERY_INFORMATION.InformationBuffer);\r
+\r
+        //\r
+        // The following fields must be overwritten by an IM driver.\r
+        //\r
+        pPMstruct= & pPNPCapabilities->WakeUpCapabilities;\r
+        pPMstruct->MinMagicPacketWakeUp = NdisDeviceStateUnspecified;\r
+        pPMstruct->MinPatternWakeUp = NdisDeviceStateUnspecified;\r
+        pPMstruct->MinLinkChangeWakeUp = NdisDeviceStateUnspecified;\r
+        *pAdapt->BytesReadOrWritten = sizeof(NDIS_PNP_CAPABILITIES);\r
+        *pAdapt->BytesNeeded = 0;\r
+\r
+\r
+        //\r
+        // Setting our internal flags\r
+        // Default, device is ON\r
+        //\r
+        pAdapt->MPDeviceState = NdisDeviceStateD0;\r
+        pAdapt->PTDeviceState = NdisDeviceStateD0;\r
+\r
+        *pStatus = NDIS_STATUS_SUCCESS;\r
+    }\r
+    else\r
+    {\r
+        *pAdapt->BytesNeeded= sizeof(NDIS_PNP_CAPABILITIES);\r
+        *pStatus = NDIS_STATUS_RESOURCES;\r
+    }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+MPSetInformation(\r
+    IN NDIS_HANDLE                                  MiniportAdapterContext,\r
+    IN NDIS_OID                                     Oid,\r
+    __in_bcount(InformationBufferLength) IN PVOID   InformationBuffer,\r
+    IN ULONG                                        InformationBufferLength,\r
+    OUT PULONG                                      BytesRead,\r
+    OUT PULONG                                      BytesNeeded\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Miniport SetInfo handler.\r
+\r
+    In the case of OID_PNP_SET_POWER, record the power state and return the OID.    \r
+    Do not pass below\r
+    If the device is suspended, do not block the SET_POWER_OID \r
+    as it is used to reactivate the Passthru miniport\r
+\r
+    \r
+    PM- If the MP is not ON (DeviceState > D0) return immediately  (except for 'query power' and 'set power')\r
+         If MP is ON, but the PT is not at D0, then queue the queue the request for later processing\r
+\r
+    Requests to miniports are always serialized\r
+\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext    Pointer to the adapter structure\r
+    Oid                       Oid for this query\r
+    InformationBuffer         Buffer for information\r
+    InformationBufferLength   Size of this buffer\r
+    BytesRead                 Specifies how much info is read\r
+    BytesNeeded               In case the buffer is smaller than what we need, tell them how much is needed\r
+\r
+Return Value:\r
+\r
+    Return code from the NdisRequest below.\r
+\r
+--*/\r
+{\r
+    PADAPT        pAdapt = (PADAPT)MiniportAdapterContext;\r
+    NDIS_STATUS   Status;\r
+\r
+    Status = NDIS_STATUS_FAILURE;\r
+\r
+    do\r
+    {\r
+        //\r
+        // The Set Power should not be sent to the miniport below the Passthru, but is handled internally\r
+        //\r
+        if (Oid == OID_PNP_SET_POWER)\r
+        {\r
+            MPProcessSetPowerOid(&Status, \r
+                                 pAdapt, \r
+                                 InformationBuffer, \r
+                                 InformationBufferLength, \r
+                                 BytesRead, \r
+                                 BytesNeeded);\r
+            break;\r
+\r
+        }\r
+\r
+        //\r
+        // If the miniport below is unbinding, fail the request\r
+        //\r
+        NdisAcquireSpinLock(&pAdapt->Lock);     \r
+        if (pAdapt->UnbindingInProcess == TRUE)\r
+        {\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            Status = NDIS_STATUS_FAILURE;\r
+            break;\r
+        }\r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+        //\r
+        // All other Set Information requests are failed, if the miniport is\r
+        // not at D0 or is transitioning to a device state greater than D0.\r
+        //\r
+        if (pAdapt->MPDeviceState > NdisDeviceStateD0)\r
+        {\r
+            Status = NDIS_STATUS_FAILURE;\r
+            break;\r
+        }\r
+\r
+        // Set up the Request and return the result\r
+        pAdapt->Request.RequestType = NdisRequestSetInformation;\r
+        pAdapt->Request.DATA.SET_INFORMATION.Oid = Oid;\r
+        pAdapt->Request.DATA.SET_INFORMATION.InformationBuffer = InformationBuffer;\r
+        pAdapt->Request.DATA.SET_INFORMATION.InformationBufferLength = InformationBufferLength;\r
+        pAdapt->BytesNeeded = BytesNeeded;\r
+        pAdapt->BytesReadOrWritten = BytesRead;\r
+\r
+        //\r
+        // If the miniport below is unbinding, fail the request\r
+        //\r
+        NdisAcquireSpinLock(&pAdapt->Lock);     \r
+        if (pAdapt->UnbindingInProcess == TRUE)\r
+        {\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            Status = NDIS_STATUS_FAILURE;\r
+            break;\r
+        }\r
+            \r
+        //\r
+        // If the device below is at a low power state, we cannot send it the\r
+        // request now, and must pend it.\r
+        //\r
+        if ((pAdapt->PTDeviceState > NdisDeviceStateD0) \r
+                && (pAdapt->StandingBy == FALSE))\r
+        {\r
+            pAdapt->QueuedRequest = TRUE;\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            Status = NDIS_STATUS_PENDING;\r
+            break;\r
+        }\r
+        //\r
+        // This is in the process of powering down the system, always fail the request\r
+        // \r
+        if (pAdapt->StandingBy == TRUE)\r
+        {\r
+            NdisReleaseSpinLock(&pAdapt->Lock);\r
+            Status = NDIS_STATUS_FAILURE;\r
+            break;\r
+        }\r
+        pAdapt->OutstandingRequests = TRUE;\r
+        \r
+        NdisReleaseSpinLock(&pAdapt->Lock);\r
+        //\r
+        // Forward the request to the device below.\r
+        //\r
+        NdisRequest(&Status,\r
+                    pAdapt->BindingHandle,\r
+                    &pAdapt->Request);\r
+\r
+        if (Status != NDIS_STATUS_PENDING)\r
+        {\r
+            *BytesRead = pAdapt->Request.DATA.SET_INFORMATION.BytesRead;\r
+            *BytesNeeded = pAdapt->Request.DATA.SET_INFORMATION.BytesNeeded;\r
+            pAdapt->OutstandingRequests = FALSE;\r
+        }\r
+\r
+    } while (FALSE);\r
+\r
+    return(Status);\r
+}\r
+\r
+\r
+VOID\r
+MPProcessSetPowerOid(\r
+    IN OUT PNDIS_STATUS                             pNdisStatus,\r
+    IN PADAPT                                       pAdapt,\r
+    __in_bcount(InformationBufferLength) IN PVOID   InformationBuffer,\r
+    IN ULONG                                        InformationBufferLength,\r
+    OUT PULONG                                      BytesRead,\r
+    OUT PULONG                                      BytesNeeded\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+    This routine does all the procssing for a request with a SetPower Oid\r
+    The miniport shoud accept  the Set Power and transition to the new state\r
+\r
+    The Set Power should not be passed to the miniport below\r
+\r
+    If the IM miniport is going into a low power state, then there is no guarantee if it will ever\r
+    be asked go back to D0, before getting halted. No requests should be pended or queued.\r
+\r
+    \r
+Arguments:\r
+    pNdisStatus           - Status of the operation\r
+    pAdapt                - The Adapter structure\r
+    InformationBuffer     - The New DeviceState\r
+    InformationBufferLength\r
+    BytesRead             - No of bytes read\r
+    BytesNeeded           -  No of bytes needed\r
+\r
+\r
+Return Value:\r
+    Status  - NDIS_STATUS_SUCCESS if all the wait events succeed.\r
+\r
+--*/\r
+{\r
+\r
+    \r
+    NDIS_DEVICE_POWER_STATE NewDeviceState;\r
+\r
+    DBGPRINT(("==>MPProcessSetPowerOid: Adapt %p\n", pAdapt)); \r
+\r
+    ASSERT (InformationBuffer != NULL);\r
+\r
+    *pNdisStatus = NDIS_STATUS_FAILURE;\r
+\r
+    do \r
+    {\r
+        //\r
+        // Check for invalid length\r
+        //\r
+        if (InformationBufferLength < sizeof(NDIS_DEVICE_POWER_STATE))\r
+        {\r
+            *pNdisStatus = NDIS_STATUS_INVALID_LENGTH;\r
+            break;\r
+        }\r
+\r
+        NewDeviceState = (*(PNDIS_DEVICE_POWER_STATE)InformationBuffer);\r
+\r
+        //\r
+        // Check for invalid device state\r
+        //\r
+        if ((pAdapt->MPDeviceState > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0))\r
+        {\r
+            //\r
+            // If the miniport is in a non-D0 state, the miniport can only receive a Set Power to D0\r
+            //\r
+            ASSERT (!(pAdapt->MPDeviceState > NdisDeviceStateD0) && (NewDeviceState != NdisDeviceStateD0));\r
+\r
+            *pNdisStatus = NDIS_STATUS_FAILURE;\r
+            break;\r
+        }    \r
+\r
+        //\r
+        // Is the miniport transitioning from an On (D0) state to an Low Power State (>D0)\r
+        // If so, then set the StandingBy Flag - (Block all incoming requests)\r
+        //\r
+        if (pAdapt->MPDeviceState == NdisDeviceStateD0 && NewDeviceState > NdisDeviceStateD0)\r
+        {\r
+            pAdapt->StandingBy = TRUE;\r
+        }\r
+\r
+        //\r
+        // If the miniport is transitioning from a low power state to ON (D0), then clear the StandingBy flag\r
+        // All incoming requests will be pended until the physical miniport turns ON.\r
+        //\r
+        if (pAdapt->MPDeviceState > NdisDeviceStateD0 &&  NewDeviceState == NdisDeviceStateD0)\r
+        {\r
+            pAdapt->StandingBy = FALSE;\r
+        }\r
+        \r
+        //\r
+        // Now update the state in the pAdapt structure;\r
+        //\r
+        pAdapt->MPDeviceState = NewDeviceState;\r
+        \r
+        *pNdisStatus = NDIS_STATUS_SUCCESS;\r
+    \r
+\r
+    } while (FALSE);    \r
+        \r
+    if (*pNdisStatus == NDIS_STATUS_SUCCESS)\r
+    {\r
+        //\r
+        // The miniport resume from low power state\r
+        // \r
+        if (pAdapt->StandingBy == FALSE)\r
+        {\r
+            //\r
+            // If we need to indicate the media connect state\r
+            // \r
+            if (pAdapt->LastIndicatedStatus != pAdapt->LatestUnIndicateStatus)\r
+            {\r
+               if (pAdapt->MiniportHandle != NULL)\r
+               {\r
+                   NdisMIndicateStatus(pAdapt->MiniportHandle,\r
+                                            pAdapt->LatestUnIndicateStatus,\r
+                                            (PVOID)NULL,\r
+                                            0);\r
+                   NdisMIndicateStatusComplete(pAdapt->MiniportHandle);\r
+                   pAdapt->LastIndicatedStatus = pAdapt->LatestUnIndicateStatus;\r
+               }\r
+            }\r
+        }\r
+        else\r
+        {\r
+            //\r
+            // Initialize LatestUnIndicatedStatus\r
+            //\r
+            pAdapt->LatestUnIndicateStatus = pAdapt->LastIndicatedStatus;\r
+        }\r
+        *BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);\r
+        *BytesNeeded = 0;\r
+    }\r
+    else\r
+    {\r
+        *BytesRead = 0;\r
+        *BytesNeeded = sizeof (NDIS_DEVICE_POWER_STATE);\r
+    }\r
+\r
+    DBGPRINT(("<==MPProcessSetPowerOid: Adapt %p\n", pAdapt)); \r
+}\r
+\r
+\r
+VOID\r
+MPReturnPacket(\r
+    IN NDIS_HANDLE             MiniportAdapterContext,\r
+    IN PNDIS_PACKET            Packet\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    NDIS Miniport entry point called whenever protocols are done with\r
+    a packet that we had indicated up and they had queued up for returning\r
+    later.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext    - pointer to ADAPT structure\r
+    Packet    - packet being returned.\r
+\r
+Return Value:\r
+\r
+    None.\r
+\r
+--*/\r
+{\r
+    PADAPT            pAdapt = (PADAPT)MiniportAdapterContext;\r
+\r
+#ifdef NDIS51\r
+    //\r
+    // Packet stacking: Check if this packet belongs to us.\r
+    //\r
+    if (NdisGetPoolFromPacket(Packet) != pAdapt->RecvPacketPoolHandle)\r
+    {\r
+        //\r
+        // We reused the original packet in a receive indication.\r
+        // Simply return it to the miniport below us.\r
+        //\r
+        NdisReturnPackets(&Packet, 1);\r
+    }\r
+    else\r
+#endif // NDIS51\r
+    {\r
+        //\r
+        // This is a packet allocated from this IM's receive packet pool.\r
+        // Reclaim our packet, and return the original to the driver below.\r
+        //\r
+\r
+        PNDIS_PACKET    MyPacket;\r
+        PRECV_RSVD      RecvRsvd;\r
+    \r
+        RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved);\r
+        MyPacket = RecvRsvd->OriginalPkt;\r
+    \r
+        NdisFreePacket(Packet);\r
+        NdisReturnPackets(&MyPacket, 1);\r
+    }\r
+}\r
+\r
+\r
+NDIS_STATUS\r
+MPTransferData(\r
+    OUT PNDIS_PACKET            Packet,\r
+    OUT PUINT                   BytesTransferred,\r
+    IN NDIS_HANDLE              MiniportAdapterContext,\r
+    IN NDIS_HANDLE              MiniportReceiveContext,\r
+    IN UINT                     ByteOffset,\r
+    IN UINT                     BytesToTransfer\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Miniport's transfer data handler.\r
+\r
+Arguments:\r
+\r
+    Packet                    Destination packet\r
+    BytesTransferred          Place-holder for how much data was copied\r
+    MiniportAdapterContext    Pointer to the adapter structure\r
+    MiniportReceiveContext    Context\r
+    ByteOffset                Offset into the packet for copying data\r
+    BytesToTransfer           How much to copy.\r
+\r
+Return Value:\r
+\r
+    Status of transfer\r
+\r
+--*/\r
+{\r
+    PADAPT        pAdapt = (PADAPT)MiniportAdapterContext;\r
+    NDIS_STATUS   Status;\r
+\r
+    //\r
+    // Return, if the device is OFF\r
+    //\r
+\r
+    if (IsIMDeviceStateOn(pAdapt) == FALSE)\r
+    {\r
+        return NDIS_STATUS_FAILURE;\r
+    }\r
+\r
+    NdisTransferData(&Status,\r
+                     pAdapt->BindingHandle,\r
+                     MiniportReceiveContext,\r
+                     ByteOffset,\r
+                     BytesToTransfer,\r
+                     Packet,\r
+                     BytesTransferred);\r
+\r
+    return(Status);\r
+}\r
+\r
+VOID\r
+MPHalt(\r
+    IN NDIS_HANDLE                MiniportAdapterContext\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Halt handler. All the hard-work for clean-up is done here.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext    Pointer to the Adapter\r
+\r
+Return Value:\r
+\r
+    None.\r
+\r
+--*/\r
+{\r
+    PADAPT             pAdapt = (PADAPT)MiniportAdapterContext;\r
+    NDIS_STATUS        Status;\r
+    PADAPT            *ppCursor;\r
+\r
+    DBGPRINT(("==>MiniportHalt: Adapt %p\n", pAdapt));\r
+\r
+    pAdapt->MiniportHandle = NULL;\r
+    pAdapt->MiniportIsHalted = TRUE;\r
+\r
+    //\r
+    // Remove this adapter from the global list\r
+    //\r
+    NdisAcquireSpinLock(&GlobalLock);\r
+\r
+    for (ppCursor = &pAdaptList; *ppCursor != NULL; ppCursor = &(*ppCursor)->Next)\r
+    {\r
+        if (*ppCursor == pAdapt)\r
+        {\r
+            *ppCursor = pAdapt->Next;\r
+            break;\r
+        }\r
+    }\r
+\r
+    NdisReleaseSpinLock(&GlobalLock);\r
+\r
+    //\r
+    // Delete the ioctl interface that was created when the miniport\r
+    // was created.\r
+    //\r
+    (VOID)PtDeregisterDevice();\r
+\r
+    //\r
+    // If we have a valid bind, close the miniport below the protocol\r
+    //\r
+#pragma prefast(suppress: __WARNING_DEREF_NULL_PTR, "pAdapt cannot be NULL")\r
+    if (pAdapt->BindingHandle != NULL)\r
+    {\r
+        //\r
+        // Close the binding below. and wait for it to complete\r
+        //\r
+        NdisResetEvent(&pAdapt->Event);\r
+\r
+        NdisCloseAdapter(&Status, pAdapt->BindingHandle);\r
+\r
+        if (Status == NDIS_STATUS_PENDING)\r
+        {\r
+            NdisWaitEvent(&pAdapt->Event, 0);\r
+            Status = pAdapt->Status;\r
+        }\r
+\r
+        ASSERT (Status == NDIS_STATUS_SUCCESS);\r
+\r
+        pAdapt->BindingHandle = NULL;\r
+        \r
+        PtDereferenceAdapt(pAdapt);\r
+    }\r
+\r
+    if (PtDereferenceAdapt(pAdapt))\r
+    {\r
+        pAdapt = NULL;\r
+    }\r
+        \r
+    \r
+    DBGPRINT(("<== MiniportHalt: pAdapt %p\n", pAdapt));\r
+}\r
+\r
+\r
+#ifdef NDIS51_MINIPORT\r
+\r
+VOID\r
+MPCancelSendPackets(\r
+    IN NDIS_HANDLE            MiniportAdapterContext,\r
+    IN PVOID                  CancelId\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    The miniport entry point to handle cancellation of all send packets\r
+    that match the given CancelId. If we have queued any packets that match\r
+    this, then we should dequeue them and call NdisMSendComplete for all\r
+    such packets, with a status of NDIS_STATUS_REQUEST_ABORTED.\r
+\r
+    We should also call NdisCancelSendPackets in turn, on each lower binding\r
+    that this adapter corresponds to. This is to let miniports below cancel\r
+    any matching packets.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext    - pointer to ADAPT structure\r
+    CancelId    - ID of packets to be cancelled.\r
+\r
+Return Value:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+    PADAPT    pAdapt = (PADAPT)MiniportAdapterContext;\r
+\r
+    //\r
+    // If we queue packets on our adapter structure, this would be \r
+    // the place to acquire a spinlock to it, unlink any packets whose\r
+    // Id matches CancelId, release the spinlock and call NdisMSendComplete\r
+    // with NDIS_STATUS_REQUEST_ABORTED for all unlinked packets.\r
+    //\r
+\r
+    //\r
+    // Next, pass this down so that we let the miniport(s) below cancel\r
+    // any packets that they might have queued.\r
+    //\r
+    NdisCancelSendPackets(pAdapt->BindingHandle, CancelId);\r
+\r
+    return;\r
+}\r
+\r
+VOID\r
+MPDevicePnPEvent(\r
+    IN NDIS_HANDLE              MiniportAdapterContext,\r
+    IN NDIS_DEVICE_PNP_EVENT    DevicePnPEvent,\r
+    IN PVOID                    InformationBuffer,\r
+    IN ULONG                    InformationBufferLength\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This handler is called to notify us of PnP events directed to\r
+    our miniport device object.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext    - pointer to ADAPT structure\r
+    DevicePnPEvent - the event\r
+    InformationBuffer - Points to additional event-specific information\r
+    InformationBufferLength - length of above\r
+\r
+Return Value:\r
+\r
+    None\r
+--*/\r
+{\r
+    // TBD - add code/comments about processing this.\r
+\r
+    UNREFERENCED_PARAMETER(MiniportAdapterContext);\r
+    UNREFERENCED_PARAMETER(DevicePnPEvent);\r
+    UNREFERENCED_PARAMETER(InformationBuffer);\r
+    UNREFERENCED_PARAMETER(InformationBufferLength);\r
+    \r
+    return;\r
+}\r
+\r
+VOID\r
+MPAdapterShutdown(\r
+    IN NDIS_HANDLE                MiniportAdapterContext\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This handler is called to notify us of an impending system shutdown.\r
+\r
+Arguments:\r
+\r
+    MiniportAdapterContext    - pointer to ADAPT structure\r
+\r
+Return Value:\r
+\r
+    None\r
+--*/\r
+{\r
+    UNREFERENCED_PARAMETER(MiniportAdapterContext);\r
+    \r
+    return;\r
+}\r
+\r
+#endif\r
+\r
+\r
+VOID\r
+MPFreeAllPacketPools(\r
+    IN PADAPT                    pAdapt\r
+    )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    Free all packet pools on the specified adapter.\r
+    \r
+Arguments:\r
+\r
+    pAdapt    - pointer to ADAPT structure\r
+\r
+Return Value:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+    if (pAdapt->RecvPacketPoolHandle != NULL)\r
+    {\r
+        //\r
+        // Free the packet pool that is used to indicate receives\r
+        //\r
+        NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);\r
+\r
+        pAdapt->RecvPacketPoolHandle = NULL;\r
+    }\r
+\r
+    if (pAdapt->SendPacketPoolHandle != NULL)\r
+    {\r
+\r
+        //\r
+        //  Free the packet pool that is used to send packets below\r
+        //\r
+\r
+        NdisFreePacketPool(pAdapt->SendPacketPoolHandle);\r
+\r
+        pAdapt->SendPacketPoolHandle = NULL;\r
+\r
+    }\r
+}\r
+\r