private void TranslateEncryptionKey(ref WLANConfiguration config, string key, AuthenticationMode authMode, WEPStatus privacyMode)
        {
            if (privacyMode == WEPStatus.WEPEnabled)
            {
                if ((key.Length != 10) && (key.Length != 26))
                {
                    throw new ArgumentException("The encryption key for WEP must be either 10 or 26 characters");
                }

                byte[] keyMaterial = HexStringToBytes(key);
                config.KeyMaterial = keyMaterial;

                config.CtlFlags |= WZCControl.WEPKPresent | WZCControl.WEPKXFormat;
                if (key.Length == 10)
                {
                    config.CtlFlags |= WZCControl.WEPK40Bit;
                }

                config.KeyMaterial = EncryptKeyMaterial(keyMaterial);
            }
            else if ((privacyMode == WEPStatus.AESEnabled) || (privacyMode == WEPStatus.TKIPEnabled))
            {
                config.KeyLength = key.Length;
                if ((config.KeyLength < 8) || (config.KeyLength > 63))
                {
                    throw new ArgumentException("The encryption key for WPA-PSK/TKIP must be either between 8 and 63");
                }
                WZC.WZCPassword2Key(ref config, key);

                config.CtlFlags      |= WZCControl.WEPKPresent | WZCControl.WEPKXFormat | WZCControl.ONEXEnabled;
                config.WPAMCastCipher = (int)WEPStatus.TKIPEnabled;

                config.KeyMaterial = EncryptKeyMaterial(config.KeyMaterial);
            }
        }
예제 #2
0
        WZCPassword2Key(
            ref WLANConfiguration pwzcConfig,
            string cszPassword)
        {
            // Convert string from Unicode to Ascii.
            byte[] ascii = new byte[64];
            byte[] src   = Encoding.ASCII.GetBytes(cszPassword);
            Buffer.BlockCopy(src, 0, ascii, 0, src.Length);

            // Pass Ascii string and configuration structure
            // to the external call.
            WZCPassword2KeyCE(pwzcConfig.Data, ascii);
        }
예제 #3
0
        internal AccessPoint(WLANConfiguration config)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            Name               = config.SSID;
            macaddr            = config.MACAddress;
            Privacy            = config.Privacy;
            AuthenticationMode = config.AuthenticationMode;

            // jsm - Defect 352: Exposed keyIndex, keyMaterial, and EapolParams
            KeyIndex    = config.KeyIndex;
            KeyMaterial = config.KeyMaterial;
            EapolParams = config.EapolParams;

            Channel = config.Configuration.Frequency;
            if (Channel > 14)
            {
                Channel = (config.Configuration.Frequency - 2407000) / 5000;
            }
            if (Channel < 0)
            {
                Channel = (int)((config.Configuration.Frequency - 2407) / 5);
            }

            // see if the rssi is in the HIWORD or LOWORD
            uint ssi = (uint)config.Rssi;

            if (((ssi & 0xFFFF0000) > 0) && ((ssi & 0xffff) == 0))
            {
                // hiword
                SignalStrengthInDecibels = config.Rssi >> 16;
            }
            else if (ssi == 0)
            {
                SignalStrengthInDecibels = -99;
            }
            else
            {
                // loword
                SignalStrengthInDecibels = config.Rssi;
            }

            supportedrates     = config.Rates;
            NetworkTypeInUse   = config.NetworkTypeInUse;
            InfrastructureMode = config.InfrastructureMode;
        }
