Пример #1
0
VOID
Hw11Free(
    __in  PHW                     Hw
    )
{
    NdisFreeSpinLock(&Hw->Lock);

    if (Hw->PhyState.PhyProgramWorkItem != NULL)
    {
        NdisFreeIoWorkItem(Hw->PhyState.PhyProgramWorkItem);
        Hw->PhyState.PhyProgramWorkItem = NULL;
    }

    if (Hw->ScanContext.Timer_Scan)
    {
        NdisFreeTimerObject(Hw->ScanContext.Timer_Scan);
        Hw->ScanContext.Timer_Scan = NULL;
    }

    if (Hw->PhyState.Timer_Doze)
    {
        NdisFreeTimerObject(Hw->PhyState.Timer_Doze);
        Hw->PhyState.Timer_Doze = NULL;
    }
    
    if (Hw->PhyState.Timer_Awake)
    {
        NdisFreeTimerObject(Hw->PhyState.Timer_Awake);
        Hw->PhyState.Timer_Awake = NULL;
    }
    
    if (Hw->PhyState.RegDomainsSupportValue)
    {
        MP_FREE_MEMORY(Hw->PhyState.RegDomainsSupportValue);
        Hw->PhyState.RegDomainsSupportValue = NULL;
    }

    if (Hw->PhyState.DiversitySelectionRxList)
    {
        MP_FREE_MEMORY(Hw->PhyState.DiversitySelectionRxList);
        Hw->PhyState.DiversitySelectionRxList = NULL;
    }
    if (Hw->Hal != NULL)
    {
        HalFreeNic(Hw->Hal);
        Hw->Hal = NULL;
    }
    
    MP_FREE_MEMORY(Hw);
}
Пример #2
0
VOID
Sta11FreeRegistryInformation(
    _In_opt_  PVOID                   RegistryInformation
    )
{
    if (RegistryInformation != NULL)
    {
        MP_FREE_MEMORY(RegistryInformation);
    }
}
Пример #3
0
/**
* Cleansup the DataRecorder
* 
* \sa Initialize()
*/
VOID TerminateDataRecorder (PMP_DATA_RECORDER_OBJ Recorder)
{
    Recorder->MaxLength = 0;
    Recorder->CurrentIndex = 0;
 
    if (Recorder->RecordList)
    {
        MP_FREE_MEMORY(Recorder->RecordList);
        Recorder->RecordList = NULL;
    }
}
Пример #4
0
VOID
Hvl11Cleanup80211Attributes(
    _In_  PHVL                    Hvl,
    _In_  PNDIS_MINIPORT_ADAPTER_NATIVE_802_11_ATTRIBUTES Attr
)
{
    UNREFERENCED_PARAMETER(Hvl);

    if (Attr->VWiFiAttributes)
    {
        MP_FREE_MEMORY(Attr->VWiFiAttributes);
    }
}
Пример #5
0
VOID
StaFreeAssociateRequestPacket(
                             __in  PSTATION        pStation,
                             __in  PSTA_BSS_ENTRY  pAPEntry,
                             __out PUCHAR          pAssocPacket,
                             __out USHORT          AssocPacketLength
                             )
{
    UNREFERENCED_PARAMETER(pStation);
    UNREFERENCED_PARAMETER(pAPEntry);
    UNREFERENCED_PARAMETER(AssocPacketLength);

    MP_FREE_MEMORY(pAssocPacket);
}
Пример #6
0
VOID
Sta11FreeStation(
    __in PSTATION         pStation
    )
{
    MPVERIFY(pStation);

    // Cleanup anything we create for scan
    StaFreeScanContext(pStation);

    // Cleanup connection context
    StaFreeConnectionContext(pStation);

    // Free any memory allocated for Adhoc
    StaFreeAdHocStaInfo(pStation);
    
    MP_FREE_MEMORY(pStation);
}
Пример #7
0
VOID
Sta11FreePort(
    _In_  PMP_PORT                Port
    )
{
    PMP_EXTSTA_PORT             extStaPort = MP_GET_STA_PORT(Port);
    
    // Cleanup anything we create for scan
    StaFreeScanContext(extStaPort);

    // Cleanup connection context
    StaFreeConnectionContext(extStaPort);

    // Free any memory allocated for Adhoc
    StaFreeAdHocStaInfo(extStaPort);

    MP_FREE_MEMORY(extStaPort);    
}
Пример #8
0
VOID
HelperPortTerminateScanContext(
    _In_  PMP_HELPER_PORT         HelperPort
    )
{
    PMP_SCAN_PARAMETERS         scanParameters = NULL;

    ULONG                       i;

    // There can be scan requests around if we were waiting for exclusive access
    // for a request and it did not get satisfied
    if (HelperPort->ScanContext.ParametersCount != 0)
    {
        // We may have scan requests structures allocated, waiting for exclusive access
        // but that is never going to get satisfied. Free the requests
        for (i = 0; i < MP_MAX_NUMBER_OF_PORT; i++)
        {
            scanParameters = &HelperPort->ScanContext.ScanParameters[i];
            if (scanParameters->State != SCAN_EMPTY_REQUEST)
            {
                // The only condition in which this is OK is when we are waiting for 
                // an exclusive access
                MPASSERT(scanParameters->UsageCount == 1);
                HelperPortScanParametersReleaseRef(HelperPort, scanParameters);
            }
        }        
    }

    if (HelperPort->ScanContext.Timer_Scan)
    {
        NdisFreeTimerObject(HelperPort->ScanContext.Timer_Scan);
        HelperPort->ScanContext.Timer_Scan = NULL;
    }

    for (i = 0; i < HW11_MAX_PHY_COUNT; i++)
    {
        if (HelperPort->ScanContext.ScanChannels[i].ChannelList != NULL)
        {
            MP_FREE_MEMORY(HelperPort->ScanContext.ScanChannels[i].ChannelList);
            HelperPort->ScanContext.ScanChannels[i].ChannelList = NULL;
        }
    }
}
Пример #9
0
VOID
HelperPortScanParametersReleaseRef(
    _In_  PMP_HELPER_PORT         HelperPort,
    _In_  PMP_SCAN_PARAMETERS     ScanParameters
    )
{
    if (MP_DECREMENT_SCAN_PARAMETER_REF(ScanParameters) == 0)
    {
        // Free the channel list
        if (ScanParameters->VNicScanRequest.ChannelList != NULL)
        {
            MP_FREE_MEMORY(ScanParameters->VNicScanRequest.ChannelList );
            ScanParameters->VNicScanRequest.ChannelList = NULL;
        }

        // Release the structure
        HelperPort->ScanContext.ParametersCount--;    
        ScanParameters->State = SCAN_EMPTY_REQUEST;
    }
}
Пример #10
0
VOID
BasePortCompleteFailedPackets(
    __in  PMP_PORT                Port,
    __in  PMP_TX_MSDU             PacketList,
    __in  ULONG                   SendCompleteFlags
    )
{
    PMP_TX_MSDU                 currentPacket = PacketList;
    PNET_BUFFER_LIST            currentNetBufferList, prevNetBufferList = NULL;
    PNET_BUFFER_LIST            netBufferListsToComplete = NULL;
    #if DBG
    ULONG ulNumNBLs = 0, ulInternalSends = 0;
    #endif
        

    while (currentPacket != NULL)
    {        
        //
        // No refcount is added yet, so we dont need to remove anything
        //

        if (MP_TX_MSDU_WRAPPED_NBL(currentPacket) == NULL)
        {
            #if DBG
            ulInternalSends++;
            #endif
            // Internal packet submitted from BasePortSendInternalPacket, free the memory
            // we allocated for the buffer
            MP_FREE_MEMORY(MP_TX_MSDU_MPDU_AT(currentPacket, 0)->InternalSendBuffer);
        }
        else
        {
            #if DBG
            ulNumNBLs++;
            #endif
            //
            // There were from the OS. We need to convert back to NBLs and 
            // complete them to the OS
            //

            //
            // Get the NBLs out
            //
            currentNetBufferList = currentPacket->NetBufferList;
            NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList) = NULL;
            NET_BUFFER_LIST_STATUS(currentNetBufferList) = currentPacket->Status;

            if (netBufferListsToComplete == NULL)
            {
                netBufferListsToComplete = currentNetBufferList;
            }
            else
            {
                NET_BUFFER_LIST_NEXT_NBL(prevNetBufferList) = currentNetBufferList;
            }
            
            prevNetBufferList = currentNetBufferList;
        }

        currentPacket = MP_TX_MSDU_NEXT_MSDU(currentPacket);
    }

    //
    // Free our packet wrapper structures for all the packets
    //
    BasePortFreeTranslatedTxPackets(Port, PacketList);

    #if DBG
        MpTrace(COMP_SEND, DBG_NORMAL, ("Port(%d): NdisMSendNetBufferListsComplete called with %d NBLs\n", Port->PortNumber, ulNumNBLs));
        MpTrace(COMP_SEND, DBG_NORMAL, ("Port(%d): Completed %d internal sends\n", Port->PortNumber, ulInternalSends));
    #endif        

    if (netBufferListsToComplete != NULL)
    {
        // Complete the NBLs back to NDIS
        NdisMSendNetBufferListsComplete(
            Port->MiniportAdapterHandle,
            netBufferListsToComplete,
            SendCompleteFlags
            );
    }
}
Пример #11
0
VOID
StaInitializeStationConfig(
    __in PSTATION         pStation
    )
{
    PSTA_CURRENT_CONFIG         pConfig = &pStation->Config;

    //
    // free PrivacyExemptionList
    //
    if (pConfig->PrivacyExemptionList)
    {
        MP_FREE_MEMORY(pStation->Config.PrivacyExemptionList);
    }

    //
    // free IBSS params
    //
    if (pConfig->AdditionalIEData)
    {
        MP_FREE_MEMORY(pConfig->AdditionalIEData);
    }

    //
    // Any dynamically allocated structure must be freed prior to this point.
    //
    NdisZeroMemory(pConfig, sizeof(STA_CURRENT_CONFIG));

    pConfig->BSSType = dot11_BSS_type_infrastructure;
    // Wildcard SSID
    pConfig->SSID.uSSIDLength = 0;

    // Setup to accept an BSSID
    pConfig->DesiredBSSIDList[0][0] = 0xFF;
    pConfig->DesiredBSSIDList[0][1] = 0xFF;
    pConfig->DesiredBSSIDList[0][2] = 0xFF;
    pConfig->DesiredBSSIDList[0][3] = 0xFF;
    pConfig->DesiredBSSIDList[0][4] = 0xFF;
    pConfig->DesiredBSSIDList[0][5] = 0xFF;
    pConfig->DesiredBSSIDCount = 1;
    pConfig->AcceptAnyBSSID = TRUE;

    //
    // Reset other configuration parameters.
    //
    pConfig->UnreachableDetectionThreshold = 2000;
    pConfig->ExcludeUnencrypted = FALSE;

    pConfig->AID = 0;
    pConfig->ValidAID = FALSE;
    pConfig->ListenInterval = 3;        // TODO: FIX this.

    pConfig->MediaStreamingEnabled = FALSE;
    pConfig->UnicastUseGroupEnabled = TRUE;
    pConfig->HiddenNetworkEnabled = FALSE;
    
    //
    // Reset desired PHY ID list
    //
    pConfig->DesiredPhyCount = 1;
    pConfig->DesiredPhyList[0] = DOT11_PHY_ID_ANY;
    pConfig->ActivePhyId = DOT11_PHY_ID_ANY;

    //
    // This is scan specific setting 
    //
    pStation->ScanContext.SSIDInProbeRequest = TRUE;         // True until we go to low power state

}
Пример #12
0
// BSS list lock acquired & called at Dispatch
NDIS_STATUS 
HelperPortUpdateBSSEntry(
    __in  PMP_HELPER_PORT        HelperPort,
    __in  PMP_BSS_ENTRY  pBSSEntry,
    __in  PMP_RX_MPDU        pFragment,
    __in  PDOT11_BEACON_FRAME pDot11BeaconPRFrame,
    __in  ULONG           BeaconPRDataLength
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PDOT11_MGMT_HEADER  pMgmtPktHeader;
    ULONGLONG           ullHostTimeStamp;
    PVOID               pSavedBeaconPRBuffer = NULL;
    ULONG               uOffsetOfInfoElemBlob = FIELD_OFFSET(DOT11_BEACON_FRAME, InfoElements);
    UCHAR               channel;
    DOT11_PHY_TYPE      PhyType;

    pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment);
    NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp);
    
    do
    {
        // 
        // Modifying data in the AP entry
        //
        NdisDprAcquireSpinLock(&(pBSSEntry->Lock));

        if (pDot11BeaconPRFrame->Capability.IBSS)
        {
            pBSSEntry->Dot11BSSType = dot11_BSS_type_independent;
        }
        else
        {   
            pBSSEntry->Dot11BSSType = dot11_BSS_type_infrastructure;
        }
        
        //
        // Adhoc station can leave adhoc cell and create a new cell. SoftAPs
        // can move. This means the BSSID can change
        //
        NdisMoveMemory(
            pBSSEntry->Dot11BSSID,
            pMgmtPktHeader->BSSID,
            sizeof(DOT11_MAC_ADDRESS)
            );

        pBSSEntry->HostTimestamp = ullHostTimeStamp;
        pBSSEntry->BeaconTimestamp = pDot11BeaconPRFrame->Timestamp;
        pBSSEntry->BeaconInterval = pDot11BeaconPRFrame->BeaconInterval;
        pBSSEntry->Dot11Capability = pDot11BeaconPRFrame->Capability;
        pBSSEntry->RSSI = pFragment->Msdu->RecvContext.lRSSI;
        pBSSEntry->LinkQuality = pFragment->Msdu->LinkQuality;
        pBSSEntry->ChannelCenterFrequency 
            = pFragment->Msdu->RecvContext.uChCenterFrequency;

        //
        // If signal strength was below our threshold, catch that
        //
        if (pBSSEntry->LinkQuality < HelperPort->RegInfo->RSSILinkQualityThreshold)
        {
            pBSSEntry->LowQualityCount++;
        }
        else
        {
            pBSSEntry->LowQualityCount = 0;
        }

#if 0
        if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc)
        {
            MpTrace(COMP_ASSOC, DBG_LOUD, ("Received beacon from associated AP: %02X-%02X-%02X-%02X-%02X-%02X\n",
                pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], 
                pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5]));
        }