예제 #4
0
        public WLANConfiguration Item(int index)
        {
            int offset      = ConfigOffset;
            int currentSize = 0;

            // don't assume every element is equal size
            for (int i = 0; i <= index; i++)
            {
                currentSize = BitConverter.ToInt32(m_data.lpData, ConfigOffset);
                offset     += currentSize;
            }

            WLANConfiguration config = new WLANConfiguration(currentSize);
            //jsm Bug 148 - BlockCopy was referencing data beyond data.lpData and causing ArgumentOutOfBounds Exception
            int bytesToCopyA = m_data.lpData.Length - (offset - currentSize);   //this is the most we'll ever take
            int bytesToCopyB = bytesToCopyA <= currentSize ? bytesToCopyA : currentSize;

            Buffer.BlockCopy(m_data.lpData, offset - currentSize, config.Data, 0, bytesToCopyB);
            //Buffer.BlockCopy(data.lpData, offset - currentSize, config.Data, 0, currentSize);
            return(config);
        }
        private WLANConfiguration MakeSSIDEntry(string SSID, bool bInfrastructure, string authKey, int keyIndex, AuthenticationMode authMode, WEPStatus privacyMode, EAPParameters eap)
        {
            WLANConfiguration config = new WLANConfiguration();

            if (eap == null)
            {
                // setup default based on mode
                eap = new EAPParameters();
                if (privacyMode == WEPStatus.WEPEnabled)
                {
                    eap.EapFlags = EAPFlags.Disabled;
                }
                else if ((privacyMode == WEPStatus.AESEnabled) || (privacyMode == WEPStatus.TKIPEnabled))
                {
                    eap.EapType     = EAPType.Default;
                    eap.EapFlags    = EAPFlags.Enabled;
                    eap.Enable8021x = true;
                    eap.AuthData    = IntPtr.Zero;
                    eap.AuthDataLen = 0;
                }
            }

            config.EapolParams        = eap;
            config.MACAddress         = this.GetPhysicalAddress().GetAddressBytes();
            config.SSID               = SSID;
            config.KeyIndex           = keyIndex - 1; // WZC is 0-based, but wireless specs are 1-based
            config.InfrastructureMode = bInfrastructure ? InfrastructureMode.Infrastructure : InfrastructureMode.AdHoc;
            config.AuthenticationMode = authMode;
            config.Privacy            = privacyMode;

            // translate key string into encrypted version
            if (authKey != null)
            {
                if (string.Compare(authKey, "auto", true) != 0)
                {
                    TranslateEncryptionKey(ref config, authKey, authMode, privacyMode);
                }
            }
            return(config);
        }
예제 #6
0
        public void SetItem(int index, WLANConfiguration wlc)
        {
            // Make sure data array is large enough to get element size.
            if ((ConfigOffset + sizeof(int)) <= m_data.lpData.Length)
            {
                // Figure out how big each element in the array
                // is.
                int elemSize = BitConverter.ToInt32(m_data.lpData, ConfigOffset);

                if (elemSize > wlc.Data.Length)
                {
                    elemSize = wlc.Data.Length;
                }
                // Use the actual index to get the indicated element
                // in the Config list.  Note that we use lpDataDirect,
                // so that we're copying to the internal array of our
                // data, not cloning it first, then copying to the clone
                // (which, of course, has no effect).
                Marshal.Copy(wlc.Data, 0,
                             (IntPtr)((uint)(m_data.lpDataDirect) + ConfigOffset + index * (int)elemSize),
                             elemSize);
            }
        }
        /// <summary>
        /// Removes a network from the adapter's preferred list
        /// </summary>
        /// <param name="SSID">The SSID of the network to remove</param>
        public bool RemovePreferredNetwork(string SSID)
        {
            if ((SSID == null) || (SSID == string.Empty))
            {
                throw new ArgumentException("Invalid SSID");
            }

            // Get the current preferred list of SSID values.
            // First, we need to get an INTF_ENTRY for this adapter.
            INTF_ENTRY entry;
            int        uret = WZC.QueryAdapter(this.Name, out entry);

            try
            {
                if (uret > 0)
                {
                    // There is no list.  Return false.
                    return(false);
                }

                // Find the indicated item and remove it from
                // the list by creating a new list and setting
                // that as the preferred list.
                RAW_DATA rdold = entry.rdStSSIDList;
                WLANConfigurationList prefl = new WLANConfigurationList(rdold);

                // If there are no items in the list, return false.
                if (prefl.NumberOfItems == 0)
                {
                    return(false);
                }

                // Build the new list.
                WLANConfigurationList prefnew = new WLANConfigurationList(prefl.NumberOfItems - 1);

                // Start at the top of the old list and copy items
                // from old to new, until we find the item to be
                // removed.
                int j = 0;
                int i;
                for (i = 0; i < prefl.NumberOfItems; i++)
                {
                    WLANConfiguration item = prefl.Item(i);

                    if (item.SSID == SSID)
                    {
                        // Skip to next item without incrementing
                        // j.
                    }
                    else
                    {
                        prefnew.SetItem(j, item);
                        j++;
                    }
                }

                // Check for whether the item was found in the
                // list or not.  If not, we don't reset the
                // wireless settings and instead return false.
                if (j == i)
                {
                    return(false);
                }

                // Replace the old list with the new one
                // for the rest of the code.  Entry #0
                // is unset.
                prefl = prefnew;

                // Must now copy the new preferred list to the entry that
                // we will send with WZCSetInterface.
                entry.rdStSSIDList = prefl.rawData;

                // Finally, we are ready to select the new SSID as our
                // primary preferred connection.
                uret = WZC.SetAdapter(entry, INTF_FLAGS.INTF_ALL_FLAGS | INTF_FLAGS.INTF_PREFLIST);

                if (uret != 0)
                {
                    throw new System.ComponentModel.Win32Exception(uret, "Unable to Set WZC Interface");
                }
            }
            finally
            {
                entry.Dispose();
            }
            return(uret <= 0);
        }
        /// <summary>
        /// Sets wireless settings associated with a given interface and AP, adding to, rather than replacing the preferred list of APs.  This version of the
        /// method is designed for the case where *all* of  the options are going to be set, where no initial  configuration exists at all and where existing
        /// items in the preferred list should be maintained. After this method executes, if it is successful, the specified SSID will be at the top, highest-
        /// priority, end of the preferred list.
        /// </summary>
        /// <param name="SSID">
        /// Target SSID to connect
        /// </param>
        /// <param name="infrastructureMode">
        /// Is infrastructure
        /// </param>
        /// <param name="authKey">
        /// WEP key or WPA shared key string representing hex string (each two characters are converted to a single byte)
        /// </param>
        /// <param name="keyIndex">
        /// Index of the WEP key.  Valid values are 1-4
        /// </param>
        /// <param name="authMode">
        /// Authentication mode for the connection
        /// </param>
        /// <param name="privacyMode">
        /// Privacy (encryption) mode for the connection
        /// </param>
        /// <param name="eapParams">
        /// Parameters describing how the connection should use EAP to authenticate the user to the network
        /// </param>
        /// <returns>true if succeeded</returns>
        #endregion
        public bool AddPreferredNetwork(string SSID,
                                        bool infrastructureMode,
                                        string authKey,
                                        int keyIndex,
                                        AuthenticationMode authMode,
                                        WEPStatus privacyMode,
                                        EAPParameters eapParams)
        {
            if ((keyIndex <= 0) || (keyIndex > 4))
            {
                throw new ArgumentException("Invalid keyIndex (must be between 1 and 4)");
            }
            if ((SSID == null) || (SSID == string.Empty))
            {
                throw new ArgumentException("Invalid SSID");
            }

            // We may yet need to do some processing on the key,
            // if it is a WPA key.  We need a WZC_WLAN_CONFIG
            // structure to pass to the WZC routine that does
            // this processing, however, so that is done below.

            // Get the current preferred list of SSID values.
            // First, we need to get an INTF_ENTRY for this adapter.
            INTF_ENTRY entry;
            int        uret = WZC.QueryAdapter(this.Name, out entry);

            try
            {
                if (uret != 0)
                {
                    throw new System.ComponentModel.Win32Exception(uret, "No preferred list found");
                }

                // We need to push the indicated item to the top of the
                // preferred list.  Once we do that and call WZCSetInterface
                // the connection will be established to that SSID.
                // The preferred list is in the rdStSSIDList field.
                RAW_DATA rdold = entry.rdStSSIDList;
                WLANConfigurationList prefl = new WLANConfigurationList(rdold);

                // Start at the bottom of the list.  If the current item
                // is the one we want to copy, save it and start copying
                // items down in the list.
                WLANConfiguration targetItem = null;
                int i;
                for (i = (int)prefl.NumberOfItems - 1; i >= 0; i--)
                {
                    targetItem = prefl.Item(i);
                    if (targetItem.SSID == SSID)
                    {
                        break;
                    }
                }

                // If we get no match for our SSID value, the item
                // is *not* in the preferred list, so we can
                // skip removing it.
                if (i >= 0)
                {
                    // Now, copy the items before i on the
                    // list down to cover i.  This leaves
                    // position 0 in the list as a copy of
                    // position 1.  We'll fill in position 0
                    // with the new most-preferred SSID.
                    for (int j = i; j >= 1; j--)
                    {
                        // Copy old list item j-1 to new list item j.
                        prefl.SetItem(j, prefl.Item(j - 1));
                    }
                }
                else
                {
                    // The item was not in the list.  We have
                    // to expand the list and move all of
                    // the original items down one spot.
                    WLANConfigurationList prefl2 = new WLANConfigurationList(prefl.NumberOfItems + 1);
                    for (int j = 0; j < (int)prefl.NumberOfItems; j++)
                    {
                        // Copy from old list to new list.
                        prefl2.SetItem(j + 1, prefl.Item(j));
                    }

                    // Replace the old list with the new one
                    // for the rest of the code.  Entry #0
                    // is unset.
                    prefl = prefl2;
                }

                // Create a new item and put that in the list
                // at item #0, which presently exists but
                // doesn't mean anything (it's either a
                // totally blank item, if the SSID was not
                // in the list before the call, or it's the
                // old first item in the list).

                // Unlike the other SetWirelessSettings versions,
                // we *don't* get the current configuration here;
                // our parameters will set that.
                WLANConfiguration thisConfig = MakeSSIDEntry(SSID, infrastructureMode, authKey, keyIndex, authMode, privacyMode, eapParams);

                // OK, finally, set the item in the preferred
                // list according to the parameters to this
                // call.
                prefl.SetItem(0, thisConfig);

                // Must now copy the new preferred list to the entry that
                // we will sent with WZCSetInterface.
                entry.rdStSSIDList = prefl.rawData;

                // Finally, we are ready to select the new SSID as our
                // primary preferred connection.
                uret = WZC.SetAdapter(entry, INTF_FLAGS.INTF_PREFLIST);
                if (uret != 0)
                {
                    throw new System.ComponentModel.Win32Exception(uret, "Unable to Set WZC Interface");
                }
            }
            finally
            {
                entry.Dispose();
            }

            return(true);
        }
        /// <summary>
        /// Connects to an already-configured wireless network by SSID
        /// </summary>
        /// <param name="SSID"></param>
        /// <returns></returns>
        public bool ConnectToPreferredNetwork(string SSID)
        {
            INTF_ENTRY entry;
            int        uret = WZC.QueryAdapter(this.Name, out entry);

            try
            {
                if (uret != 0)
                {
                    throw new System.ComponentModel.Win32Exception(uret, "Unable to Query WZC Interface");
                }

                // We need to push the indicated item to the top of the
                // preferred list.  Once we do that and call WZCSetInterface
                // the connection will be established to that SSID.
                // The preferred list is in the rdStSSIDList field.
                RAW_DATA rdold = entry.rdStSSIDList;
                WLANConfigurationList prefl = new WLANConfigurationList(rdold);

                // Start at the bottom of the list.  If the current item
                // is the one we want to copy, save it and start copying
                // items down in the list.
                WLANConfiguration targetItem = null;
                int i;
                for (i = (int)prefl.NumberOfItems - 1; i >= 0; i--)
                {
                    targetItem = prefl.Item(i);
                    if (targetItem.SSID == SSID)
                    {
                        break;
                    }
                }

                // If we get no match for our SSID value, the item is *not*
                // in the preferred list.  Return false.
                if (targetItem == null)
                {
                    return(false);
                }

                // If the SSID is already first in the list, we're done.
                if (i > 0)
                {
                    // Now, copy the rest of the items one place down in the
                    // list.
                    for (int j = i; j >= 1; j--)
                    {
                        // Copy old list item j-1 to new list item j.
                        prefl.SetItem(j, prefl.Item(j - 1));
                    }

                    // Put the saved target item in index 0 in the new list.
                    prefl.SetItem(0, targetItem);
                }

                uret = WZC.SetAdapter(entry, INTF_FLAGS.INTF_ALL_FLAGS | INTF_FLAGS.INTF_PREFLIST);
                if (uret != 0)
                {
                    throw new System.ComponentModel.Win32Exception(uret, "Unable to Set WZC Interface");
                }
            }
            finally
            {
                entry.Dispose();
            }
            return(true);
        }
        /// <summary>
        /// The ProcessKey routine makes necessary modifications
        /// to the key material of a WPA key before it is passed
        /// to WZC routines.  The processing done to it depends
        /// on how it was generated.
        /// </summary>
        /// <param name="kt">
        /// The key type, indicating how the key material in
        /// the structure was originally generated
        /// </param>
        /// <param name="config">
        /// The configuration being changed
        /// </param>
        /// <param name="passphrase">
        /// For WPA-PSK passphrase type, the passphrase.
        /// </param>
        internal void ProcessKey(KeyType kt, ref WLANConfiguration config,
                                 string passphrase)
        {
            // Define fake key material for 'encrypting' the
            // keys.
            byte[] chFakeKeyMaterial = new byte[] { 0x56, 0x09, 0x08, 0x98, 0x4D, 0x08, 0x11, 0x66, 0x42, 0x03, 0x01, 0x67, 0x66 };
            byte[] key;
            uint   i;

            switch (kt)
            {
            case KeyType.WPAPassphrase:
                // We set this explicitly here.  It was set
                // out of line in the NetUI code.
                config.Privacy = WEPStatus.TKIPEnabled;

                config.KeyLength = WLANConfiguration.WZCCTL_MAX_WEPK_MATERIAL;
                config.CtlFlags |= WZCControl.WEPKXFormat | WZCControl.ONEXEnabled | WZCControl.WEPKPresent;

                WZC.WZCPassword2Key(ref config, passphrase);

                // Note that, since the config structure doesn't
                // actually have a byte[] for key material, we
                // can't modify bytes of that 'array' in-place.
                key = config.KeyMaterial;
                for (i = 0; i < WLANConfiguration.WZCCTL_MAX_WEPK_MATERIAL; i++)
                {
                    key[i] ^= chFakeKeyMaterial[(7 * i) % 13];
                }
                config.KeyMaterial = key;

                config.EapolParams.EapFlags    = EAPFlags.Enabled;
                config.EapolParams.EapType     = EAPType.TLS;
                config.EapolParams.Enable8021x = true;
                // config.WPAMCastCipher = Ndis802_11Encryption2Enabled;
                break;

            case KeyType.WPABinary:
                // We set this explicitly here.  It was set
                // out of line in the NetUI code.
                config.Privacy = WEPStatus.TKIPEnabled;

                config.KeyLength = WLANConfiguration.WZCCTL_MAX_WEPK_MATERIAL;
                config.CtlFlags |= WZCControl.WEPKPresent;

                // Note that, since the config structure doesn't
                // actually have a byte[] for key material, we
                // can't modify bytes of that 'array' in-place.
                key = config.KeyMaterial;
                for (i = 0; i < WLANConfiguration.WZCCTL_MAX_WEPK_MATERIAL; i++)
                {
                    config.KeyMaterial[i] ^= chFakeKeyMaterial[(7 * i) % 13];
                }
                config.KeyMaterial = key;

                config.EapolParams.EapFlags    = EAPFlags.Enabled;
                config.EapolParams.EapType     = EAPType.TLS;
                config.EapolParams.Enable8021x = true;
                // config.WPAMCastCipher = Ndis802_11Encryption2Enabled;
                break;
            }
        }
        /// <summary>
        /// This routine is used, internally, to make entries
        /// for the preferred SSID list.  It centralizes the
        /// mapping of key data into the structure, etc.
        /// </summary>
        /// <param name="SSID">
        /// The SSID string for the new entry
        /// </param>
        /// <param name="bInfrastructure">
        /// Set to true for infrastucture mode; false for
        /// ad hoc mode
        /// </param>
        /// <param name="Key">
        /// WEP key material
        /// </param>
        /// <param name="keyIndex">
        /// Key index.  Valid values are 1-4
        /// </param>
        /// <param name="authMode">
        /// Authentication mode for the connection
        /// </param>
        /// <param name="privacyMode">
        /// Privacy (encryption) mode for the connection
        /// </param>
        /// <returns>
        /// New WZC_WLAN_CONFIG object or null on failure
        /// </returns>
        private WLANConfiguration MakeSSIDEntry(string SSID, bool bInfrastructure,
                                                byte[] Key, int keyIndex,
                                                AuthenticationMode authMode, WEPStatus privacyMode)
        {
            WLANConfiguration thisConfig = new WLANConfiguration();

            // Set the length.
            thisConfig.Length = thisConfig.Data.Length;

            // Set the MAC address.
            thisConfig.MACAddress = this.GetPhysicalAddress().GetAddressBytes();

            // Set the SSID.
            thisConfig.SSID = SSID;

            // Save the privacy mode.
            thisConfig.Privacy = privacyMode;

            // Set the key index.  Note that, since the 'first'
            // key is key #1 in all of the wireless specifications,
            // we have to decrement the value for WZC, which expects
            // it to be 0.
            thisConfig.KeyIndex = keyIndex - 1;

            // Proceed with configuration.
            byte[] arrKey = null;
            if (Key != null)
            {
                // Key size has already been checked (this
                // is an entry invariant).

                arrKey = Key.Clone() as byte[];
                thisConfig.KeyLength = arrKey.Length;
                thisConfig.CtlFlags |= WZCControl.WEPKPresent | WZCControl.WEPKXFormat;
                if (arrKey.Length == 10)
                {
                    thisConfig.CtlFlags |= WZCControl.WEPK40Bit;
                }
                byte[] chFakeKeyMaterial = new byte[] { 0x56, 0x09, 0x08, 0x98, 0x4D, 0x08, 0x11, 0x66, 0x42, 0x03, 0x01, 0x67, 0x66 };
                for (int i = 0; i < arrKey.Length; i++)
                {
                    arrKey[i] ^= chFakeKeyMaterial[(7 * i) % 13];
                }
                thisConfig.KeyMaterial = arrKey;
            }
            else
            {
                // Clear the key material, as well as setting
                // the length to zero.
                byte[] key = new byte[]
                { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

                thisConfig.KeyMaterial = key;
                thisConfig.KeyLength   = 0;
            }
            thisConfig.AuthenticationMode = authMode;

            // ???? do the right thing, based on the mode.

            // If we have no key, we should probably set this to WEP Off.
            thisConfig.InfrastructureMode = bInfrastructure ? InfrastructureMode.Infrastructure : InfrastructureMode.AdHoc;

            return(thisConfig);
        }
예제 #12
0
        internal unsafe void RefreshListPreferred(bool nearbyOnly)
        {
            // If the caller wants only the local preferred APs,
            // we check nearby list and, if the AP is not there,
            // we don't add it to our own preferred list.
            AccessPointCollection apc = null;

            if (nearbyOnly)
            {
                apc = m_adapter.NearbyAccessPoints;
            }

            // First step is to get the INTF_ENTRY for the adapter.
            // This includes the list of preferred SSID values.
            INTF_ENTRY ie = INTF_ENTRY.GetEntry(this.m_adapter.Name);

            // The field rdStSSIDList is the preferred list.  It comes
            // in the form of a WZC_802_11_CONFIG_LIST.
            RAW_DATA rd = ie.rdStSSIDList;
            WLANConfigurationList cl = new WLANConfigurationList(rd);

            // Step through the list and add a new AP to the
            // collection for each entry.
            for (int i = 0; i < cl.NumberOfItems; i++)
            {
                WLANConfiguration c = cl.Item(i);

                //Debug.WriteLine(c.SSID);
                //for (int d = 1; d <= c.Data.Length; d++)
                //{
                //    Debug.Write(string.Format("{0:x2}{1}", c.Data[d - 1], (d%8 == 0) ? "\r\n" : " "));
                //}
                //Debug.WriteLine(string.Empty);

                // If we're only showing those which we can hear,
                // see if the current SSID is in the nearby list.
                if (nearbyOnly)
                {
                    // Find the currently active AP with the SSID
                    // to match the one we're working on.
                    AccessPoint activeAP = apc.FindBySSID(c.SSID);
                    int         ss;

                    // If the given SSID is not in range, don't add
                    // an entry to the list.
                    if (activeAP != null)
                    {
                        // Update signal strength.
                        ss = activeAP.SignalStrengthInDecibels;

                        // Copy the signal strength value to the
                        // NDIS_WLAN_BSSID structure for the
                        // preferred list entry.
                        c.Rssi = ss;

                        // Create the AP instance and add it to the
                        // preferred list.
                        AccessPoint ap = new AccessPoint(c);
                        m_aps.Add(ap);
                    }
                }
                else
                {
                    // Create the AP instance and add it to the
                    // preferred list.  The signal strength will
                    // not necessarily be valid.
                    AccessPoint ap = new AccessPoint(c);
                    m_aps.Add(ap);
                }
            }

            // Dispose of INTF_ENTRY
            ie.Dispose();
        }