#endif

        //
        // Get channel number at which the frame was received.
        //
        if (Dot11GetChannelForDSPhy(Add2Ptr(pDot11BeaconPRFrame, uOffsetOfInfoElemBlob),
                                    BeaconPRDataLength - uOffsetOfInfoElemBlob, 
                                    &channel) != NDIS_STATUS_SUCCESS)
        {
            channel = pFragment->Msdu->Channel;
        }

        if (channel != 0)
        {
            pBSSEntry->Channel = channel;
        }

        //
        // Get PhyType and PhyId
        //
        PhyType = VNic11DeterminePHYType(HELPPORT_GET_VNIC(HelperPort), 
                                       pBSSEntry->Dot11Capability,
                                       pBSSEntry->Channel);
        if (pBSSEntry->Dot11PhyType != PhyType)
        {
            pBSSEntry->Dot11PhyType = PhyType;
            pBSSEntry->PhyId = BasePortGetPhyIdFromType(HELPPORT_GET_MP_PORT(HelperPort), PhyType);
        }

        if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_BEACON)
        {
            //
            // Increase the beacon frame size if necessary
            //
            if (pBSSEntry->MaxBeaconFrameSize < BeaconPRDataLength)
            {
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, 
                    &pSavedBeaconPRBuffer, 
                    BeaconPRDataLength,
                    PORT_MEMORY_TAG
                    );
                    
                if (pSavedBeaconPRBuffer == NULL)
                {
                    //
                    // Unable to allocate memory for information elements.
                    // If this is a new AP entry, we wont be adding it to the list.
                    // For existing entries, we end up ignoring the new IE blob
                    //
                    ndisStatus = NDIS_STATUS_RESOURCES;
                    NdisDprReleaseSpinLock(&(pBSSEntry->Lock));
                    break;
                }
                //
                // Delete any old blob buffer
                //
                if (pBSSEntry->pDot11BeaconFrame != NULL)
                {
                    MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame);
                }

                pBSSEntry->pDot11BeaconFrame = pSavedBeaconPRBuffer;
                pBSSEntry->MaxBeaconFrameSize = BeaconPRDataLength;
            }

            // Update the beacon
            pBSSEntry->BeaconFrameSize = BeaconPRDataLength;
            
            // Also save this as the IE blob pointer
            pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob;
            pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11BeaconFrame + uOffsetOfInfoElemBlob;
            
            //
            // Update/Save the beacon information element block
            //
            NdisMoveMemory(
                pBSSEntry->pDot11BeaconFrame,
                pDot11BeaconPRFrame,
                BeaconPRDataLength
                );
        }
    
        if (pMgmtPktHeader->FrameControl.Subtype == DOT11_MGMT_SUBTYPE_PROBE_RESPONSE)
        {
            //
            // Increase the probe response frame size if necessary
            //
            if (pBSSEntry->MaxProbeFrameSize < BeaconPRDataLength)
            {
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, 
                    &pSavedBeaconPRBuffer, 
                    BeaconPRDataLength,
                    PORT_MEMORY_TAG
                    );
                    
                if (pSavedBeaconPRBuffer == NULL)
                {
                    //
                    // Unable to allocate memory for information elements.
                    // If this is a new AP entry, we wont be adding it to the list.
                    // For existing entries, we end up ignoring the new IE blob
                    //
                    ndisStatus = NDIS_STATUS_RESOURCES;
                    NdisDprReleaseSpinLock(&(pBSSEntry->Lock));
                    break;
                }
                //
                // Delete any old blob buffer
                //
                if (pBSSEntry->pDot11ProbeFrame != NULL)
                {
                    MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame);
                }

                pBSSEntry->pDot11ProbeFrame = pSavedBeaconPRBuffer;
                pBSSEntry->MaxProbeFrameSize = BeaconPRDataLength;
            }
            
            pBSSEntry->ProbeFrameSize = BeaconPRDataLength;

            // Also save this as the IE blob pointer
            pBSSEntry->InfoElemBlobSize = BeaconPRDataLength - uOffsetOfInfoElemBlob;
            pBSSEntry->pDot11InfoElemBlob = (PUCHAR)pBSSEntry->pDot11ProbeFrame + uOffsetOfInfoElemBlob;

            //
            // Update/Save the beacon information element block
            //
            NdisMoveMemory(
                pBSSEntry->pDot11ProbeFrame,
                pDot11BeaconPRFrame,
                BeaconPRDataLength
                );

        }

#if 0
        if (pBSSEntry->AssocState == dot11_assoc_state_auth_assoc)
        {
            MpTrace(COMP_SCAN, DBG_LOUD, ("Received %d for AP %02X-%02X-%02X-%02X-%02X-%02X \n", 
                    pMgmtPktHeader->FrameControl.Subtype,
                    pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], 
                    pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5]));
        }
#endif

        //
        // Done with our modification of the AP entry
        //
        NdisDprReleaseSpinLock(&(pBSSEntry->Lock));
        
    } while (FALSE);

    return ndisStatus;
Пример #13
0
NDIS_STATUS 
HelperPortInsertBSSEntry(
    __in  PMP_HELPER_PORT        HelperPort,
    __in  PMP_RX_MPDU        pFragment,
    __in  PDOT11_BEACON_FRAME pDot11BeaconFrame,
    __in  ULONG           BeaconDataLength
    )
{
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    ULONGLONG           ullHostTimeStamp;
    MP_RW_LOCK_STATE          LockState;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    PDOT11_MGMT_HEADER  pMgmtPktHeader;
    BOOLEAN             bNewAp = FALSE;
    PMP_BSS_LIST       pDiscoveredBSSList = &(HelperPort->BSSList);

    pMgmtPktHeader = (PDOT11_MGMT_HEADER)MP_RX_MPDU_DATA(pFragment);
    NdisGetCurrentSystemTime((PLARGE_INTEGER)&ullHostTimeStamp);

    //
    // We acquire the write lock as we are adding entries to the list
    //
    MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    do
    {
        //
        // Check again if this entry already exists in the list. This is to handle
        // if the AP was added since we first checked (possible if the
        // flush routine was running)
        //
        pBSSEntry = HelperPortFindBSSEntry(
            pDiscoveredBSSList,
            pMgmtPktHeader->SA
            );

        if (pBSSEntry == NULL)
        {
            bNewAp = TRUE;      // New AP
            //
            // We havent found this AP yet, we would add it to the list
            //
            if (pDiscoveredBSSList->NumOfBSSEntries >= pDiscoveredBSSList->MaxNumOfBSSEntries)
            {
                //
                // We need to replace an entry thats in the list
                //
                pBSSEntry = HelperPortExpireBSSEntry(
                    pDiscoveredBSSList,
                    HelperPort->RegInfo->BSSEntryExpireTime,
                    ullHostTimeStamp
                    );

                if (pBSSEntry != NULL)
                {
                    //
                    // Add initial in-use refcount
                    //
                    pBSSEntry->RefCount = 1;
                }
                
                //
                // Dont zero out the AP entry so that we can
                // reuse the info element blob
                //
            }
            else
            {
                //
                // Create a new entry for this AP
                //
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle, 
                    &pBSSEntry, 
                    sizeof(MP_BSS_ENTRY), 
                    PORT_MEMORY_TAG
                    );
                if (pBSSEntry != NULL)
                {
                    //
                    // Initialize the new entry
                    //
                    NdisZeroMemory(pBSSEntry, sizeof(MP_BSS_ENTRY));
                    
                    pBSSEntry->RefCount = 1; // Add initial in-use refcount
                    NdisAllocateSpinLock(&(pBSSEntry->Lock));
                }
            }

            if (pBSSEntry == NULL)
            {
                MpTrace(COMP_SCAN, DBG_SERIOUS, ("Not enough space to add AP: %02X-%02X-%02X-%02X-%02X-%02X\n",
                    pMgmtPktHeader->SA[0], pMgmtPktHeader->SA[1], pMgmtPktHeader->SA[2], 
                    pMgmtPktHeader->SA[3], pMgmtPktHeader->SA[4], pMgmtPktHeader->SA[5]));
            
                ndisStatus = NDIS_STATUS_RESOURCES;
                break;
            }

            //
            // This Entry is not yet in the list
            //
            
            // We will be updating the beacon & probe response frames
            pBSSEntry->BeaconFrameSize = 0;
            pBSSEntry->ProbeFrameSize = 0;
            
            pBSSEntry->AssocCost = 0;

            NdisMoveMemory(
                pBSSEntry->Dot11BSSID,
                pMgmtPktHeader->BSSID,
                sizeof(DOT11_MAC_ADDRESS)
                );

            NdisMoveMemory(
                pBSSEntry->MacAddress,
                pMgmtPktHeader->SA,
                sizeof(DOT11_MAC_ADDRESS)
                );
        }

        // Update the information in this BSS entry (either new or reused entry)
        ndisStatus = HelperPortUpdateBSSEntry(
            HelperPort, 
            pBSSEntry, 
            pFragment, 
            pDot11BeaconFrame, 
            BeaconDataLength
            );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            break;
        }

        //
        // Add the new BSS to our list
        //
        if (bNewAp)
        {
            MpTrace(COMP_SCAN, DBG_LOUD, ("AP %02X-%02X-%02X-%02X-%02X-%02X at channel: %d (%d)\n", 
                    pBSSEntry->Dot11BSSID[0], pBSSEntry->Dot11BSSID[1], pBSSEntry->Dot11BSSID[2], 
                    pBSSEntry->Dot11BSSID[3], pBSSEntry->Dot11BSSID[4], pBSSEntry->Dot11BSSID[5],
                    pBSSEntry->Channel, pFragment->Msdu->Channel));

            HelperPortAddBSSEntry(pDiscoveredBSSList, pBSSEntry);
        }

        //
        // Note: If any code is added below here, remember to remove entry
        // from the list
        //
    } while (FALSE);

    MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        // Free the new entry we may have created
        if ((bNewAp) && (pBSSEntry != NULL))
        {
            if (pBSSEntry->pDot11BeaconFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame);
                pBSSEntry->pDot11BeaconFrame = NULL;
                pBSSEntry->BeaconFrameSize = 0;
                pBSSEntry->MaxBeaconFrameSize= 0;
            }

            if (pBSSEntry->pDot11ProbeFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame);
                pBSSEntry->pDot11ProbeFrame = NULL;
                pBSSEntry->ProbeFrameSize = 0;
                pBSSEntry->MaxProbeFrameSize= 0;
            }
                        
            pBSSEntry->pDot11InfoElemBlob = NULL;                
            pBSSEntry->InfoElemBlobSize = 0;
            MP_FREE_MEMORY(pBSSEntry);
        }
    }

    return ndisStatus;
Пример #14
0
NDIS_STATUS
HelperPortInitializeScanContext(
    _In_  PMP_HELPER_PORT         HelperPort
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    NDIS_TIMER_CHARACTERISTICS  timerChar;               
    ULONG                       i;
    do
    {
        HelperPort->ScanContext.ActiveScanParameters = NULL;

        // Allocate the power save timeout call back
        NdisZeroMemory(&timerChar, sizeof(NDIS_TIMER_CHARACTERISTICS));
        
        timerChar.Header.Type = NDIS_OBJECT_TYPE_TIMER_CHARACTERISTICS;
        timerChar.Header.Revision = NDIS_TIMER_CHARACTERISTICS_REVISION_1;
        timerChar.Header.Size = sizeof(NDIS_TIMER_CHARACTERISTICS);
        timerChar.AllocationTag = PORT_MEMORY_TAG;
        
        timerChar.TimerFunction = HelperPortScanTimer;
        timerChar.FunctionContext = HelperPort;

        ndisStatus = NdisAllocateTimerObject(
                        HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle,
                        &timerChar,
                        &HelperPort->ScanContext.Timer_Scan
                        );
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to allocate helper port scan timer\n"));
            break;
        }

        //
        // Get list of channels we would scan
        //
        ndisStatus = HelperPortCreateScanChannelList(HelperPort);
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Failed to create helper port scan list\n"));
            break;
        }        

        // Initialize the preallocated scan parameter structures
        for (i = 0; i < MP_MAX_NUMBER_OF_PORT; i++)
        {
            NdisZeroMemory(&HelperPort->ScanContext.ScanParameters[i], sizeof(MP_SCAN_PARAMETERS));
            
            HelperPort->ScanContext.ScanParameters[i].State = SCAN_EMPTY_REQUEST;
            HelperPort->ScanContext.ScanParameters[i].UsageCount = 0;
        }

        // To maintain the scan list, we need to receive all beacons and probe responses. Set the
        // appropriate packet filter
        VNic11SetPacketFilter(HELPPORT_GET_VNIC(HelperPort), 
            NDIS_PACKET_TYPE_802_11_BROADCAST_MGMT | NDIS_PACKET_TYPE_802_11_DIRECTED_MGMT
            );
        
    }while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        if (HelperPort->ScanContext.Timer_Scan)
        {
            NdisFreeTimerObject(HelperPort->ScanContext.Timer_Scan);
            HelperPort->ScanContext.Timer_Scan = NULL;
        }
    
        for (i = 0; i < HW11_MAX_PHY_COUNT; i++)
        {
            if (HelperPort->ScanContext.ScanChannels[i].ChannelList != NULL)
            {
                MP_FREE_MEMORY(HelperPort->ScanContext.ScanChannels[i].ChannelList);
                HelperPort->ScanContext.ScanChannels[i].ChannelList = NULL;
            }
        }

    }
    
    return ndisStatus;
}
Пример #15
0
NDIS_STATUS
HelperPortCreateScanChannelList(
    _In_  PMP_HELPER_PORT         HelperPort
    )
{
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    ULONG                       phyId, channelListIndex = 0;
    PDOT11_SUPPORTED_PHY_TYPES  supportedPhyTypes;
    UCHAR                       buffer[(sizeof(DOT11_SUPPORTED_PHY_TYPES) + 
                                    sizeof(DOT11_PHY_TYPE) * HW11_MAX_PHY_COUNT)];  
    PMP_SCAN_CHANNEL_LIST       currentChannelList;
    DOT11_PHY_TYPE              bgScanPhy;

    do
    {
        //
        // Get supported PHY types.
        //
        supportedPhyTypes = (PDOT11_SUPPORTED_PHY_TYPES) buffer;
        supportedPhyTypes->uNumOfEntries = 0;
        VNic11QuerySupportedPHYTypes(HELPPORT_GET_VNIC(HelperPort), 
            HW11_MAX_PHY_COUNT, 
            supportedPhyTypes
            );

        //
        // For devices supporting both b & g phys, we only scan on g. Check if
        // we need to do this here
        //
        bgScanPhy = dot11_phy_type_hrdsss;
        for (phyId = 0; phyId < supportedPhyTypes->uNumOfEntries; phyId++)
        {
            if (supportedPhyTypes->dot11PHYType[phyId] == dot11_phy_type_erp)
            {
                // Support g, no need to scan b
                bgScanPhy = dot11_phy_type_erp;
                break;
            }
        }        

        //
        // Go through the list to see if there is a phy type we scan for
        //
        for (phyId = 0; phyId < supportedPhyTypes->uNumOfEntries; phyId++)
        {
            // We only scan on g(or b) & a phy
            if ((supportedPhyTypes->dot11PHYType[phyId] == bgScanPhy) ||
                (supportedPhyTypes->dot11PHYType[phyId] == dot11_phy_type_ofdm))
            {
                // Query for the channel list
                currentChannelList = &HelperPort->ScanContext.ScanChannels[channelListIndex];

                // Start with a zero length buffer to determine the size
                currentChannelList->ChannelCount = 0;
                ndisStatus = VNic11QuerySupportedChannels(HELPPORT_GET_VNIC(HelperPort), 
                                    phyId,
                                    &currentChannelList->ChannelCount, 
                                    NULL
                                    );
                if (ndisStatus != NDIS_STATUS_BUFFER_TOO_SHORT)
                {
                    MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to query size of the channel list for phy ID %d\n", phyId));    
                    // We skip this PHY
                    ndisStatus = NDIS_STATUS_SUCCESS;
                    break;
                }
                
                MP_ALLOCATE_MEMORY(HELPPORT_GET_MP_PORT(HelperPort)->MiniportAdapterHandle,
                    &currentChannelList->ChannelList,
                    currentChannelList->ChannelCount * sizeof(ULONG),
                    PORT_MEMORY_TAG
                    );
                if (currentChannelList->ChannelList == NULL)
                {
                    MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to allocate memory for the channel list for phy ID %d\n", phyId));
                    ndisStatus = NDIS_STATUS_RESOURCES;
                    break;
                }

                // Query again
                ndisStatus = VNic11QuerySupportedChannels(HELPPORT_GET_VNIC(HelperPort), 
                                    phyId,
                                    &currentChannelList->ChannelCount, 
                                    currentChannelList->ChannelList
                                    );
                if (ndisStatus != NDIS_STATUS_SUCCESS)
                {
                    MpTrace(COMP_INIT_PNP, DBG_SERIOUS, ("Unable to query channel list for phy ID %d\n", phyId));
                    break;
                }

                currentChannelList->PhyId = phyId;
                
                // Populated one set of channels
                channelListIndex++;
            }

            if (ndisStatus != NDIS_STATUS_SUCCESS)
            {
                break;
            }
        }
    } while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        for (channelListIndex = 0; channelListIndex < HW11_MAX_PHY_COUNT; channelListIndex++)
        {
            if (HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList != NULL)
            {
                MP_FREE_MEMORY(HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList);
                HelperPort->ScanContext.ScanChannels[channelListIndex].ChannelList = NULL;
            }
        }
    }

    return ndisStatus;
}
Пример #16
0
NDIS_STATUS
StaCreateAssociateRequestPacket(
                               __in  PSTATION        pStation,
                               __in  PSTA_BSS_ENTRY  pAPEntry,
                               __deref_out_opt PUCHAR*         ppAssocPacket,
                               __out PUSHORT         pAssocPacketLength
                               )
{
    PDOT11_MGMT_HEADER  pMgmtMacHeader = NULL;
    PDOT11_ASSOC_REQUEST_FRAME   pDot11AssocRequest = NULL;
    USHORT              IESize;
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PUCHAR              pCurrentIE = NULL;
    DOT11_RATE_SET      RateSet;
    BOOLEAN             set;
    PNIC                pNic = pStation->pNic;

    IESize = STA11_MAX_IE_BLOB_SIZE;                    // SSID + Rates IE
    *pAssocPacketLength = sizeof(DOT11_MGMT_HEADER) + 
                          sizeof(DOT11_ASSOC_REQUEST_FRAME) +
                          IESize;

    MP_ALLOCATE_MEMORY(pStation->MiniportAdapterHandle, ppAssocPacket, *pAssocPacketLength, STA11_MEMORY_TAG);
    if (*ppAssocPacket == NULL) {
        MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to allocate association request packet\n"));
        return NDIS_STATUS_RESOURCES;
    }
    NdisZeroMemory(*ppAssocPacket, *pAssocPacketLength);    

    pMgmtMacHeader = (PDOT11_MGMT_HEADER)*ppAssocPacket;

    //
    // Fill the MAC header
    //
    pMgmtMacHeader->FrameControl.Version = 0x0;
    pMgmtMacHeader->FrameControl.Type = DOT11_FRAME_TYPE_MANAGEMENT;
    pMgmtMacHeader->FrameControl.Subtype = DOT11_MGMT_SUBTYPE_ASSOCIATION_REQUEST;
    pMgmtMacHeader->FrameControl.ToDS = 0x0;      // Default value for Mgmt frames
    pMgmtMacHeader->FrameControl.FromDS = 0x0;    // Default value for Mgmt frames
    pMgmtMacHeader->FrameControl.MoreFrag = 0x0;  
    pMgmtMacHeader->FrameControl.Retry = 0x0;
    pMgmtMacHeader->FrameControl.PwrMgt = 0x0;
    pMgmtMacHeader->FrameControl.MoreData = 0x0;
    pMgmtMacHeader->FrameControl.WEP = 0x0;       // no WEP
    pMgmtMacHeader->FrameControl.Order = 0x0;     // no order

    memcpy(pMgmtMacHeader->DA, 
           pAPEntry->MacAddress,
           DOT11_ADDRESS_SIZE
          );

    memcpy(pMgmtMacHeader->SA, 
           Hw11GetMACAddress(pNic),
           DOT11_ADDRESS_SIZE
          );

    memcpy(pMgmtMacHeader->BSSID,
           pAPEntry->Dot11BSSID,
           DOT11_ADDRESS_SIZE
          );

    pDot11AssocRequest = (PDOT11_ASSOC_REQUEST_FRAME)((*ppAssocPacket) + sizeof(DOT11_MGMT_HEADER));

    do {
        //
        // Capabilities
        //
        NdisZeroMemory(&(pDot11AssocRequest->Capability), sizeof(DOT11_CAPABILITY));

        pDot11AssocRequest->Capability.ESS = 1;
        pDot11AssocRequest->Capability.IBSS = 0;
        pDot11AssocRequest->Capability.CFPollable = (Hw11QueryCFPollable(pNic) ? 1 : 0);
        pDot11AssocRequest->Capability.CFPollRequest = 0;

        pDot11AssocRequest->Capability.Privacy = 
        (pStation->Config.UnicastCipherAlgorithm != DOT11_CIPHER_ALGO_NONE) ? 1 : 0;

        switch (Hw11QueryCurrentPhyType(pNic)) {
            case dot11_phy_type_erp:
                Hw11QueryShortSlotTimeOptionImplemented(pNic, &set, FALSE);
                if (set) {
                    Hw11QueryShortSlotTimeOptionEnabled(pNic, &set, FALSE);
                }
                pDot11AssocRequest->Capability.ShortSlotTime = set ? 1 : 0;

                Hw11QueryDsssOfdmOptionImplemented(pNic, &set, FALSE);
                if (set) {
                    Hw11QueryDsssOfdmOptionEnabled(pNic, &set, FALSE);
                }
                pDot11AssocRequest->Capability.DSSSOFDM = set ? 1 : 0;

                // fall through

            case dot11_phy_type_hrdsss:
                // Enable/verify short preamble
                Hw11QueryShortPreambleOptionImplemented(pNic, &set, FALSE);
                pDot11AssocRequest->Capability.ShortPreamble = set ? 1: 0;

                Hw11QueryPbccOptionImplemented(pNic, &set, FALSE);
                pDot11AssocRequest->Capability.PBCC = set ? 1: 0;

                Hw11QueryChannelAgilityPresent(pNic, &set, FALSE);
                if (set) {
                    Hw11QueryChannelAgilityEnabled(pNic, &set, FALSE);
                }
                pDot11AssocRequest->Capability.ChannelAgility = set ? 1 : 0;
        }

        pDot11AssocRequest->usListenInterval = pStation->Config.ListenInterval;

        pCurrentIE = ((PUCHAR)pDot11AssocRequest) + sizeof(DOT11_ASSOC_REQUEST_FRAME);

        //
        // Fill the SSID
        //
        ndisStatus = Dot11AttachElement(
                                       &pCurrentIE,
                                       &IESize,
                                       DOT11_INFO_ELEMENT_ID_SSID,
                                       (UCHAR)pStation->Config.SSID.uSSIDLength,
                                       pStation->Config.SSID.ucSSID
                                       );
        if (ndisStatus != NDIS_STATUS_SUCCESS) {
            MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to populate SSID in association request\n"));
            break;
        }

        //
        // Fill the supported rates
        //
        Hw11QueryOperationalRateSet(pNic, &RateSet, FALSE);
        StaFilterUnsupportedRates(pAPEntry, &RateSet);

        ndisStatus = Dot11AttachElement(
                                       &pCurrentIE,
                                       &IESize,
                                       DOT11_INFO_ELEMENT_ID_SUPPORTED_RATES,
                                       (UCHAR)((RateSet.uRateSetLength > 8) ? 8 : RateSet.uRateSetLength),
                                       RateSet.ucRateSet
                                       );
        if (ndisStatus != NDIS_STATUS_SUCCESS) {
            MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to populate supported rates in association request\n"));
            break;
        }

        //
        // Add the extended rate set if needed
        //
        if (RateSet.uRateSetLength > (UCHAR)8) {
            ndisStatus = Dot11AttachElement(
                                           &pCurrentIE,
                                           &IESize,
                                           DOT11_INFO_ELEMENT_ID_EXTD_SUPPORTED_RATES,
                                           (UCHAR)(RateSet.uRateSetLength - 8),
                                           (RateSet.ucRateSet + 8)
                                           );
            if (ndisStatus != NDIS_STATUS_SUCCESS) {
                MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to add extended rates in association request\n"));
                break;
            }
        }

        //
        // RSNA/WPA IE
        //
        if (pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_RSNA ||
            pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_RSNA_PSK ||
            pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_WPA ||
            pStation->Config.AuthAlgorithm == DOT11_AUTH_ALGO_WPA_PSK) {
            ndisStatus = StaAttachInfraRSNIE(pStation, 
                                             pAPEntry, 
                                             &pCurrentIE,
                                             &IESize);
            if (ndisStatus != NDIS_STATUS_SUCCESS) {
                MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to add RSN IE in association request\n"));
                break;
            }
        }

        //
        // Adjust packet length for IE space we did not use. Eg. if the SSID is not 32 bytes long, 
        // we have empty space here that we dont want send out in the packet. 
        //
        *pAssocPacketLength = *pAssocPacketLength - IESize;


    } while (FALSE);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        MP_FREE_MEMORY(*ppAssocPacket);
        *ppAssocPacket = NULL;
    }
    
    return ndisStatus;
}
Пример #17
0
NDIS_STATUS
StaSendDisassociation(
                     __in  PSTATION        pStation,
                     __in  PSTA_BSS_ENTRY  pAPEntry,
                     __in  USHORT          ReasonCode
                     )
{
    PDOT11_MGMT_HEADER  pMgmtMacHeader = NULL;
    PDOT11_DISASSOC_FRAME   pDot11DisassocFrame = NULL;
    NDIS_STATUS         ndisStatus = NDIS_STATUS_SUCCESS;
    PUCHAR              pPacketBuffer = NULL;
    USHORT              PacketSize;

    MpEntry;

    PacketSize = sizeof(DOT11_MGMT_HEADER) + sizeof(DOT11_DISASSOC_FRAME);

    MP_ALLOCATE_MEMORY(pStation->MiniportAdapterHandle, &pPacketBuffer, PacketSize, STA11_MEMORY_TAG);
    if (pPacketBuffer == NULL) {
        MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to allocate disassociation request packet\n"));
        return NDIS_STATUS_RESOURCES;
    }
    NdisZeroMemory(pPacketBuffer, PacketSize);        

    pMgmtMacHeader = (PDOT11_MGMT_HEADER)pPacketBuffer;

    //
    // Fill the MAC header
    //
    pMgmtMacHeader->FrameControl.Version = 0x0;
    pMgmtMacHeader->FrameControl.Type = DOT11_FRAME_TYPE_MANAGEMENT;
    pMgmtMacHeader->FrameControl.Subtype = DOT11_MGMT_SUBTYPE_DISASSOCIATION;
    pMgmtMacHeader->FrameControl.ToDS = 0x0;      // Default value for Mgmt frames
    pMgmtMacHeader->FrameControl.FromDS = 0x0;    // Default value for Mgmt frames
    pMgmtMacHeader->FrameControl.MoreFrag = 0x0;  
    pMgmtMacHeader->FrameControl.Retry = 0x0;
    pMgmtMacHeader->FrameControl.PwrMgt = 0x0;
    pMgmtMacHeader->FrameControl.MoreData = 0x0;
    pMgmtMacHeader->FrameControl.WEP = 0x0;       // no WEP
    pMgmtMacHeader->FrameControl.Order = 0x0;     // no order

    memcpy(pMgmtMacHeader->DA, 
           pAPEntry->MacAddress,
           DOT11_ADDRESS_SIZE
          );

    memcpy(pMgmtMacHeader->SA, 
           Hw11GetMACAddress(pStation->pNic),
           DOT11_ADDRESS_SIZE
          );

    memcpy(pMgmtMacHeader->BSSID,
           pAPEntry->Dot11BSSID,
           DOT11_ADDRESS_SIZE
          );

    pDot11DisassocFrame = (PDOT11_DISASSOC_FRAME)(pPacketBuffer + sizeof(DOT11_MGMT_HEADER));
    pDot11DisassocFrame->usReasonCode = ReasonCode;

    //
    // Send the disassociation request packet
    ndisStatus = Hw11SendMgmtPacket(
                                   pStation->pNic,
                                   pAPEntry,
                                   pPacketBuffer,
                                   PacketSize
                                   );
    if (ndisStatus != NDIS_STATUS_SUCCESS) {
        MpTrace(COMP_ASSOC, DBG_SERIOUS, ("Unable to send disassociation packet\n"));
    }

    // Send Mgmt Packet cannot pend
    MPVERIFY(ndisStatus != NDIS_STATUS_PENDING);

    if (pPacketBuffer) {
        MP_FREE_MEMORY(pPacketBuffer);
    }

    return ndisStatus;
}
Пример #18
0
NDIS_STATUS
HelperPortFlushBSSList(
    __in PMP_PORT                 Port
    )
{
    MP_RW_LOCK_STATE          LockState;
    PLIST_ENTRY         pListEntry;
    PMP_BSS_ENTRY      pBSSEntry = NULL;
    LONG                APRefCount;
    LIST_ENTRY          TempList;
    PMP_HELPER_PORT     HelperPort = MP_GET_HELPPORT(Port);
    PMP_BSS_LIST       pDiscoveredBSSList = &(HelperPort->BSSList);

    //
    // Entries that are currently in use (eg for connection)
    // we cannot flush and instead would put in the temporary queue
    //
    InitializeListHead(&TempList);
    
    MP_ACQUIRE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);
        
    while (!IsListEmpty(&(pDiscoveredBSSList->List)))
    {
        pListEntry = RemoveHeadList(&(pDiscoveredBSSList->List));
        pBSSEntry = CONTAINING_RECORD(pListEntry, MP_BSS_ENTRY, Link);

        APRefCount = NdisInterlockedDecrement(&(pBSSEntry->RefCount));
        if (APRefCount == 0)
        {        
            NdisAcquireSpinLock(&(pBSSEntry->Lock));
            MPASSERT(pBSSEntry->pAssocRequest == NULL);
            MPASSERT(pBSSEntry->pAssocResponse == NULL);
            
            if (pBSSEntry->pDot11BeaconFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11BeaconFrame);
                pBSSEntry->pDot11BeaconFrame = NULL;
                pBSSEntry->BeaconFrameSize = 0;
                pBSSEntry->MaxBeaconFrameSize= 0;
            }

            if (pBSSEntry->pDot11ProbeFrame != NULL)
            {
                MP_FREE_MEMORY(pBSSEntry->pDot11ProbeFrame);
                pBSSEntry->pDot11ProbeFrame = NULL;
                pBSSEntry->ProbeFrameSize = 0;
                pBSSEntry->MaxProbeFrameSize= 0;
            }
            
            pBSSEntry->pDot11InfoElemBlob = NULL;
            pBSSEntry->InfoElemBlobSize = 0;            
            NdisReleaseSpinLock(&(pBSSEntry->Lock));
            
            MP_FREE_MEMORY(pBSSEntry);        
        }
        else
        {
            // Restore refcount and save for adding back to list
            NdisInterlockedIncrement(&(pBSSEntry->RefCount));
            InsertTailList(&TempList, pListEntry);
        }
    }
    pDiscoveredBSSList->NumOfBSSEntries = 0;

    //
    // Restore entries that are in use
    //
    while (!IsListEmpty(&TempList))
    {
        pListEntry = RemoveHeadList(&TempList);

        InsertTailList(&(pDiscoveredBSSList->List), pListEntry);
        pDiscoveredBSSList->NumOfBSSEntries++;
    }

    // Since our scan list is flushed, also clear the last scan time
    HelperPort->ScanContext.LastScanTime = 0;
    
    MP_RELEASE_WRITE_LOCK(&(HelperPort->BSSList.ListLock), &LockState);

    return NDIS_STATUS_SUCCESS;