├── .gitignore
├── LICENSE.md
├── README.md
├── SimpleWifi.sln
└── SimpleWifi
├── AccessPoint.cs
├── AuthRequest.cs
├── EapUserFactory.cs
├── EapUserXML
├── EAP-MS-CHAPv2.xml
├── EAP-TLS.xml
├── PEAP-MS-CHAPv2.xml
├── PEAP-TLS.xml
└── SDK.xml
├── ProfileFactory.cs
├── ProfileXML
├── OPEN.xml
├── WEP.xml
├── WPA-Enterprise-PEAP-MSCHAPv2.xml
├── WPA-Enterprise-TLS.xml
├── WPA-PSK.xml
├── WPA2-Enterprise-PEAP-MSCHAPv2.xml
├── WPA2-Enterprise-TLS.xml
└── WPA2-PSK.xml
├── Properties
└── AssemblyInfo.cs
├── SimpleWifi.csproj
├── SimpleWifi.nuspec
├── Wifi.cs
└── Win32
├── Helpers
└── WlanHelpers.cs
├── Interop
├── Enums.cs
├── Exceptions.cs
├── Interop.cs
└── Structs.cs
├── WlanApi.cs
├── WlanInterface.cs
└── WlanNotificationStructs.cs
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 |
5 | # mstest test results
6 | TestResults
7 |
8 | ## Ignore Visual Studio temporary files, build results, and
9 | ## files generated by popular Visual Studio add-ons.
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Rr]elease/
19 | x64/
20 | *_i.c
21 | *_p.c
22 | *.ilk
23 | *.meta
24 | *.obj
25 | *.pch
26 | *.pdb
27 | *.pgc
28 | *.pgd
29 | *.rsp
30 | *.sbr
31 | *.tlb
32 | *.tli
33 | *.tlh
34 | *.tmp
35 | *.log
36 | *.vspscc
37 | *.vssscc
38 | .builds
39 |
40 | # Visual C++ cache files
41 | ipch/
42 | *.aps
43 | *.ncb
44 | *.opensdf
45 | *.sdf
46 |
47 | # Visual Studio profiler
48 | *.psess
49 | *.vsp
50 | *.vspx
51 |
52 | # Guidance Automation Toolkit
53 | *.gpState
54 |
55 | # ReSharper is a .NET coding add-in
56 | _ReSharper*
57 |
58 | # NCrunch
59 | *.ncrunch*
60 | .*crunch*.local.xml
61 |
62 | # Installshield output folder
63 | [Ee]xpress
64 |
65 | # DocProject is a documentation generator add-in
66 | DocProject/buildhelp/
67 | DocProject/Help/*.HxT
68 | DocProject/Help/*.HxC
69 | DocProject/Help/*.hhc
70 | DocProject/Help/*.hhk
71 | DocProject/Help/*.hhp
72 | DocProject/Help/Html2
73 | DocProject/Help/html
74 |
75 | # Click-Once directory
76 | publish
77 |
78 | # Publish Web Output
79 | *.Publish.xml
80 |
81 | # NuGet Packages Directory
82 | packages
83 |
84 | # Windows Azure Build Output
85 | csx
86 | *.build.csdef
87 |
88 | # Windows Store app package directory
89 | AppPackages/
90 |
91 | # Others
92 | [Bb]in
93 | [Oo]bj
94 | sql
95 | TestResults
96 | [Tt]est[Rr]esult*
97 | *.Cache
98 | ClientBin
99 | [Ss]tyle[Cc]op.*
100 | ~$*
101 | *.dbmdl
102 | Generated_Code #added for RIA/Silverlight projects
103 |
104 | # Backup & report files from converting an old project file to a newer
105 | # Visual Studio version. Backup files are not needed, because we have git ;-)
106 | _UpgradeReport_Files/
107 | Backup*/
108 | UpgradeLog*.XML
109 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SimpleWifi
2 | ==========
3 |
4 |
5 | [](https://www.nuget.org/packages/SimpleWifi)
6 |
7 | SimpleWifi is a .NET 4 library written in C# to manage wifi connections in Windows. It is basically a layer of abstraction above Managed Wifi API that takes care of wifi connection profile creation etc, built to be easy to use.
8 |
9 | An example console application is supplied, it can be found in the [example branch](https://github.com/DigiExam/simplewifi/tree/example).
10 |
11 | Available on NuGet: https://www.nuget.org/packages/SimpleWifi
12 |
13 | Currently supported ciphers
14 | ---------------------------
15 | - NONE (open networks)
16 | - WEP
17 | - WPA-PSK
18 | - WPA2-PSK
19 |
20 | Supported operating systems
21 | ---------------------------
22 | - Windows XP SP2 (with hotfix [KB918997](http://support.microsoft.com/kb/918997))
23 | - Windows Vista
24 | - Windows 7
25 | - Windows 8
26 |
27 | Related links
28 | -------------
29 | - Profile examples: http://msdn.microsoft.com/en-us/library/windows/desktop/aa369853(v=vs.85).aspx
30 | - Managed Wifi API: http://managedwifi.codeplex.com/
31 |
--------------------------------------------------------------------------------
/SimpleWifi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleWifi", "SimpleWifi\SimpleWifi.csproj", "{6AA425C9-EA6A-4B01-AAED-5FF122E8B663}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {6AA425C9-EA6A-4B01-AAED-5FF122E8B663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {6AA425C9-EA6A-4B01-AAED-5FF122E8B663}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {6AA425C9-EA6A-4B01-AAED-5FF122E8B663}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {6AA425C9-EA6A-4B01-AAED-5FF122E8B663}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/SimpleWifi/AccessPoint.cs:
--------------------------------------------------------------------------------
1 | using SimpleWifi.Win32;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 | using System.Threading;
9 | using SimpleWifi.Win32.Interop;
10 |
11 | namespace SimpleWifi
12 | {
13 | public class AccessPoint
14 | {
15 | private WlanInterface _interface;
16 | private WlanAvailableNetwork _network;
17 |
18 | internal AccessPoint(WlanInterface interfac, WlanAvailableNetwork network)
19 | {
20 | _interface = interfac;
21 | _network = network;
22 | }
23 |
24 | public string Name
25 | {
26 | get
27 | {
28 | return Encoding.ASCII.GetString(_network.dot11Ssid.SSID, 0, (int)_network.dot11Ssid.SSIDLength);
29 | }
30 | }
31 |
32 | public uint SignalStrength
33 | {
34 | get
35 | {
36 | return _network.wlanSignalQuality;
37 | }
38 | }
39 |
40 | ///
41 | /// If the computer has a connection profile stored for this access point
42 | ///
43 | public bool HasProfile
44 | {
45 | get
46 | {
47 | try
48 | {
49 | return _interface.GetProfiles().Where(p => p.profileName == Name).Any();
50 | }
51 | catch
52 | {
53 | return false;
54 | }
55 | }
56 | }
57 |
58 | public bool IsSecure
59 | {
60 | get
61 | {
62 | return _network.securityEnabled;
63 | }
64 | }
65 |
66 | public bool IsConnected
67 | {
68 | get
69 | {
70 | try
71 | {
72 | var a = _interface.CurrentConnection; // This prop throws exception if not connected, which forces me to this try catch. Refactor plix.
73 | return a.profileName == _network.profileName;
74 | }
75 | catch
76 | {
77 | return false;
78 | }
79 | }
80 |
81 | }
82 |
83 | ///
84 | /// Returns the underlying network object.
85 | ///
86 | internal WlanAvailableNetwork Network
87 | {
88 | get
89 | {
90 | return _network;
91 | }
92 | }
93 |
94 |
95 | ///
96 | /// Returns the underlying interface object.
97 | ///
98 | internal WlanInterface Interface
99 | {
100 | get
101 | {
102 | return _interface;
103 | }
104 | }
105 |
106 | ///
107 | /// Checks that the password format matches this access point's encryption method.
108 | ///
109 | public bool IsValidPassword(string password)
110 | {
111 | return PasswordHelper.IsValid(password, _network.dot11DefaultCipherAlgorithm);
112 | }
113 |
114 | ///
115 | /// Connect synchronous to the access point.
116 | ///
117 | public bool Connect(AuthRequest request, bool overwriteProfile = false)
118 | {
119 | // No point to continue with the connect if the password is not valid if overwrite is true or profile is missing.
120 | if (!request.IsPasswordValid && (!HasProfile || overwriteProfile))
121 | return false;
122 |
123 | // If we should create or overwrite the profile, do so.
124 | if (!HasProfile || overwriteProfile)
125 | {
126 | if (HasProfile)
127 | _interface.DeleteProfile(Name);
128 |
129 | request.Process();
130 | }
131 |
132 |
133 | // TODO: Auth algorithm: IEEE80211_Open + Cipher algorithm: None throws an error.
134 | // Probably due to connectionmode profile + no profile exist, cant figure out how to solve it though.
135 | return _interface.ConnectSynchronously(WlanConnectionMode.Profile, _network.dot11BssType, Name, 6000);
136 | }
137 |
138 | ///
139 | /// Connect asynchronous to the access point.
140 | ///
141 | public void ConnectAsync(AuthRequest request, bool overwriteProfile = false, Action onConnectComplete = null)
142 | {
143 | // TODO: Refactor -> Use async connect in wlaninterface.
144 | ThreadPool.QueueUserWorkItem(new WaitCallback((o) => {
145 | bool success = false;
146 |
147 | try
148 | {
149 | success = Connect(request, overwriteProfile);
150 | }
151 | catch (Win32Exception)
152 | {
153 | success = false;
154 | }
155 |
156 | if (onConnectComplete != null)
157 | onConnectComplete(success);
158 | }));
159 | }
160 |
161 | public string GetProfileXML()
162 | {
163 | if (HasProfile)
164 | return _interface.GetProfileXml(Name);
165 | else
166 | return string.Empty;
167 | }
168 |
169 | public void DeleteProfile()
170 | {
171 | try
172 | {
173 | if (HasProfile)
174 | _interface.DeleteProfile(Name);
175 | }
176 | catch { }
177 | }
178 |
179 | public override sealed string ToString()
180 | {
181 | StringBuilder info = new StringBuilder();
182 | info.AppendLine("Interface: " + _interface.InterfaceName);
183 | info.AppendLine("Auth algorithm: " + _network.dot11DefaultAuthAlgorithm);
184 | info.AppendLine("Cipher algorithm: " + _network.dot11DefaultCipherAlgorithm);
185 | info.AppendLine("BSS type: " + _network.dot11BssType);
186 | info.AppendLine("Connectable: " + _network.networkConnectable);
187 |
188 | if (!_network.networkConnectable)
189 | info.AppendLine("Reason to false: " + _network.wlanNotConnectableReason);
190 |
191 | return info.ToString();
192 | }
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/SimpleWifi/AuthRequest.cs:
--------------------------------------------------------------------------------
1 | using SimpleWifi.Win32;
2 | using SimpleWifi.Win32.Interop;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Text.RegularExpressions;
8 |
9 | namespace SimpleWifi
10 | {
11 | public class AuthRequest
12 | {
13 | private bool _isPasswordRequired, _isUsernameRequired, _isDomainSupported, _isEAPStore;
14 | private string _password, _username, _domain;
15 | private WlanAvailableNetwork _network;
16 | private WlanInterface _interface;
17 |
18 | public AuthRequest(AccessPoint ap)
19 | {
20 | _network = ap.Network;
21 | _interface = ap.Interface;
22 |
23 | _isPasswordRequired =
24 | _network.securityEnabled &&
25 | _network.dot11DefaultCipherAlgorithm != Dot11CipherAlgorithm.None;
26 |
27 | _isEAPStore =
28 | _network.dot11DefaultAuthAlgorithm == Dot11AuthAlgorithm.RSNA ||
29 | _network.dot11DefaultAuthAlgorithm == Dot11AuthAlgorithm.WPA;
30 |
31 | _isUsernameRequired = _isEAPStore;
32 | _isDomainSupported = _isEAPStore;
33 | }
34 |
35 | public bool IsPasswordRequired { get { return _isPasswordRequired; } }
36 | public bool IsUsernameRequired { get { return _isUsernameRequired; } }
37 | public bool IsDomainSupported { get { return _isDomainSupported; } }
38 |
39 | public string Password
40 | {
41 | get { return _password; }
42 | set { _password = value; }
43 | }
44 |
45 | public string Username
46 | {
47 | get { return _username; }
48 | set { _username = value; }
49 | }
50 |
51 | public string Domain
52 | {
53 | get { return _domain; }
54 | set { _domain = value; }
55 | }
56 |
57 | public bool IsPasswordValid
58 | {
59 | get
60 | {
61 | #warning Robin: Not sure that Enterprise networks have the same requirements on the password complexity as standard ones.
62 | return PasswordHelper.IsValid(_password, _network.dot11DefaultCipherAlgorithm);
63 | }
64 | }
65 |
66 | private bool SaveToEAP()
67 | {
68 | if (!_isEAPStore || !IsPasswordValid)
69 | return false;
70 |
71 | string userXML = EapUserFactory.Generate(_network.dot11DefaultCipherAlgorithm, _username, _password, _domain);
72 | _interface.SetEAP(_network.profileName, userXML);
73 |
74 | return true;
75 | }
76 |
77 | internal bool Process()
78 | {
79 | if (!IsPasswordValid)
80 | return false;
81 |
82 | string profileXML = ProfileFactory.Generate(_network, _password);
83 | _interface.SetProfile(WlanProfileFlags.AllUser, profileXML, true);
84 |
85 | if (_isEAPStore && !SaveToEAP())
86 | return false;
87 |
88 | return true;
89 | }
90 | }
91 |
92 | public static class PasswordHelper
93 | {
94 | ///
95 | /// Checks if a password is valid for a cipher type.
96 | ///
97 | public static bool IsValid(string password, Dot11CipherAlgorithm cipherAlgorithm)
98 | {
99 | switch (cipherAlgorithm)
100 | {
101 | case Dot11CipherAlgorithm.None:
102 | return true;
103 | case Dot11CipherAlgorithm.WEP: // WEP key is 10, 26 or 40 hex digits long.
104 | if (string.IsNullOrEmpty(password))
105 | return false;
106 |
107 | int len = password.Length;
108 |
109 | bool correctLength = len == 10 || len == 26 || len == 40;
110 | bool onlyHex = new Regex("^[0-9A-F]+$").IsMatch(password);
111 |
112 | return correctLength && onlyHex;
113 | case Dot11CipherAlgorithm.CCMP: // WPA2-PSK 8 to 63 ASCII characters
114 | case Dot11CipherAlgorithm.TKIP: // WPA-PSK 8 to 63 ASCII characters
115 | if (string.IsNullOrEmpty(password))
116 | return false;
117 |
118 | return 8 <= password.Length && password.Length <= 63;
119 | default:
120 | return true;
121 | }
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/SimpleWifi/EapUserFactory.cs:
--------------------------------------------------------------------------------
1 | using SimpleWifi.Win32.Interop;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Reflection;
7 | using System.Text;
8 |
9 | namespace SimpleWifi
10 | {
11 | internal static class EapUserFactory
12 | {
13 | ///
14 | /// Generates the EAP user XML
15 | ///
16 | internal static string Generate(Dot11CipherAlgorithm cipher, string username, string password, string domain)
17 | {
18 | #warning Robin: Probably not properly implemented, only supports WPA- and WPA-2 Enterprise with PEAP-MSCHAPv2
19 |
20 | string profile = string.Empty;
21 | string template = string.Empty;
22 |
23 | switch (cipher)
24 | {
25 | case Dot11CipherAlgorithm.CCMP: // WPA-2
26 | case Dot11CipherAlgorithm.TKIP: // WPA
27 | template = GetTemplate("PEAP-MS-CHAPv2");
28 |
29 | profile = string.Format(template, username, FixPass(password), domain);
30 | break;
31 | default:
32 | throw new NotImplementedException("Profile for selected cipher algorithm is not implemented");
33 | }
34 |
35 | return profile;
36 | }
37 |
38 | ///
39 | /// Fetches the template for an EAP user
40 | ///
41 | private static string GetTemplate(string name)
42 | {
43 | string resourceName = string.Format("SimpleWifi.EapUserXML.{0}.xml", name);
44 |
45 | using (StreamReader reader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)))
46 | {
47 | return reader.ReadToEnd();
48 | }
49 | }
50 |
51 | private static string FixPass(string pass)
52 | {
53 | pass = EncodeToBase64(pass);
54 | pass = pass.Replace("&", "&");
55 | pass = pass.Replace("<", "<");
56 | pass = pass.Replace(">", ">");
57 |
58 | return pass;
59 | }
60 |
61 |
62 | private static string EncodeToBase64(string toEncode)
63 | {
64 | byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
65 | string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
66 | return returnValue;
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/SimpleWifi/EapUserXML/EAP-MS-CHAPv2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 26
5 | 0
6 |
7 |
8 |
9 | 26
10 |
11 | {0}
12 | {1}
13 | {2}
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/SimpleWifi/EapUserXML/EAP-TLS.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 13
5 | 0
6 |
7 |
8 |
9 | 13
10 |
11 | {1}\{0}
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/SimpleWifi/EapUserXML/PEAP-MS-CHAPv2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 25
5 | 0
6 |
7 |
8 |
9 | 25
10 |
11 | {0}
12 |
13 | 26
14 |
15 | {0}
16 | {1}
17 | {2}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/SimpleWifi/EapUserXML/PEAP-TLS.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 25
5 | 0
6 |
7 |
8 |
9 | 25
10 |
11 | {0}
12 |
13 | 13
14 |
15 | {1}\{0}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/SimpleWifi/EapUserXML/SDK.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 40
5 | 100
6 |
7 |
8 | 40
9 | {0}
10 | {1}
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/SimpleWifi/ProfileFactory.cs:
--------------------------------------------------------------------------------
1 | using SimpleWifi.Win32;
2 | using SimpleWifi.Win32.Interop;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Reflection;
8 | using System.Text;
9 |
10 | namespace SimpleWifi
11 | {
12 | internal static class ProfileFactory
13 | {
14 | ///
15 | /// Generates the profile XML for the access point and password
16 | ///
17 | internal static string Generate(WlanAvailableNetwork network, string password)
18 | {
19 | string profile = string.Empty;
20 | string template = string.Empty;
21 | string name = Encoding.ASCII.GetString(network.dot11Ssid.SSID, 0, (int)network.dot11Ssid.SSIDLength);
22 | string hex = GetHexString(network.dot11Ssid.SSID);
23 |
24 | var authAlgo = network.dot11DefaultAuthAlgorithm;
25 |
26 | switch (network.dot11DefaultCipherAlgorithm)
27 | {
28 | case Dot11CipherAlgorithm.None:
29 | template = GetTemplate("OPEN");
30 | profile = string.Format(template, name, hex);
31 | break;
32 | case Dot11CipherAlgorithm.WEP:
33 | template = GetTemplate("WEP");
34 | profile = string.Format(template, name, hex, password);
35 | break;
36 | case Dot11CipherAlgorithm.CCMP:
37 | if (authAlgo == Dot11AuthAlgorithm.RSNA)
38 | {
39 | template = GetTemplate("WPA2-Enterprise-PEAP-MSCHAPv2");
40 | profile = string.Format(template, name);
41 | }
42 | else // PSK
43 | {
44 | template = GetTemplate("WPA2-PSK");
45 | profile = string.Format(template, name, password);
46 | }
47 | break;
48 | case Dot11CipherAlgorithm.TKIP:
49 | #warning Robin: Not sure WPA uses RSNA
50 | if (authAlgo == Dot11AuthAlgorithm.RSNA)
51 | {
52 | template = GetTemplate("WPA-Enterprise-PEAP-MSCHAPv2");
53 | profile = string.Format(template, name);
54 | }
55 | else // PSK
56 | {
57 | template = GetTemplate("WPA-PSK");
58 | profile = string.Format(template, name, password);
59 | }
60 |
61 | break;
62 | default:
63 | throw new NotImplementedException("Profile for selected cipher algorithm is not implemented");
64 | }
65 |
66 | return profile;
67 | }
68 |
69 | ///
70 | /// Fetches the template for an wireless connection profile.
71 | ///
72 | private static string GetTemplate(string name)
73 | {
74 | string resourceName = string.Format("SimpleWifi.ProfileXML.{0}.xml", name);
75 |
76 | using (StreamReader reader = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)))
77 | {
78 | return reader.ReadToEnd();
79 | }
80 | }
81 |
82 | ///
83 | /// Converts an byte array into the hex representation, ex: [255, 255] -> "FFFF"
84 | ///
85 | private static string GetHexString(byte[] ba)
86 | {
87 | StringBuilder sb = new StringBuilder(ba.Length * 2);
88 |
89 | foreach (byte b in ba)
90 | {
91 | if (b == 0)
92 | break;
93 |
94 | sb.AppendFormat("{0:x2}", b);
95 | }
96 |
97 | return sb.ToString();
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/SimpleWifi/ProfileXML/OPEN.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0}
4 |
5 |
6 | {1}
7 | {0}
8 |
9 |
10 | ESS
11 | manual
12 |
13 |
14 |
15 | open
16 | none
17 | false
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/SimpleWifi/ProfileXML/WEP.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0}
4 |
5 |
6 | {1}
7 | {0}
8 |
9 |
10 | ESS
11 |
12 |
13 |
14 | open
15 | WEP
16 | false
17 |
18 |
19 | networkKey
20 | false
21 | {2}
22 |
23 | 0
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SimpleWifi/ProfileXML/WPA-Enterprise-PEAP-MSCHAPv2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0}
4 |
5 |
6 | {0}
7 |
8 |
9 | ESS
10 | auto
11 |
12 |
13 |
14 | WPA
15 | TKIP
16 | true
17 |
18 |
19 |
20 |
21 |
22 | 25
23 | 0
24 |
25 |
26 |
27 | 25
28 |
29 |
30 | false
31 |
32 |
33 | true
34 | 0
35 |
36 | 26
37 |
38 | false
39 |
40 |
41 | false
42 | false
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/SimpleWifi/ProfileXML/WPA-Enterprise-TLS.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0}
4 |
5 |
6 | {0}
7 |
8 | false
9 |
10 | ESS
11 | auto
12 | false
13 |
14 |
15 |
16 | WPA
17 | TKIP
18 | true
19 |
20 |
21 |
22 |
23 |
24 | 13
25 | 0
26 |
27 |
28 |
29 | 13
30 |
31 |
32 |
33 |
34 |
35 | false
36 |
37 |
38 | false
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/SimpleWifi/ProfileXML/WPA-PSK.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0}
4 |
5 |
6 | {0}
7 |
8 |
9 | ESS
10 | auto
11 | false
12 |
13 |
14 |
15 | WPAPSK
16 | TKIP
17 | false
18 |
19 |
20 | passPhrase
21 | false
22 | {1}
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SimpleWifi/ProfileXML/WPA2-Enterprise-PEAP-MSCHAPv2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0}
4 |
5 |
6 | {0}
7 |
8 |
9 | ESS
10 | auto
11 |
12 |
13 |
14 | WPA2
15 | AES
16 | true
17 |
18 |
19 |
20 |
21 |
22 | 25
23 | 0
24 |
25 |
26 |
27 | 25
28 |
29 |
30 | false
31 |
32 |
33 | true
34 | 0
35 |
36 | 26
37 |
38 | false
39 |
40 |
41 | false
42 | false
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/SimpleWifi/ProfileXML/WPA2-Enterprise-TLS.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0}
4 |
5 |
6 | {0}
7 |
8 |
9 | ESS
10 | auto
11 | false
12 |
13 |
14 |
15 | WPA2
16 | AES
17 | true
18 |
19 |
20 |
21 |
22 |
23 | 13
24 | 0
25 |
26 |
27 |
28 | 13
29 |
30 |
31 |
32 |
33 |
34 | false
35 |
36 |
37 | false
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/SimpleWifi/ProfileXML/WPA2-PSK.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | {0}
4 |
5 |
6 | {0}
7 |
8 |
9 | ESS
10 | auto
11 | false
12 |
13 |
14 |
15 | WPA2PSK
16 | AES
17 | false
18 |
19 |
20 | passPhrase
21 | false
22 | {1}
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/SimpleWifi/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SimpleWifi")]
9 | [assembly: AssemblyDescription(".NET 4 library to manage wifi connections")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("DigiExam AB")]
12 | [assembly: AssemblyProduct("SimpleWifi")]
13 | [assembly: AssemblyCopyright("Copyright © DigiExam AB 2015 - MIT License")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("e7646a9f-2d07-455a-b9ae-51eaf7281d2f")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Revision and Build Numbers
33 | // by using the '*' as shown below:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/SimpleWifi/SimpleWifi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.50727
7 | 2.0
8 | {6AA425C9-EA6A-4B01-AAED-5FF122E8B663}
9 | Library
10 | Properties
11 | SimpleWifi
12 | SimpleWifi
13 | v4.0
14 |
15 |
16 |
17 |
18 | 2.0
19 | publish\
20 | true
21 | Disk
22 | false
23 | Foreground
24 | 7
25 | Days
26 | false
27 | false
28 | true
29 | 0
30 | 1.0.0.%2a
31 | false
32 | false
33 | true
34 |
35 |
36 |
37 | true
38 | full
39 | false
40 | bin\Debug\
41 | DEBUG;TRACE
42 | prompt
43 | 4
44 |
45 |
46 | pdbonly
47 | true
48 | bin\Release\
49 | TRACE
50 | prompt
51 | 4
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | False
77 | .NET Framework 3.5 SP1 Client Profile
78 | false
79 |
80 |
81 | False
82 | .NET Framework 3.5 SP1
83 | true
84 |
85 |
86 |
87 |
88 | Designer
89 |
90 |
91 |
92 |
93 |
94 | Designer
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
119 |
--------------------------------------------------------------------------------
/SimpleWifi/SimpleWifi.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | $version$
6 | $title$
7 | $author$
8 | $author$
9 | false
10 | $description$
11 | Initial release
12 | Copyright 2015
13 | wifi networking
14 |
15 |
--------------------------------------------------------------------------------
/SimpleWifi/Wifi.cs:
--------------------------------------------------------------------------------
1 | using SimpleWifi.Win32;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 | using System.Linq;
6 | using SimpleWifi.Win32.Interop;
7 |
8 | using NotifCodeACM = SimpleWifi.Win32.Interop.WlanNotificationCodeAcm;
9 | using NotifCodeMSM = SimpleWifi.Win32.Interop.WlanNotificationCodeMsm;
10 |
11 | namespace SimpleWifi
12 | {
13 | public class Wifi
14 | {
15 | public event EventHandler ConnectionStatusChanged;
16 |
17 | private WlanClient _client;
18 | private WifiStatus _connectionStatus;
19 | private bool _isConnectionStatusSet = false;
20 | public bool NoWifiAvailable = false;
21 |
22 | public Wifi()
23 | {
24 | _client = new WlanClient();
25 | NoWifiAvailable = _client.NoWifiAvailable;
26 | if (_client.NoWifiAvailable)
27 | return;
28 |
29 | foreach (var inte in _client.Interfaces)
30 | inte.WlanNotification += inte_WlanNotification;
31 | }
32 |
33 | ///
34 | /// Returns a list over all available access points
35 | ///
36 | public List GetAccessPoints()
37 | {
38 | List accessPoints = new List();
39 | if (_client.NoWifiAvailable)
40 | return accessPoints;
41 |
42 | foreach (WlanInterface wlanIface in _client.Interfaces)
43 | {
44 | WlanAvailableNetwork[] rawNetworks = wlanIface.GetAvailableNetworkList(0);
45 | List networks = new List();
46 |
47 | // Remove network entries without profile name if one exist with a profile name.
48 | foreach (WlanAvailableNetwork network in rawNetworks)
49 | {
50 | bool hasProfileName = !string.IsNullOrEmpty(network.profileName);
51 | bool anotherInstanceWithProfileExists = rawNetworks.Where(n => n.Equals(network) && !string.IsNullOrEmpty(n.profileName)).Any();
52 |
53 | if (!anotherInstanceWithProfileExists || hasProfileName)
54 | networks.Add(network);
55 | }
56 |
57 | foreach (WlanAvailableNetwork network in networks)
58 | {
59 | accessPoints.Add(new AccessPoint(wlanIface, network));
60 | }
61 | }
62 |
63 | return accessPoints;
64 | }
65 |
66 | ///
67 | /// Disconnect all wifi interfaces
68 | ///
69 | public void Disconnect()
70 | {
71 | if (_client.NoWifiAvailable)
72 | return;
73 |
74 | foreach (WlanInterface wlanIface in _client.Interfaces)
75 | {
76 | wlanIface.Disconnect();
77 | }
78 | }
79 | public WifiStatus ConnectionStatus
80 | {
81 | get
82 | {
83 | if (!_isConnectionStatusSet)
84 | ConnectionStatus = GetForcedConnectionStatus();
85 |
86 | return _connectionStatus;
87 | }
88 | private set
89 | {
90 | _isConnectionStatusSet = true;
91 | _connectionStatus = value;
92 | }
93 | }
94 |
95 | private void inte_WlanNotification(WlanNotificationData notifyData)
96 | {
97 | if (notifyData.notificationSource == WlanNotificationSource.ACM && (NotifCodeACM)notifyData.NotificationCode == NotifCodeACM.Disconnected)
98 | OnConnectionStatusChanged(WifiStatus.Disconnected);
99 | else if (notifyData.notificationSource == WlanNotificationSource.MSM && (NotifCodeMSM)notifyData.NotificationCode == NotifCodeMSM.Connected)
100 | OnConnectionStatusChanged(WifiStatus.Connected);
101 | }
102 |
103 | private void OnConnectionStatusChanged(WifiStatus newStatus)
104 | {
105 | ConnectionStatus = newStatus;
106 |
107 | if (ConnectionStatusChanged != null)
108 | ConnectionStatusChanged(this, new WifiStatusEventArgs(newStatus));
109 | }
110 |
111 | // I don't like this method, it's slow, ugly and should be refactored ASAP.
112 | private WifiStatus GetForcedConnectionStatus()
113 | {
114 | if (NoWifiAvailable)
115 | return WifiStatus.Disconnected;
116 |
117 | bool connected = false;
118 |
119 | foreach (var i in _client.Interfaces)
120 | {
121 | try
122 | {
123 | var a = i.CurrentConnection; // Current connection throws an exception if disconnected.
124 | connected = true;
125 | }
126 | catch { }
127 | }
128 |
129 | if (connected)
130 | return WifiStatus.Connected;
131 | else
132 | return WifiStatus.Disconnected;
133 | }
134 | }
135 |
136 | public class WifiStatusEventArgs : EventArgs
137 | {
138 | public WifiStatus NewStatus { get; private set; }
139 |
140 | internal WifiStatusEventArgs(WifiStatus status) : base()
141 | {
142 | this.NewStatus = status;
143 | }
144 |
145 | }
146 |
147 | public enum WifiStatus
148 | {
149 | Disconnected,
150 | Connected
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/SimpleWifi/Win32/Helpers/WlanHelpers.cs:
--------------------------------------------------------------------------------
1 | using SimpleWifi.Win32.Interop;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 |
8 | namespace SimpleWifi.Win32.Helpers
9 | {
10 | internal static class WlanHelpers
11 | {
12 | internal static WlanConnectionNotificationData? ParseWlanConnectionNotification(ref WlanNotificationData notifyData)
13 | {
14 | int expectedSize = Marshal.SizeOf(typeof(WlanConnectionNotificationData));
15 | if (notifyData.dataSize < expectedSize)
16 | return null;
17 |
18 | WlanConnectionNotificationData connNotifyData = (WlanConnectionNotificationData)Marshal.PtrToStructure(notifyData.dataPtr, typeof(WlanConnectionNotificationData));
19 |
20 | if (connNotifyData.wlanReasonCode == WlanReasonCode.Success)
21 | {
22 | long profileXmlPtrValue = notifyData.dataPtr.ToInt64() + Marshal.OffsetOf(typeof(WlanConnectionNotificationData), "profileXml").ToInt64();
23 | connNotifyData.profileXml = Marshal.PtrToStringUni(new IntPtr(profileXmlPtrValue));
24 | }
25 |
26 | return connNotifyData;
27 | }
28 |
29 | ///
30 | /// Gets a string that describes a specified reason code. NOTE: Not used!
31 | ///
32 | /// The reason code.
33 | /// The string.
34 | internal static string GetStringForReasonCode(WlanReasonCode reasonCode)
35 | {
36 | StringBuilder sb = new StringBuilder(1024); // the 1024 size here is arbitrary; the WlanReasonCodeToString docs fail to specify a recommended size
37 |
38 | if (WlanInterop.WlanReasonCodeToString(reasonCode, sb.Capacity, sb, IntPtr.Zero) != 0)
39 | {
40 | sb.Clear(); // Not sure if we get junk in the stringbuilder buffer from WlanReasonCodeToString, clearing it to be sure.
41 | sb.Append("Failed to retrieve reason code, probably too small buffer.");
42 | }
43 |
44 | return sb.ToString();
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/SimpleWifi/Win32/Interop/Enums.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace SimpleWifi.Win32.Interop
7 | {
8 |
9 | ///
10 | /// Defines various opcodes used to set and query parameters for an interface.
11 | ///
12 | ///
13 | /// Corresponds to the native WLAN_INTF_OPCODE type.
14 | ///
15 | public enum WlanIntfOpcode
16 | {
17 | ///
18 | /// Opcode used to set or query whether auto config is enabled.
19 | ///
20 | AutoconfEnabled = 1,
21 | ///
22 | /// Opcode used to set or query whether background scan is enabled.
23 | ///
24 | BackgroundScanEnabled,
25 | ///
26 | /// Opcode used to set or query the media streaming mode of the driver.
27 | ///
28 | MediaStreamingMode,
29 | ///
30 | /// Opcode used to set or query the radio state.
31 | ///
32 | RadioState,
33 | ///
34 | /// Opcode used to set or query the BSS type of the interface.
35 | ///
36 | BssType,
37 | ///
38 | /// Opcode used to query the state of the interface.
39 | ///
40 | InterfaceState,
41 | ///
42 | /// Opcode used to query information about the current connection of the interface.
43 | ///
44 | CurrentConnection,
45 | ///
46 | /// Opcose used to query the current channel on which the wireless interface is operating.
47 | ///
48 | ChannelNumber,
49 | ///
50 | /// Opcode used to query the supported auth/cipher pairs for infrastructure mode.
51 | ///
52 | SupportedInfrastructureAuthCipherPairs,
53 | ///
54 | /// Opcode used to query the supported auth/cipher pairs for ad hoc mode.
55 | ///
56 | SupportedAdhocAuthCipherPairs,
57 | ///
58 | /// Opcode used to query the list of supported country or region strings.
59 | ///
60 | SupportedCountryOrRegionStringList,
61 | ///
62 | /// Opcode used to set or query the current operation mode of the wireless interface.
63 | ///
64 | CurrentOperationMode,
65 | ///
66 | /// Opcode used to query driver statistics.
67 | ///
68 | Statistics = 0x10000101,
69 | ///
70 | /// Opcode used to query the received signal strength.
71 | ///
72 | RSSI,
73 | SecurityStart = 0x20010000,
74 | SecurityEnd = 0x2fffffff,
75 | IhvStart = 0x30000000,
76 | IhvEnd = 0x3fffffff
77 | }
78 |
79 | ///
80 | /// Specifies the origin of automatic configuration (auto config) settings.
81 | ///
82 | ///
83 | /// Corresponds to the native WLAN_OPCODE_VALUE_TYPE type.
84 | ///
85 | public enum WlanOpcodeValueType
86 | {
87 | ///
88 | /// The auto config settings were queried, but the origin of the settings was not determined.
89 | ///
90 | QueryOnly = 0,
91 | ///
92 | /// The auto config settings were set by group policy.
93 | ///
94 | SetByGroupPolicy = 1,
95 | ///
96 | /// The auto config settings were set by the user.
97 | ///
98 | SetByUser = 2,
99 | ///
100 | /// The auto config settings are invalid.
101 | ///
102 | Invalid = 3
103 | }
104 |
105 | ///
106 | /// Defines flags passed to .
107 | ///
108 | [Flags]
109 | public enum WlanGetAvailableNetworkFlags
110 | {
111 | ///
112 | /// Include all ad-hoc network profiles in the available network list, including profiles that are not visible.
113 | ///
114 | IncludeAllAdhocProfiles = 0x00000001,
115 | ///
116 | /// Include all hidden network profiles in the available network list, including profiles that are not visible.
117 | ///
118 | IncludeAllManualHiddenProfiles = 0x00000002
119 | }
120 |
121 | ///
122 | /// Contains various flags for the network.
123 | ///
124 | [Flags]
125 | public enum WlanAvailableNetworkFlags
126 | {
127 | ///
128 | /// This network is currently connected.
129 | ///
130 | Connected = 0x00000001,
131 | ///
132 | /// There is a profile for this network.
133 | ///
134 | HasProfile = 0x00000002
135 | }
136 |
137 | [Flags]
138 | public enum WlanProfileFlags
139 | {
140 | ///
141 | /// The only option available on Windows XP SP2.
142 | ///
143 | AllUser = 0,
144 | GroupPolicy = 1,
145 | User = 2
146 | }
147 |
148 | ///
149 | /// Defines the access mask of an all-user profile.
150 | ///
151 | [Flags]
152 | public enum WlanAccess
153 | {
154 | ///
155 | /// The user can view profile permissions.
156 | ///
157 | ReadAccess = 0x00020000 | 0x0001,
158 | ///
159 | /// The user has read access, and the user can also connect to and disconnect from a network using the profile.
160 | ///
161 | ExecuteAccess = ReadAccess | 0x0020,
162 | ///
163 | /// The user has execute access and the user can also modify and delete permissions associated with a profile.
164 | ///
165 | WriteAccess = ReadAccess | ExecuteAccess | 0x0002 | 0x00010000 | 0x00040000
166 | }
167 |
168 | ///
169 | /// Specifies where the notification comes from.
170 | ///
171 | [Flags]
172 | public enum WlanNotificationSource
173 | {
174 | None = 0,
175 | ///
176 | /// All notifications, including those generated by the 802.1X module.
177 | ///
178 | All = 0X0000FFFF,
179 | ///
180 | /// Notifications generated by the auto configuration module.
181 | ///
182 | ACM = 0X00000008,
183 | ///
184 | /// Notifications generated by MSM.
185 | ///
186 | MSM = 0X00000010,
187 | ///
188 | /// Notifications generated by the security module.
189 | ///
190 | Security = 0X00000020,
191 | ///
192 | /// Notifications generated by independent hardware vendors (IHV).
193 | ///
194 | IHV = 0X00000040
195 | }
196 |
197 | ///
198 | /// Indicates the type of an ACM () notification.
199 | ///
200 | ///
201 | /// The enumeration identifiers correspond to the native wlan_notification_acm_ identifiers.
202 | /// On Windows XP SP2, only the ConnectionComplete and Disconnected notifications are available.
203 | ///
204 | public enum WlanNotificationCodeAcm
205 | {
206 | AutoconfEnabled = 1,
207 | AutoconfDisabled,
208 | BackgroundScanEnabled,
209 | BackgroundScanDisabled,
210 | BssTypeChange,
211 | PowerSettingChange,
212 | ScanComplete,
213 | ScanFail,
214 | ConnectionStart,
215 | ConnectionComplete,
216 | ConnectionAttemptFail,
217 | FilterListChange,
218 | InterfaceArrival,
219 | InterfaceRemoval,
220 | ProfileChange,
221 | ProfileNameChange,
222 | ProfilesExhausted,
223 | NetworkNotAvailable,
224 | NetworkAvailable,
225 | Disconnecting,
226 | Disconnected,
227 | AdhocNetworkStateChange
228 | }
229 |
230 | ///
231 | /// Indicates the type of an MSM () notification.
232 | ///
233 | ///
234 | /// The enumeration identifiers correspond to the native wlan_notification_msm_ identifiers.
235 | ///
236 | public enum WlanNotificationCodeMsm
237 | {
238 | Associating = 1,
239 | Associated,
240 | Authenticating,
241 | Connected,
242 | RoamingStart,
243 | RoamingEnd,
244 | RadioStateChange,
245 | SignalQualityChange,
246 | Disassociating,
247 | Disconnected,
248 | PeerJoin,
249 | PeerLeave,
250 | AdapterRemoval,
251 | AdapterOperationModeChange
252 | }
253 |
254 | ///
255 | /// Defines connection parameter flags.
256 | ///
257 | [Flags]
258 | public enum WlanConnectionFlags
259 | {
260 | ///
261 | /// Connect to the destination network even if the destination is a hidden network. A hidden network does not broadcast its SSID. Do not use this flag if the destination network is an ad-hoc network.
262 | /// If the profile specified by is not null, then this flag is ignored and the nonBroadcast profile element determines whether to connect to a hidden network.
263 | ///
264 | HiddenNetwork = 0x00000001,
265 | ///
266 | /// Do not form an ad-hoc network. Only join an ad-hoc network if the network already exists. Do not use this flag if the destination network is an infrastructure network.
267 | ///
268 | AdhocJoinOnly = 0x00000002,
269 | ///
270 | /// Ignore the privacy bit when connecting to the network. Ignoring the privacy bit has the effect of ignoring whether packets are encryption and ignoring the method of encryption used. Only use this flag when connecting to an infrastructure network using a temporary profile.
271 | ///
272 | IgnorePrivacyBit = 0x00000004,
273 | ///
274 | /// Exempt EAPOL traffic from encryption and decryption. This flag is used when an application must send EAPOL traffic over an infrastructure network that uses Open authentication and WEP encryption. This flag must not be used to connect to networks that require 802.1X authentication. This flag is only valid when is set to . Avoid using this flag whenever possible.
275 | ///
276 | EapolPassthrough = 0x00000008
277 | }
278 |
279 |
280 | ///
281 | /// The connection state of an ad hoc network.
282 | ///
283 | public enum WlanAdhocNetworkState
284 | {
285 | ///
286 | /// The ad hoc network has been formed, but no client or host is connected to the network.
287 | ///
288 | Formed = 0,
289 | ///
290 | /// A client or host is connected to the ad hoc network.
291 | ///
292 | Connected = 1
293 | }
294 |
295 | // TODO: .NET-ify the WlanReasonCode enum (naming convention + docs).
296 |
297 | ///
298 | /// Specifies reasons for a failure of a WLAN operation.
299 | ///
300 | ///
301 | /// To get the WLAN API native reason code identifiers, prefix the identifiers with WLAN_REASON_CODE_.
302 | ///
303 | public enum WlanReasonCode
304 | {
305 | Success = 0,
306 | // general codes
307 | UNKNOWN = 0x10000 + 1,
308 |
309 | RANGE_SIZE = 0x10000,
310 | BASE = 0x10000 + RANGE_SIZE,
311 |
312 | // range for Auto Config
313 | //
314 | AC_BASE = 0x10000 + RANGE_SIZE,
315 | AC_CONNECT_BASE = (AC_BASE + RANGE_SIZE / 2),
316 | AC_END = (AC_BASE + RANGE_SIZE - 1),
317 |
318 | // range for profile manager
319 | // it has profile adding failure reason codes, but may not have
320 | // connection reason codes
321 | //
322 | PROFILE_BASE = 0x10000 + (7 * RANGE_SIZE),
323 | PROFILE_CONNECT_BASE = (PROFILE_BASE + RANGE_SIZE / 2),
324 | PROFILE_END = (PROFILE_BASE + RANGE_SIZE - 1),
325 |
326 | // range for MSM
327 | //
328 | MSM_BASE = 0x10000 + (2 * RANGE_SIZE),
329 | MSM_CONNECT_BASE = (MSM_BASE + RANGE_SIZE / 2),
330 | MSM_END = (MSM_BASE + RANGE_SIZE - 1),
331 |
332 | // range for MSMSEC
333 | //
334 | MSMSEC_BASE = 0x10000 + (3 * RANGE_SIZE),
335 | MSMSEC_CONNECT_BASE = (MSMSEC_BASE + RANGE_SIZE / 2),
336 | MSMSEC_END = (MSMSEC_BASE + RANGE_SIZE - 1),
337 |
338 | // AC network incompatible reason codes
339 | //
340 | NETWORK_NOT_COMPATIBLE = (AC_BASE + 1),
341 | PROFILE_NOT_COMPATIBLE = (AC_BASE + 2),
342 |
343 | // AC connect reason code
344 | //
345 | NO_AUTO_CONNECTION = (AC_CONNECT_BASE + 1),
346 | NOT_VISIBLE = (AC_CONNECT_BASE + 2),
347 | GP_DENIED = (AC_CONNECT_BASE + 3),
348 | USER_DENIED = (AC_CONNECT_BASE + 4),
349 | BSS_TYPE_NOT_ALLOWED = (AC_CONNECT_BASE + 5),
350 | IN_FAILED_LIST = (AC_CONNECT_BASE + 6),
351 | IN_BLOCKED_LIST = (AC_CONNECT_BASE + 7),
352 | SSID_LIST_TOO_LONG = (AC_CONNECT_BASE + 8),
353 | CONNECT_CALL_FAIL = (AC_CONNECT_BASE + 9),
354 | SCAN_CALL_FAIL = (AC_CONNECT_BASE + 10),
355 | NETWORK_NOT_AVAILABLE = (AC_CONNECT_BASE + 11),
356 | PROFILE_CHANGED_OR_DELETED = (AC_CONNECT_BASE + 12),
357 | KEY_MISMATCH = (AC_CONNECT_BASE + 13),
358 | USER_NOT_RESPOND = (AC_CONNECT_BASE + 14),
359 |
360 | // Profile validation errors
361 | //
362 | INVALID_PROFILE_SCHEMA = (PROFILE_BASE + 1),
363 | PROFILE_MISSING = (PROFILE_BASE + 2),
364 | INVALID_PROFILE_NAME = (PROFILE_BASE + 3),
365 | INVALID_PROFILE_TYPE = (PROFILE_BASE + 4),
366 | INVALID_PHY_TYPE = (PROFILE_BASE + 5),
367 | MSM_SECURITY_MISSING = (PROFILE_BASE + 6),
368 | IHV_SECURITY_NOT_SUPPORTED = (PROFILE_BASE + 7),
369 | IHV_OUI_MISMATCH = (PROFILE_BASE + 8),
370 | // IHV OUI not present but there is IHV settings in profile
371 | IHV_OUI_MISSING = (PROFILE_BASE + 9),
372 | // IHV OUI is present but there is no IHV settings in profile
373 | IHV_SETTINGS_MISSING = (PROFILE_BASE + 10),
374 | // both/conflict MSMSec and IHV security settings exist in profile
375 | CONFLICT_SECURITY = (PROFILE_BASE + 11),
376 | // no IHV or MSMSec security settings in profile
377 | SECURITY_MISSING = (PROFILE_BASE + 12),
378 | INVALID_BSS_TYPE = (PROFILE_BASE + 13),
379 | INVALID_ADHOC_CONNECTION_MODE = (PROFILE_BASE + 14),
380 | NON_BROADCAST_SET_FOR_ADHOC = (PROFILE_BASE + 15),
381 | AUTO_SWITCH_SET_FOR_ADHOC = (PROFILE_BASE + 16),
382 | AUTO_SWITCH_SET_FOR_MANUAL_CONNECTION = (PROFILE_BASE + 17),
383 | IHV_SECURITY_ONEX_MISSING = (PROFILE_BASE + 18),
384 | PROFILE_SSID_INVALID = (PROFILE_BASE + 19),
385 | TOO_MANY_SSID = (PROFILE_BASE + 20),
386 |
387 | // MSM network incompatible reasons
388 | //
389 | UNSUPPORTED_SECURITY_SET_BY_OS = (MSM_BASE + 1),
390 | UNSUPPORTED_SECURITY_SET = (MSM_BASE + 2),
391 | BSS_TYPE_UNMATCH = (MSM_BASE + 3),
392 | PHY_TYPE_UNMATCH = (MSM_BASE + 4),
393 | DATARATE_UNMATCH = (MSM_BASE + 5),
394 |
395 | // MSM connection failure reasons, to be defined
396 | // failure reason codes
397 | //
398 | // user called to disconnect
399 | USER_CANCELLED = (MSM_CONNECT_BASE + 1),
400 | // got disconnect while associating
401 | ASSOCIATION_FAILURE = (MSM_CONNECT_BASE + 2),
402 | // timeout for association
403 | ASSOCIATION_TIMEOUT = (MSM_CONNECT_BASE + 3),
404 | // pre-association security completed with failure
405 | PRE_SECURITY_FAILURE = (MSM_CONNECT_BASE + 4),
406 | // fail to start post-association security
407 | START_SECURITY_FAILURE = (MSM_CONNECT_BASE + 5),
408 | // post-association security completed with failure
409 | SECURITY_FAILURE = (MSM_CONNECT_BASE + 6),
410 | // security watchdog timeout
411 | SECURITY_TIMEOUT = (MSM_CONNECT_BASE + 7),
412 | // got disconnect from driver when roaming
413 | ROAMING_FAILURE = (MSM_CONNECT_BASE + 8),
414 | // failed to start security for roaming
415 | ROAMING_SECURITY_FAILURE = (MSM_CONNECT_BASE + 9),
416 | // failed to start security for adhoc-join
417 | ADHOC_SECURITY_FAILURE = (MSM_CONNECT_BASE + 10),
418 | // got disconnection from driver
419 | DRIVER_DISCONNECTED = (MSM_CONNECT_BASE + 11),
420 | // driver operation failed
421 | DRIVER_OPERATION_FAILURE = (MSM_CONNECT_BASE + 12),
422 | // Ihv service is not available
423 | IHV_NOT_AVAILABLE = (MSM_CONNECT_BASE + 13),
424 | // Response from ihv timed out
425 | IHV_NOT_RESPONDING = (MSM_CONNECT_BASE + 14),
426 | // Timed out waiting for driver to disconnect
427 | DISCONNECT_TIMEOUT = (MSM_CONNECT_BASE + 15),
428 | // An internal error prevented the operation from being completed.
429 | INTERNAL_FAILURE = (MSM_CONNECT_BASE + 16),
430 | // UI Request timed out.
431 | UI_REQUEST_TIMEOUT = (MSM_CONNECT_BASE + 17),
432 | // Roaming too often, post security is not completed after 5 times.
433 | TOO_MANY_SECURITY_ATTEMPTS = (MSM_CONNECT_BASE + 18),
434 |
435 | // MSMSEC reason codes
436 | //
437 |
438 | MSMSEC_MIN = MSMSEC_BASE,
439 |
440 | // Key index specified is not valid
441 | MSMSEC_PROFILE_INVALID_KEY_INDEX = (MSMSEC_BASE + 1),
442 | // Key required, PSK present
443 | MSMSEC_PROFILE_PSK_PRESENT = (MSMSEC_BASE + 2),
444 | // Invalid key length
445 | MSMSEC_PROFILE_KEY_LENGTH = (MSMSEC_BASE + 3),
446 | // Invalid PSK length
447 | MSMSEC_PROFILE_PSK_LENGTH = (MSMSEC_BASE + 4),
448 | // No auth/cipher specified
449 | MSMSEC_PROFILE_NO_AUTH_CIPHER_SPECIFIED = (MSMSEC_BASE + 5),
450 | // Too many auth/cipher specified
451 | MSMSEC_PROFILE_TOO_MANY_AUTH_CIPHER_SPECIFIED = (MSMSEC_BASE + 6),
452 | // Profile contains duplicate auth/cipher
453 | MSMSEC_PROFILE_DUPLICATE_AUTH_CIPHER = (MSMSEC_BASE + 7),
454 | // Profile raw data is invalid (1x or key data)
455 | MSMSEC_PROFILE_RAWDATA_INVALID = (MSMSEC_BASE + 8),
456 | // Invalid auth/cipher combination
457 | MSMSEC_PROFILE_INVALID_AUTH_CIPHER = (MSMSEC_BASE + 9),
458 | // 802.1x disabled when it's required to be enabled
459 | MSMSEC_PROFILE_ONEX_DISABLED = (MSMSEC_BASE + 10),
460 | // 802.1x enabled when it's required to be disabled
461 | MSMSEC_PROFILE_ONEX_ENABLED = (MSMSEC_BASE + 11),
462 | MSMSEC_PROFILE_INVALID_PMKCACHE_MODE = (MSMSEC_BASE + 12),
463 | MSMSEC_PROFILE_INVALID_PMKCACHE_SIZE = (MSMSEC_BASE + 13),
464 | MSMSEC_PROFILE_INVALID_PMKCACHE_TTL = (MSMSEC_BASE + 14),
465 | MSMSEC_PROFILE_INVALID_PREAUTH_MODE = (MSMSEC_BASE + 15),
466 | MSMSEC_PROFILE_INVALID_PREAUTH_THROTTLE = (MSMSEC_BASE + 16),
467 | // PreAuth enabled when PMK cache is disabled
468 | MSMSEC_PROFILE_PREAUTH_ONLY_ENABLED = (MSMSEC_BASE + 17),
469 | // Capability matching failed at network
470 | MSMSEC_CAPABILITY_NETWORK = (MSMSEC_BASE + 18),
471 | // Capability matching failed at NIC
472 | MSMSEC_CAPABILITY_NIC = (MSMSEC_BASE + 19),
473 | // Capability matching failed at profile
474 | MSMSEC_CAPABILITY_PROFILE = (MSMSEC_BASE + 20),
475 | // Network does not support specified discovery type
476 | MSMSEC_CAPABILITY_DISCOVERY = (MSMSEC_BASE + 21),
477 | // Passphrase contains invalid character
478 | MSMSEC_PROFILE_PASSPHRASE_CHAR = (MSMSEC_BASE + 22),
479 | // Key material contains invalid character
480 | MSMSEC_PROFILE_KEYMATERIAL_CHAR = (MSMSEC_BASE + 23),
481 | // Wrong key type specified for the auth/cipher pair
482 | MSMSEC_PROFILE_WRONG_KEYTYPE = (MSMSEC_BASE + 24),
483 | // "Mixed cell" suspected (AP not beaconing privacy, we have privacy enabled profile)
484 | MSMSEC_MIXED_CELL = (MSMSEC_BASE + 25),
485 | // Auth timers or number of timeouts in profile is incorrect
486 | MSMSEC_PROFILE_AUTH_TIMERS_INVALID = (MSMSEC_BASE + 26),
487 | // Group key update interval in profile is incorrect
488 | MSMSEC_PROFILE_INVALID_GKEY_INTV = (MSMSEC_BASE + 27),
489 | // "Transition network" suspected, trying legacy 802.11 security
490 | MSMSEC_TRANSITION_NETWORK = (MSMSEC_BASE + 28),
491 | // Key contains characters which do not map to ASCII
492 | MSMSEC_PROFILE_KEY_UNMAPPED_CHAR = (MSMSEC_BASE + 29),
493 | // Capability matching failed at profile (auth not found)
494 | MSMSEC_CAPABILITY_PROFILE_AUTH = (MSMSEC_BASE + 30),
495 | // Capability matching failed at profile (cipher not found)
496 | MSMSEC_CAPABILITY_PROFILE_CIPHER = (MSMSEC_BASE + 31),
497 |
498 | // Failed to queue UI request
499 | MSMSEC_UI_REQUEST_FAILURE = (MSMSEC_CONNECT_BASE + 1),
500 | // 802.1x authentication did not start within configured time
501 | MSMSEC_AUTH_START_TIMEOUT = (MSMSEC_CONNECT_BASE + 2),
502 | // 802.1x authentication did not complete within configured time
503 | MSMSEC_AUTH_SUCCESS_TIMEOUT = (MSMSEC_CONNECT_BASE + 3),
504 | // Dynamic key exchange did not start within configured time
505 | MSMSEC_KEY_START_TIMEOUT = (MSMSEC_CONNECT_BASE + 4),
506 | // Dynamic key exchange did not succeed within configured time
507 | MSMSEC_KEY_SUCCESS_TIMEOUT = (MSMSEC_CONNECT_BASE + 5),
508 | // Message 3 of 4 way handshake has no key data (RSN/WPA)
509 | MSMSEC_M3_MISSING_KEY_DATA = (MSMSEC_CONNECT_BASE + 6),
510 | // Message 3 of 4 way handshake has no IE (RSN/WPA)
511 | MSMSEC_M3_MISSING_IE = (MSMSEC_CONNECT_BASE + 7),
512 | // Message 3 of 4 way handshake has no Group Key (RSN)
513 | MSMSEC_M3_MISSING_GRP_KEY = (MSMSEC_CONNECT_BASE + 8),
514 | // Matching security capabilities of IE in M3 failed (RSN/WPA)
515 | MSMSEC_PR_IE_MATCHING = (MSMSEC_CONNECT_BASE + 9),
516 | // Matching security capabilities of Secondary IE in M3 failed (RSN)
517 | MSMSEC_SEC_IE_MATCHING = (MSMSEC_CONNECT_BASE + 10),
518 | // Required a pairwise key but AP configured only group keys
519 | MSMSEC_NO_PAIRWISE_KEY = (MSMSEC_CONNECT_BASE + 11),
520 | // Message 1 of group key handshake has no key data (RSN/WPA)
521 | MSMSEC_G1_MISSING_KEY_DATA = (MSMSEC_CONNECT_BASE + 12),
522 | // Message 1 of group key handshake has no group key
523 | MSMSEC_G1_MISSING_GRP_KEY = (MSMSEC_CONNECT_BASE + 13),
524 | // AP reset secure bit after connection was secured
525 | MSMSEC_PEER_INDICATED_INSECURE = (MSMSEC_CONNECT_BASE + 14),
526 | // 802.1x indicated there is no authenticator but profile requires 802.1x
527 | MSMSEC_NO_AUTHENTICATOR = (MSMSEC_CONNECT_BASE + 15),
528 | // Plumbing settings to NIC failed
529 | MSMSEC_NIC_FAILURE = (MSMSEC_CONNECT_BASE + 16),
530 | // Operation was cancelled by caller
531 | MSMSEC_CANCELLED = (MSMSEC_CONNECT_BASE + 17),
532 | // Key was in incorrect format
533 | MSMSEC_KEY_FORMAT = (MSMSEC_CONNECT_BASE + 18),
534 | // Security downgrade detected
535 | MSMSEC_DOWNGRADE_DETECTED = (MSMSEC_CONNECT_BASE + 19),
536 | // PSK mismatch suspected
537 | MSMSEC_PSK_MISMATCH_SUSPECTED = (MSMSEC_CONNECT_BASE + 20),
538 | // Forced failure because connection method was not secure
539 | MSMSEC_FORCED_FAILURE = (MSMSEC_CONNECT_BASE + 21),
540 | // ui request couldn't be queued or user pressed cancel
541 | MSMSEC_SECURITY_UI_FAILURE = (MSMSEC_CONNECT_BASE + 22),
542 |
543 | MSMSEC_MAX = MSMSEC_END
544 | }
545 |
546 |
547 | ///
548 | /// Indicates the state of an interface.
549 | ///
550 | ///
551 | /// Corresponds to the native WLAN_INTERFACE_STATE type.
552 | ///
553 | public enum WlanInterfaceState
554 | {
555 | ///
556 | /// The interface is not ready to operate.
557 | ///
558 | NotReady = 0,
559 | ///
560 | /// The interface is connected to a network.
561 | ///
562 | Connected = 1,
563 | ///
564 | /// The interface is the first node in an ad hoc network. No peer has connected.
565 | ///
566 | AdHocNetworkFormed = 2,
567 | ///
568 | /// The interface is disconnecting from the current network.
569 | ///
570 | Disconnecting = 3,
571 | ///
572 | /// The interface is not connected to any network.
573 | ///
574 | Disconnected = 4,
575 | ///
576 | /// The interface is attempting to associate with a network.
577 | ///
578 | Associating = 5,
579 | ///
580 | /// Auto configuration is discovering the settings for the network.
581 | ///
582 | Discovering = 6,
583 | ///
584 | /// The interface is in the process of authenticating.
585 | ///
586 | Authenticating = 7
587 | }
588 |
589 |
590 | ///
591 | /// Defines an 802.11 PHY and media type.
592 | ///
593 | ///
594 | /// Corresponds to the native DOT11_PHY_TYPE type.
595 | ///
596 | public enum Dot11PhyType : uint
597 | {
598 | ///
599 | /// Specifies an unknown or uninitialized PHY type.
600 | ///
601 | Unknown = 0,
602 | ///
603 | /// Specifies any PHY type.
604 | ///
605 | Any = Unknown,
606 | ///
607 | /// Specifies a frequency-hopping spread-spectrum (FHSS) PHY. Bluetooth devices can use FHSS or an adaptation of FHSS.
608 | ///
609 | FHSS = 1,
610 | ///
611 | /// Specifies a direct sequence spread spectrum (DSSS) PHY.
612 | ///
613 | DSSS = 2,
614 | ///
615 | /// Specifies an infrared (IR) baseband PHY.
616 | ///
617 | IrBaseband = 3,
618 | ///
619 | /// Specifies an orthogonal frequency division multiplexing (OFDM) PHY. 802.11a devices can use OFDM.
620 | ///
621 | OFDM = 4,
622 | ///
623 | /// Specifies a high-rate DSSS (HRDSSS) PHY.
624 | ///
625 | HRDSSS = 5,
626 | ///
627 | /// Specifies an extended rate PHY (ERP). 802.11g devices can use ERP.
628 | ///
629 | ERP = 6,
630 | ///
631 | /// Specifies the start of the range that is used to define PHY types that are developed by an independent hardware vendor (IHV).
632 | ///
633 | IHV_Start = 0x80000000,
634 | ///
635 | /// Specifies the end of the range that is used to define PHY types that are developed by an independent hardware vendor (IHV).
636 | ///
637 | IHV_End = 0xffffffff
638 | }
639 |
640 | ///
641 | /// Defines a basic service set (BSS) network type.
642 | ///
643 | ///
644 | /// Corresponds to the native DOT11_BSS_TYPE type.
645 | ///
646 | public enum Dot11BssType
647 | {
648 | ///
649 | /// Specifies an infrastructure BSS network.
650 | ///
651 | Infrastructure = 1,
652 | ///
653 | /// Specifies an independent BSS (IBSS) network.
654 | ///
655 | Independent = 2,
656 | ///
657 | /// Specifies either infrastructure or IBSS network.
658 | ///
659 | Any = 3
660 | }
661 |
662 |
663 | ///
664 | /// Defines the mode of connection.
665 | ///
666 | ///
667 | /// Corresponds to the native WLAN_CONNECTION_MODE type.
668 | ///
669 | public enum WlanConnectionMode
670 | {
671 | ///
672 | /// A profile will be used to make the connection.
673 | ///
674 | Profile = 0,
675 | ///
676 | /// A temporary profile will be used to make the connection.
677 | ///
678 | TemporaryProfile,
679 | ///
680 | /// Secure discovery will be used to make the connection.
681 | ///
682 | DiscoverySecure,
683 | ///
684 | /// Unsecure discovery will be used to make the connection.
685 | ///
686 | DiscoveryUnsecure,
687 | ///
688 | /// A connection will be made automatically, generally using a persistent profile.
689 | ///
690 | Auto,
691 | ///
692 | /// Not used.
693 | ///
694 | Invalid
695 | }
696 |
697 | ///
698 | /// Defines a wireless LAN authentication algorithm.
699 | ///
700 | ///
701 | /// Corresponds to the native DOT11_AUTH_ALGORITHM type.
702 | ///
703 | public enum Dot11AuthAlgorithm : uint
704 | {
705 | ///
706 | /// Specifies an IEEE 802.11 Open System authentication algorithm.
707 | ///
708 | IEEE80211_Open = 1,
709 | ///
710 | /// Specifies an 802.11 Shared Key authentication algorithm that requires the use of a pre-shared Wired Equivalent Privacy (WEP) key for the 802.11 authentication.
711 | ///
712 | IEEE80211_SharedKey = 2,
713 | ///
714 | /// Specifies a Wi-Fi Protected Access (WPA) algorithm. IEEE 802.1X port authentication is performed by the supplicant, authenticator, and authentication server. Cipher keys are dynamically derived through the authentication process.
715 | /// This algorithm is valid only for BSS types of .
716 | /// When the WPA algorithm is enabled, the 802.11 station will associate only with an access point whose beacon or probe responses contain the authentication suite of type 1 (802.1X) within the WPA information element (IE).
717 | ///
718 | WPA = 3,
719 | ///
720 | /// Specifies a WPA algorithm that uses preshared keys (PSK). IEEE 802.1X port authentication is performed by the supplicant and authenticator. Cipher keys are dynamically derived through a preshared key that is used on both the supplicant and authenticator.
721 | /// This algorithm is valid only for BSS types of .
722 | /// When the WPA PSK algorithm is enabled, the 802.11 station will associate only with an access point whose beacon or probe responses contain the authentication suite of type 2 (preshared key) within the WPA IE.
723 | ///
724 | WPA_PSK = 4,
725 | ///
726 | /// This value is not supported.
727 | ///
728 | WPA_None = 5,
729 | ///
730 | /// Specifies an 802.11i Robust Security Network Association (RSNA) algorithm. WPA2 is one such algorithm. IEEE 802.1X port authentication is performed by the supplicant, authenticator, and authentication server. Cipher keys are dynamically derived through the authentication process.
731 | /// This algorithm is valid only for BSS types of .
732 | /// When the RSNA algorithm is enabled, the 802.11 station will associate only with an access point whose beacon or probe responses contain the authentication suite of type 1 (802.1X) within the RSN IE.
733 | ///
734 | RSNA = 6,
735 | ///
736 | /// Specifies an 802.11i RSNA algorithm that uses PSK. IEEE 802.1X port authentication is performed by the supplicant and authenticator. Cipher keys are dynamically derived through a preshared key that is used on both the supplicant and authenticator.
737 | /// This algorithm is valid only for BSS types of .
738 | /// When the RSNA PSK algorithm is enabled, the 802.11 station will associate only with an access point whose beacon or probe responses contain the authentication suite of type 2(preshared key) within the RSN IE.
739 | ///
740 | RSNA_PSK = 7,
741 | ///
742 | /// Indicates the start of the range that specifies proprietary authentication algorithms that are developed by an IHV.
743 | ///
744 | ///
745 | /// This enumerator is valid only when the miniport driver is operating in Extensible Station (ExtSTA) mode.
746 | ///
747 | IHV_Start = 0x80000000,
748 | ///
749 | /// Indicates the end of the range that specifies proprietary authentication algorithms that are developed by an IHV.
750 | ///
751 | ///
752 | /// This enumerator is valid only when the miniport driver is operating in Extensible Station (ExtSTA) mode.
753 | ///
754 | IHV_End = 0xffffffff
755 | }
756 |
757 | ///
758 | /// Defines a cipher algorithm for data encryption and decryption.
759 | ///
760 | ///
761 | /// Corresponds to the native DOT11_CIPHER_ALGORITHM type.
762 | ///
763 | public enum Dot11CipherAlgorithm : uint
764 | {
765 | ///
766 | /// Specifies that no cipher algorithm is enabled or supported.
767 | ///
768 | None = 0x00,
769 | ///
770 | /// Specifies a Wired Equivalent Privacy (WEP) algorithm, which is the RC4-based algorithm that is specified in the 802.11-1999 standard. This enumerator specifies the WEP cipher algorithm with a 40-bit cipher key.
771 | ///
772 | WEP40 = 0x01,
773 | ///
774 | /// Specifies a Temporal Key Integrity Protocol (TKIP) algorithm, which is the RC4-based cipher suite that is based on the algorithms that are defined in the WPA specification and IEEE 802.11i-2004 standard. This cipher also uses the Michael Message Integrity Code (MIC) algorithm for forgery protection.
775 | ///
776 | TKIP = 0x02,
777 | ///
778 | /// Specifies an AES-CCMP algorithm, as specified in the IEEE 802.11i-2004 standard and RFC 3610. Advanced Encryption Standard (AES) is the encryption algorithm defined in FIPS PUB 197.
779 | ///
780 | CCMP = 0x04,
781 | ///
782 | /// Specifies a WEP cipher algorithm with a 104-bit cipher key.
783 | ///
784 | WEP104 = 0x05,
785 | ///
786 | /// Specifies a Robust Security Network (RSN) Use Group Key cipher suite. For more information about the Use Group Key cipher suite, refer to Clause 7.3.2.9.1 of the IEEE 802.11i-2004 standard.
787 | ///
788 | WPA_UseGroup = 0x100,
789 | ///
790 | /// Specifies a Wifi Protected Access (WPA) Use Group Key cipher suite. For more information about the Use Group Key cipher suite, refer to Clause 7.3.2.9.1 of the IEEE 802.11i-2004 standard.
791 | ///
792 | RSN_UseGroup = 0x100,
793 | ///
794 | /// Specifies a WEP cipher algorithm with a cipher key of any length.
795 | ///
796 | WEP = 0x101,
797 | ///
798 | /// Specifies the start of the range that is used to define proprietary cipher algorithms that are developed by an independent hardware vendor (IHV).
799 | ///
800 | IHV_Start = 0x80000000,
801 | ///
802 | /// Specifies the end of the range that is used to define proprietary cipher algorithms that are developed by an IHV.
803 | ///
804 | IHV_End = 0xffffffff
805 | }
806 |
807 | ///
808 | /// Flags that specifiy the miniport driver's current operation mode.
809 | ///
810 | [Flags]
811 | public enum Dot11OperationMode : uint
812 | {
813 | Unknown = 0x00000000,
814 | Station = 0x00000001,
815 | AP = 0x00000002,
816 | ///
817 | /// Specifies that the miniport driver supports the Extensible Station (ExtSTA) operation mode.
818 | ///
819 | ExtensibleStation = 0x00000004,
820 | ///
821 | /// Specifies that the miniport driver supports the Network Monitor (NetMon) operation mode.
822 | ///
823 | NetworkMonitor = 0x80000000
824 | }
825 |
826 |
827 | ///
828 | /// A set of flags that modify the behavior of the function: WlanSetProfileEapUserData
829 | ///
830 | /// On Windows Vista and Windows Server 2008, this parameter is reserved and should be set to zero.
831 | /// On Windows 7, Windows Server 2008 R2, and later, this parameter can be one of the following values.
832 | ///
833 | [Flags]
834 | public enum SetEapUserDataMode : uint
835 | {
836 | None = 0x00000000,
837 | WlanSetEaphostDataAllUsers = 0x00000001
838 | }
839 | }
840 |
--------------------------------------------------------------------------------
/SimpleWifi/Win32/Interop/Exceptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 |
6 | namespace SimpleWifi.Win32.Interop
7 | {
8 | ///
9 | /// Represents an error occuring during WLAN operations which indicate their failure via a .
10 | ///
11 | public class WlanException : Exception
12 | {
13 | private WlanReasonCode reasonCode;
14 |
15 | WlanException(WlanReasonCode reasonCode)
16 | {
17 | this.reasonCode = reasonCode;
18 | }
19 |
20 | ///
21 | /// Gets the WLAN reason code.
22 | ///
23 | /// The WLAN reason code.
24 | public WlanReasonCode ReasonCode
25 | {
26 | get { return reasonCode; }
27 | }
28 |
29 | ///
30 | /// Gets a message that describes the reason code.
31 | ///
32 | ///
33 | /// The error message that explains the reason for the exception, or an empty string("").
34 | public override string Message
35 | {
36 | get
37 | {
38 | StringBuilder sb = new StringBuilder(1024);
39 |
40 | if (WlanInterop.WlanReasonCodeToString(reasonCode, sb.Capacity, sb, IntPtr.Zero) == 0)
41 | return sb.ToString();
42 | else
43 | return string.Empty;
44 | }
45 | }
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/SimpleWifi/Win32/Interop/Interop.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Net.NetworkInformation;
4 | using System.Text;
5 | using System.Diagnostics;
6 | using System.ComponentModel;
7 |
8 | namespace SimpleWifi.Win32.Interop
9 | {
10 | // TODO: Separate the functions and the structs/enums. Many of the structs/enums should remain public
11 | // (since they're reused in the OOP interfaces) -- the rest (including all P/Invoke function mappings)
12 | // should become internal.
13 |
14 | // All structures which native methods rely on should be kept in the Wlan class.
15 | // Only change the layout of those structures if it matches the native API documentation.
16 | // Some structures might have helper properties but adding or changing fields is prohibited.
17 | // This class is not documented since all the documentation resides in the MSDN. The code
18 | // documentation only covers details which concern interop users.
19 | // Some identifier names were modified to correspond to .NET naming conventions
20 | // but otherwise retain their native meaning.
21 |
22 | ///
23 | /// Defines the Native Wifi API through P/Invoke interop.
24 | ///
25 | ///
26 | /// This class is intended for internal use. Use the class instead.
27 | ///
28 | internal static class WlanInterop
29 | {
30 | #region P/Invoke API
31 |
32 | public const uint WLAN_CLIENT_VERSION_XP_SP2 = 1;
33 | public const uint WLAN_CLIENT_VERSION_LONGHORN = 2;
34 |
35 | [DllImport("wlanapi.dll")]
36 | public static extern int WlanOpenHandle(
37 | [In] UInt32 clientVersion,
38 | [In, Out] IntPtr pReserved,
39 | [Out] out UInt32 negotiatedVersion,
40 | [Out] out IntPtr clientHandle);
41 |
42 | [DllImport("wlanapi.dll")]
43 | public static extern int WlanCloseHandle(
44 | [In] IntPtr clientHandle,
45 | [In, Out] IntPtr pReserved);
46 |
47 | [DllImport("wlanapi.dll")]
48 | public static extern int WlanEnumInterfaces(
49 | [In] IntPtr clientHandle,
50 | [In, Out] IntPtr pReserved,
51 | [Out] out IntPtr ppInterfaceList);
52 |
53 | [DllImport("wlanapi.dll")]
54 | public static extern int WlanQueryInterface(
55 | [In] IntPtr clientHandle,
56 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
57 | [In] WlanIntfOpcode opCode,
58 | [In, Out] IntPtr pReserved,
59 | [Out] out int dataSize,
60 | [Out] out IntPtr ppData,
61 | [Out] out WlanOpcodeValueType wlanOpcodeValueType);
62 |
63 | [DllImport("wlanapi.dll")]
64 | public static extern int WlanSetInterface(
65 | [In] IntPtr clientHandle,
66 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
67 | [In] WlanIntfOpcode opCode,
68 | [In] uint dataSize,
69 | [In] IntPtr pData,
70 | [In, Out] IntPtr pReserved);
71 |
72 | /// Not supported on Windows XP SP2: must be a null reference.
73 | /// Not supported on Windows XP SP2: must be a null reference.
74 | [DllImport("wlanapi.dll")]
75 | public static extern int WlanScan(
76 | [In] IntPtr clientHandle,
77 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
78 | [In] IntPtr pDot11Ssid,
79 | [In] IntPtr pIeData,
80 | [In, Out] IntPtr pReserved);
81 |
82 | [DllImport("wlanapi.dll")]
83 | public static extern int WlanGetAvailableNetworkList(
84 | [In] IntPtr clientHandle,
85 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
86 | [In] WlanGetAvailableNetworkFlags flags,
87 | [In, Out] IntPtr reservedPtr,
88 | [Out] out IntPtr availableNetworkListPtr);
89 |
90 |
91 | [DllImport("wlanapi.dll")]
92 | public static extern int WlanSetProfile(
93 | [In] IntPtr clientHandle,
94 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
95 | [In] WlanProfileFlags flags,
96 | [In, MarshalAs(UnmanagedType.LPWStr)] string profileXml,
97 | [In, Optional, MarshalAs(UnmanagedType.LPWStr)] string allUserProfileSecurity,
98 | [In] bool overwrite,
99 | [In] IntPtr pReserved,
100 | [Out] out WlanReasonCode reasonCode);
101 |
102 | /// Not supported on Windows XP SP2: must be a null reference.
103 | [DllImport("wlanapi.dll")]
104 | public static extern int WlanGetProfile(
105 | [In] IntPtr clientHandle,
106 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
107 | [In, MarshalAs(UnmanagedType.LPWStr)] string profileName,
108 | [In] IntPtr pReserved,
109 | [Out] out IntPtr profileXml,
110 | [Out, Optional] out WlanProfileFlags flags,
111 | [Out, Optional] out WlanAccess grantedAccess);
112 |
113 | [DllImport("wlanapi.dll")]
114 | public static extern int WlanGetProfileList(
115 | [In] IntPtr clientHandle,
116 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
117 | [In] IntPtr pReserved,
118 | [Out] out IntPtr profileList
119 | );
120 |
121 | [DllImport("wlanapi.dll")]
122 | public static extern void WlanFreeMemory(IntPtr pMemory);
123 |
124 | [DllImport("wlanapi.dll")]
125 | public static extern int WlanReasonCodeToString(
126 | [In] WlanReasonCode reasonCode,
127 | [In] int bufferSize,
128 | [In, Out] StringBuilder stringBuffer,
129 | IntPtr pReserved
130 | );
131 |
132 | ///
133 | /// Defines the callback function which accepts WLAN notifications.
134 | ///
135 | public delegate void WlanNotificationCallbackDelegate(ref WlanNotificationData notificationData, IntPtr context);
136 |
137 | [DllImport("wlanapi.dll")]
138 | public static extern int WlanRegisterNotification(
139 | [In] IntPtr clientHandle,
140 | [In] WlanNotificationSource notifSource,
141 | [In] bool ignoreDuplicate,
142 | [In] WlanNotificationCallbackDelegate funcCallback,
143 | [In] IntPtr callbackContext,
144 | [In] IntPtr reserved,
145 | [Out] out WlanNotificationSource prevNotifSource);
146 |
147 | [DllImport("wlanapi.dll")]
148 | public static extern int WlanConnect(
149 | [In] IntPtr clientHandle,
150 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
151 | [In] ref WlanConnectionParameters connectionParameters,
152 | IntPtr pReserved);
153 |
154 | [DllImport("wlanapi.dll")]
155 | public static extern int WlanDeleteProfile(
156 | [In] IntPtr clientHandle,
157 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
158 | [In, MarshalAs(UnmanagedType.LPWStr)] string profileName,
159 | IntPtr reservedPtr
160 | );
161 |
162 | [DllImport("wlanapi.dll")]
163 | public static extern int WlanDisconnect(
164 | [In] IntPtr clientHandle,
165 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
166 | IntPtr pReserved);
167 |
168 | [DllImport("wlanapi.dll")]
169 | public static extern int WlanGetNetworkBssList(
170 | [In] IntPtr clientHandle,
171 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
172 | [In] IntPtr dot11SsidInt,
173 | [In] Dot11BssType dot11BssType,
174 | [In] bool securityEnabled,
175 | IntPtr reservedPtr,
176 | [Out] out IntPtr wlanBssList
177 | );
178 |
179 | /*
180 | DWORD WlanSetProfileEapUserData(
181 | _In_ HANDLE hClientHandle,
182 | _In_ const GUID *pInterfaceGuid,
183 | _In_ LPCWSTR strProfileName,
184 | _In_ EAP_METHOD_TYPE eapType,
185 | _In_ DWORD dwFlags,
186 | _In_ DWORD dwEapUserDataSize,
187 | _In_ const LPBYTE pbEapUserData,
188 | _Reserved_ PVOID pReserved
189 | );
190 | */
191 |
192 | // Link: http://msdn.microsoft.com/en-us/library/windows/desktop/ms706797(v=vs.85).aspx
193 | /*[DllImport("wlanapi.dll")]
194 | public static extern int WlanSetProfileEapUserData(
195 | [In] IntPtr clientHandle,
196 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid,
197 | [In, MarshalAs(UnmanagedType.LPWStr)] string profileName,
198 | [In] EapMethodType eapType, // EAP_METHOD_TYPE
199 | [In] SetEapUserDataMode dwFlags,
200 | [In] uint dwEapUserDataSize,
201 | [In] byte[] pbEapUserData, // Not sure if this is correct, const LPBYTE pbEapUserData,
202 | IntPtr reservedPtr
203 | );*/
204 |
205 | /*
206 | DWORD WlanSetProfileEapXmlUserData(
207 | _In_ HANDLE hClientHandle,
208 | _In_ const GUID *pInterfaceGuid,
209 | _In_ LPCWSTR strProfileName,
210 | _In_ DWORD dwFlags,
211 | _In_ LPCWSTR strEapXmlUserData,
212 | _Reserved_ PVOID pReserved
213 | );
214 | */
215 |
216 | [DllImport("wlanapi.dll")]
217 | public static extern int WlanSetProfileEapXmlUserData(
218 | [In] IntPtr clientHandle, // The client's session handle, obtained by a previous call to the WlanOpenHandle function.
219 | [In, MarshalAs(UnmanagedType.LPStruct)] Guid interfaceGuid, // The GUID of the interface.
220 | [In, MarshalAs(UnmanagedType.LPWStr)] string profileName, // The name of the profile associated with the EAP user data. Profile names are case-sensitive. This string must be NULL-terminated.
221 | [In] SetEapUserDataMode dwFlags, // A set of flags that modify the behavior of the function.
222 | [In, MarshalAs(UnmanagedType.LPWStr)] string userDataXML, // A pointer to XML data used to set the user credentials, The XML data must be based on the EAPHost User Credentials schema. To view sample user credential XML data, see EAPHost User Properties: http://msdn.microsoft.com/en-us/library/windows/desktop/bb204765(v=vs.85).aspx
223 | IntPtr reservedPtr
224 | );
225 |
226 | #endregion
227 |
228 | ///
229 | /// Helper method to wrap calls to Native WiFi API methods.
230 | /// If the method falls, throws an exception containing the error code.
231 | ///
232 | /// The error code.
233 | [DebuggerStepThrough]
234 | internal static void ThrowIfError(int win32ErrorCode)
235 | {
236 | if (win32ErrorCode != 0)
237 | throw new Win32Exception(win32ErrorCode);
238 | }
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/SimpleWifi/Win32/Interop/Structs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Net.NetworkInformation;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 |
8 | namespace SimpleWifi.Win32.Interop
9 | {
10 |
11 | ///
12 | /// The header of an array of information about available networks.
13 | ///
14 | [StructLayout(LayoutKind.Sequential)]
15 | internal struct WlanAvailableNetworkListHeader
16 | {
17 | ///
18 | /// Contains the number of items following the header.
19 | ///
20 | public uint numberOfItems;
21 | ///
22 | /// The index of the current item. The index of the first item is 0.
23 | ///
24 | public uint index;
25 | }
26 |
27 | ///
28 | /// Contains information about an available wireless network.
29 | ///
30 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
31 | public struct WlanAvailableNetwork
32 | {
33 | ///
34 | /// Contains the profile name associated with the network.
35 | /// If the network doesn't have a profile, this member will be empty.
36 | /// If multiple profiles are associated with the network, there will be multiple entries with the same SSID in the visible network list. Profile names are case-sensitive.
37 | ///
38 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
39 | public string profileName;
40 | ///
41 | /// Contains the SSID of the visible wireless network.
42 | ///
43 | public Dot11Ssid dot11Ssid;
44 | ///
45 | /// Specifies whether the network is infrastructure or ad hoc.
46 | ///
47 | public Dot11BssType dot11BssType;
48 | ///
49 | /// Indicates the number of BSSIDs in the network.
50 | ///
51 | public uint numberOfBssids;
52 | ///
53 | /// Indicates whether the network is connectable or not.
54 | ///
55 | public bool networkConnectable;
56 | ///
57 | /// Indicates why a network cannot be connected to. This member is only valid when is false.
58 | ///
59 | public WlanReasonCode wlanNotConnectableReason;
60 | ///
61 | /// The number of PHY types supported on available networks.
62 | /// The maximum value of this field is 8. If more than 8 PHY types are supported, must be set to true.
63 | ///
64 | private uint numberOfPhyTypes;
65 | ///
66 | /// Contains an array of values that represent the PHY types supported by the available networks.
67 | /// When is greater than 8, this array contains only the first 8 PHY types.
68 | ///
69 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
70 | private Dot11PhyType[] dot11PhyTypes;
71 | ///
72 | /// Gets the values that represent the PHY types supported by the available networks.
73 | ///
74 | public Dot11PhyType[] Dot11PhyTypes
75 | {
76 | get
77 | {
78 | Dot11PhyType[] ret = new Dot11PhyType[numberOfPhyTypes];
79 | Array.Copy(dot11PhyTypes, ret, numberOfPhyTypes);
80 | return ret;
81 | }
82 | }
83 | ///
84 | /// Specifies if there are more than 8 PHY types supported.
85 | /// When this member is set to true, an application must call to get the complete list of PHY types.
86 | /// contains the PHY type for an entry.
87 | ///
88 | public bool morePhyTypes;
89 | ///
90 | /// A percentage value that represents the signal quality of the network.
91 | /// This field contains a value between 0 and 100.
92 | /// A value of 0 implies an actual RSSI signal strength of -100 dbm.
93 | /// A value of 100 implies an actual RSSI signal strength of -50 dbm.
94 | /// You can calculate the RSSI signal strength value for values between 1 and 99 using linear interpolation.
95 | ///
96 | public uint wlanSignalQuality;
97 | ///
98 | /// Indicates whether security is enabled on the network.
99 | ///
100 | public bool securityEnabled;
101 | ///
102 | /// Indicates the default authentication algorithm used to join this network for the first time.
103 | ///
104 | public Dot11AuthAlgorithm dot11DefaultAuthAlgorithm;
105 | ///
106 | /// Indicates the default cipher algorithm to be used when joining this network.
107 | ///
108 | public Dot11CipherAlgorithm dot11DefaultCipherAlgorithm;
109 | ///
110 | /// Contains various flags for the network.
111 | ///
112 | public WlanAvailableNetworkFlags flags;
113 | ///
114 | /// Reserved for future use. Must be set to NULL.
115 | ///
116 | uint reserved;
117 |
118 | public bool Equals(WlanAvailableNetwork network)
119 | {
120 | // Compares the two SSID byte arrays
121 | return this.dot11Ssid.SSIDLength == network.dot11Ssid.SSIDLength
122 | && this.dot11Ssid.SSID.SequenceEqual(network.dot11Ssid.SSID);
123 | }
124 | }
125 |
126 | ///
127 | /// Contains information provided when registering for notifications.
128 | ///
129 | ///
130 | /// Corresponds to the native WLAN_NOTIFICATION_DATA type.
131 | ///
132 | [StructLayout(LayoutKind.Sequential)]
133 | public struct WlanNotificationData
134 | {
135 | ///
136 | /// Specifies where the notification comes from.
137 | ///
138 | ///
139 | /// On Windows XP SP2, this field must be set to , or .
140 | ///
141 | public WlanNotificationSource notificationSource;
142 | ///
143 | /// Indicates the type of notification. The value of this field indicates what type of associated data will be present in .
144 | ///
145 | public int notificationCode;
146 | ///
147 | /// Indicates which interface the notification is for.
148 | ///
149 | public Guid interfaceGuid;
150 | ///
151 | /// Specifies the size of , in bytes.
152 | ///
153 | public int dataSize;
154 | ///
155 | /// Pointer to additional data needed for the notification, as indicated by .
156 | ///
157 | public IntPtr dataPtr;
158 |
159 | ///
160 | /// Gets the notification code (in the correct enumeration type) according to the notification source.
161 | ///
162 | public object NotificationCode
163 | {
164 | get
165 | {
166 | if (notificationSource == WlanNotificationSource.MSM)
167 | return (WlanNotificationCodeMsm)notificationCode;
168 | else if (notificationSource == WlanNotificationSource.ACM)
169 | return (WlanNotificationCodeAcm)notificationCode;
170 | else
171 | return notificationCode;
172 | }
173 |
174 | }
175 | }
176 |
177 |
178 | ///
179 | /// Specifies the parameters used when using the function.
180 | ///
181 | ///
182 | /// Corresponds to the native WLAN_CONNECTION_PARAMETERS type.
183 | ///
184 | [StructLayout(LayoutKind.Sequential)]
185 | public struct WlanConnectionParameters
186 | {
187 | ///
188 | /// Specifies the mode of connection.
189 | ///
190 | public WlanConnectionMode wlanConnectionMode;
191 | ///
192 | /// Specifies the profile being used for the connection.
193 | /// The contents of the field depend on the :
194 | ///
195 | ///
196 | /// Value of
197 | /// Contents of the profile string
198 | ///
199 | /// -
200 | ///
201 | /// The name of the profile used for the connection.
202 | ///
203 | /// -
204 | ///
205 | /// The XML representation of the profile used for the connection.
206 | ///
207 | /// -
208 | /// , or
209 | /// null
210 | ///
211 | ///
212 | ///
213 | [MarshalAs(UnmanagedType.LPWStr)]
214 | public string profile;
215 | ///
216 | /// Pointer to a structure that specifies the SSID of the network to connect to.
217 | /// This field is optional. When set to null, all SSIDs in the profile will be tried.
218 | /// This field must not be null if is set to or .
219 | ///
220 | public IntPtr dot11SsidPtr;
221 | ///
222 | /// Pointer to a structure that contains the list of basic service set (BSS) identifiers desired for the connection.
223 | ///
224 | ///
225 | /// On Windows XP SP2, must be set to null.
226 | ///
227 | public IntPtr desiredBssidListPtr;
228 | ///
229 | /// A value that indicates the BSS type of the network. If a profile is provided, this BSS type must be the same as the one in the profile.
230 | ///
231 | public Dot11BssType dot11BssType;
232 | ///
233 | /// Specifies ocnnection parameters.
234 | ///
235 | ///
236 | /// On Windows XP SP2, must be set to 0.
237 | ///
238 | public WlanConnectionFlags flags;
239 | }
240 |
241 | [StructLayout(LayoutKind.Sequential)]
242 | internal struct WlanBssListHeader
243 | {
244 | internal uint totalSize;
245 | internal uint numberOfItems;
246 | }
247 |
248 | ///
249 | /// Contains information about a basic service set (BSS).
250 | ///
251 | [StructLayout(LayoutKind.Sequential)]
252 | public struct WlanBssEntry
253 | {
254 | ///
255 | /// Contains the SSID of the access point (AP) associated with the BSS.
256 | ///
257 | public Dot11Ssid dot11Ssid;
258 | ///
259 | /// The identifier of the PHY on which the AP is operating.
260 | ///
261 | public uint phyId;
262 | ///
263 | /// Contains the BSS identifier.
264 | ///
265 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
266 | public byte[] dot11Bssid;
267 | ///
268 | /// Specifies whether the network is infrastructure or ad hoc.
269 | ///
270 | public Dot11BssType dot11BssType;
271 | public Dot11PhyType dot11BssPhyType;
272 | ///
273 | /// The received signal strength in dBm.
274 | ///
275 | public int rssi;
276 | ///
277 | /// The link quality reported by the driver. Ranges from 0-100.
278 | ///
279 | public uint linkQuality;
280 | ///
281 | /// If 802.11d is not implemented, the network interface card (NIC) must set this field to TRUE. If 802.11d is implemented (but not necessarily enabled), the NIC must set this field to TRUE if the BSS operation complies with the configured regulatory domain.
282 | ///
283 | public bool inRegDomain;
284 | ///
285 | /// Contains the beacon interval value from the beacon packet or probe response.
286 | ///
287 | public ushort beaconPeriod;
288 | ///
289 | /// The timestamp from the beacon packet or probe response.
290 | ///
291 | public ulong timestamp;
292 | ///
293 | /// The host timestamp value when the beacon or probe response is received.
294 | ///
295 | public ulong hostTimestamp;
296 | ///
297 | /// The capability value from the beacon packet or probe response.
298 | ///
299 | public ushort capabilityInformation;
300 | ///
301 | /// The frequency of the center channel, in kHz.
302 | ///
303 | public uint chCenterFrequency;
304 | ///
305 | /// Contains the set of data transfer rates supported by the BSS.
306 | ///
307 | public WlanRateSet wlanRateSet;
308 | ///
309 | /// Offset of the information element (IE) data blob.
310 | ///
311 | public uint ieOffset;
312 | ///
313 | /// Size of the IE data blob, in bytes.
314 | ///
315 | public uint ieSize;
316 | }
317 |
318 | ///
319 | /// Contains the set of supported data rates.
320 | ///
321 | [StructLayout(LayoutKind.Sequential)]
322 | public struct WlanRateSet
323 | {
324 | ///
325 | /// The length, in bytes, of .
326 | ///
327 | private uint rateSetLength;
328 | ///
329 | /// An array of supported data transfer rates.
330 | /// If the rate is a basic rate, the first bit of the rate value is set to 1.
331 | /// A basic rate is the data transfer rate that all stations in a basic service set (BSS) can use to receive frames from the wireless medium.
332 | ///
333 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 126)]
334 | private ushort[] rateSet;
335 |
336 | public ushort[] Rates
337 | {
338 | get
339 | {
340 | ushort[] rates = new ushort[rateSetLength / sizeof(ushort)];
341 | Array.Copy(rateSet, rates, rates.Length);
342 | return rates;
343 | }
344 | }
345 |
346 | ///
347 | /// CalculateS the data transfer rate in Mbps for an arbitrary supported rate.
348 | ///
349 | ///
350 | ///
351 | public double GetRateInMbps(int rate)
352 | {
353 | return (rateSet[rate] & 0x7FFF) * 0.5;
354 | }
355 | }
356 |
357 |
358 | ///
359 | /// Contains information about connection related notifications.
360 | ///
361 | ///
362 | /// Corresponds to the native WLAN_CONNECTION_NOTIFICATION_DATA type.
363 | ///
364 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
365 | public struct WlanConnectionNotificationData
366 | {
367 | ///
368 | /// On Windows XP SP 2, only is supported.
369 | ///
370 | public WlanConnectionMode wlanConnectionMode;
371 | ///
372 | /// The name of the profile used for the connection. Profile names are case-sensitive.
373 | ///
374 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
375 | public string profileName;
376 | ///
377 | /// The SSID of the association.
378 | ///
379 | public Dot11Ssid dot11Ssid;
380 | ///
381 | /// The BSS network type.
382 | ///
383 | public Dot11BssType dot11BssType;
384 | ///
385 | /// Indicates whether security is enabled for this connection.
386 | ///
387 | public bool securityEnabled;
388 | ///
389 | /// Indicates the reason for an operation failure.
390 | /// This field has a value of for all connection-related notifications except .
391 | /// If the connection fails, this field indicates the reason for the failure.
392 | ///
393 | public WlanReasonCode wlanReasonCode;
394 | ///
395 | /// This field contains the XML presentation of the profile used for discovery, if the connection succeeds.
396 | ///
397 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
398 | public string profileXml;
399 | }
400 |
401 |
402 | ///
403 | /// Contains the SSID of an interface.
404 | ///
405 | public struct Dot11Ssid
406 | {
407 | ///
408 | /// The length, in bytes, of the array.
409 | ///
410 | public uint SSIDLength;
411 | ///
412 | /// The SSID.
413 | ///
414 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
415 | public byte[] SSID;
416 | }
417 |
418 | ///
419 | /// Contains association attributes for a connection
420 | ///
421 | ///
422 | /// Corresponds to the native WLAN_ASSOCIATION_ATTRIBUTES type.
423 | ///
424 | [StructLayout(LayoutKind.Sequential)]
425 | public struct WlanAssociationAttributes
426 | {
427 | ///
428 | /// The SSID of the association.
429 | ///
430 | public Dot11Ssid dot11Ssid;
431 | ///
432 | /// Specifies whether the network is infrastructure or ad hoc.
433 | ///
434 | public Dot11BssType dot11BssType;
435 | ///
436 | /// The BSSID of the association.
437 | ///
438 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
439 | public byte[] dot11Bssid;
440 | ///
441 | /// The physical type of the association.
442 | ///
443 | public Dot11PhyType dot11PhyType;
444 | ///
445 | /// The position of the value in the structure containing the list of PHY types.
446 | ///
447 | public uint dot11PhyIndex;
448 | ///
449 | /// A percentage value that represents the signal quality of the network.
450 | /// This field contains a value between 0 and 100.
451 | /// A value of 0 implies an actual RSSI signal strength of -100 dbm.
452 | /// A value of 100 implies an actual RSSI signal strength of -50 dbm.
453 | /// You can calculate the RSSI signal strength value for values between 1 and 99 using linear interpolation.
454 | ///
455 | public uint wlanSignalQuality;
456 | ///
457 | /// The receiving rate of the association.
458 | ///
459 | public uint rxRate;
460 | ///
461 | /// The transmission rate of the association.
462 | ///
463 | public uint txRate;
464 |
465 | ///
466 | /// Gets the BSSID of the associated access point.
467 | ///
468 | /// The BSSID.
469 | public PhysicalAddress Dot11Bssid
470 | {
471 | get { return new PhysicalAddress(dot11Bssid); }
472 | }
473 | }
474 |
475 | ///
476 | /// Defines the security attributes for a wireless connection.
477 | ///
478 | ///
479 | /// Corresponds to the native WLAN_SECURITY_ATTRIBUTES type.
480 | ///
481 | [StructLayout(LayoutKind.Sequential)]
482 | public struct WlanSecurityAttributes
483 | {
484 | ///
485 | /// Indicates whether security is enabled for this connection.
486 | ///
487 | [MarshalAs(UnmanagedType.Bool)]
488 | public bool securityEnabled;
489 | [MarshalAs(UnmanagedType.Bool)]
490 | public bool oneXEnabled;
491 | ///
492 | /// The authentication algorithm.
493 | ///
494 | public Dot11AuthAlgorithm dot11AuthAlgorithm;
495 | ///
496 | /// The cipher algorithm.
497 | ///
498 | public Dot11CipherAlgorithm dot11CipherAlgorithm;
499 | }
500 |
501 | ///
502 | /// Defines the attributes of a wireless connection.
503 | ///
504 | ///
505 | /// Corresponds to the native WLAN_CONNECTION_ATTRIBUTES type.
506 | ///
507 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
508 | public struct WlanConnectionAttributes
509 | {
510 | ///
511 | /// The state of the interface.
512 | ///
513 | public WlanInterfaceState isState;
514 | ///
515 | /// The mode of the connection.
516 | ///
517 | public WlanConnectionMode wlanConnectionMode;
518 | ///
519 | /// The name of the profile used for the connection. Profile names are case-sensitive.
520 | ///
521 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
522 | public string profileName;
523 | ///
524 | /// The attributes of the association.
525 | ///
526 | public WlanAssociationAttributes wlanAssociationAttributes;
527 | ///
528 | /// The security attributes of the connection.
529 | ///
530 | public WlanSecurityAttributes wlanSecurityAttributes;
531 | }
532 |
533 | ///
534 | /// Contains information about a LAN interface.
535 | ///
536 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
537 | public struct WlanInterfaceInfo
538 | {
539 | ///
540 | /// The GUID of the interface.
541 | ///
542 | public Guid interfaceGuid;
543 | ///
544 | /// The description of the interface.
545 | ///
546 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
547 | public string interfaceDescription;
548 | ///
549 | /// The current state of the interface.
550 | ///
551 | public WlanInterfaceState isState;
552 | }
553 |
554 | ///
555 | /// The header of the list returned by .
556 | ///
557 | [StructLayout(LayoutKind.Sequential)]
558 | internal struct WlanInterfaceInfoListHeader
559 | {
560 | public uint numberOfItems;
561 | public uint index;
562 | }
563 |
564 | ///
565 | /// The header of the list returned by .
566 | ///
567 | [StructLayout(LayoutKind.Sequential)]
568 | internal struct WlanProfileInfoListHeader
569 | {
570 | public uint numberOfItems;
571 | public uint index;
572 | }
573 |
574 | ///
575 | /// Contains basic information about a profile.
576 | ///
577 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
578 | public struct WlanProfileInfo
579 | {
580 | ///
581 | /// The name of the profile. This value may be the name of a domain if the profile is for provisioning. Profile names are case-sensitive.
582 | ///
583 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
584 | public string profileName;
585 | ///
586 | /// Profile flags.
587 | ///
588 | public WlanProfileFlags profileFlags;
589 | }
590 |
591 | /*
592 | ///
593 | /// The EAP_METHOD_TYPE structure contains type, identification, and author information about an EAP method.
594 | ///
595 | [StructLayout(LayoutKind.Sequential)]
596 | public struct EapMethodType
597 | {
598 | public EapType eapType; // EAP_TYPE structure that contains the ID for the EAP method as well as specific vendor information.
599 | public uint dwAuthorId; // The numeric ID for the author of the EAP method.
600 | }
601 |
602 | ///
603 | /// The EAP_TYPE structure contains type and vendor identification information for an EAP method.
604 | ///
605 | [StructLayout(LayoutKind.Sequential)]
606 | public struct EapType
607 | {
608 | public byte type; // The numeric type code for this EAP method, Note For more information on the allocation of EAP method types, see section 6.2 of RFC 3748: http://go.microsoft.com/fwlink/p/?linkid=84016
609 | public uint dwVendorId; // The vendor ID for the EAP method.
610 | public uint dwVendorType; // The numeric type code for the vendor of this EAP method.
611 | }*/
612 | }
613 |
--------------------------------------------------------------------------------
/SimpleWifi/Win32/WlanApi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Runtime.InteropServices;
5 | using System.Net.NetworkInformation;
6 | using System.Threading;
7 | using System.Text;
8 | using SimpleWifi.Win32.Interop;
9 | using SimpleWifi.Win32.Helpers;
10 |
11 | namespace SimpleWifi.Win32
12 | {
13 | ///
14 | /// Represents a client to the Zeroconf (Native Wifi) service.
15 | ///
16 | ///
17 | /// This class is the entrypoint to Native Wifi management. To manage WiFi settings, create an instance
18 | /// of this class.
19 | ///
20 | public class WlanClient
21 | {
22 | internal IntPtr clientHandle;
23 | internal uint negotiatedVersion;
24 | internal WlanInterop.WlanNotificationCallbackDelegate wlanNotificationCallback;
25 |
26 | private Dictionary ifaces = new Dictionary();
27 |
28 | private const int NO_WIFI = 1062;
29 |
30 | public bool NoWifiAvailable = false;
31 |
32 | ///
33 | /// Creates a new instance of a Native Wifi service client.
34 | /// Throws Win32 errors: ERROR_INVALID_PARAMETER, ERROR_NOT_ENOUGH_MEMORY, RPC_STATUS, ERROR_REMOTE_SESSION_LIMIT_EXCEEDED.
35 | ///
36 | public WlanClient()
37 | {
38 | int errorCode = 0;
39 | OperatingSystem osInfo = Environment.OSVersion;
40 |
41 | bool isWinXP =
42 | osInfo.Platform == PlatformID.Win32NT &&
43 | osInfo.Version.Major == 5 &&
44 | osInfo.Version.Minor != 0;
45 |
46 | if (isWinXP && osInfo.ServicePack == "Service Pack 1") // wlanapi not supported in sp1 (or sp2 without hotfix)
47 | {
48 | errorCode = NO_WIFI;
49 | }
50 | else
51 | {
52 | // Perform exception safe init
53 | // It can be SP2 without hotfix which would generate exception
54 | try
55 | {
56 | errorCode = WlanInterop.WlanOpenHandle(WlanInterop.WLAN_CLIENT_VERSION_XP_SP2, IntPtr.Zero, out negotiatedVersion, out clientHandle);
57 | }
58 | catch
59 | {
60 | errorCode = NO_WIFI;
61 | }
62 | }
63 |
64 | if (errorCode != 0)
65 | {
66 | NoWifiAvailable = true;
67 | return;
68 | }
69 |
70 | // 1062 = no wifi
71 | // OK!
72 | // WlanInterop.ThrowIfError(errorCode);
73 |
74 | try
75 | {
76 | // Interop callback
77 | wlanNotificationCallback = new WlanInterop.WlanNotificationCallbackDelegate(OnWlanNotification);
78 |
79 | WlanNotificationSource prevSrc;
80 | WlanInterop.ThrowIfError(WlanInterop.WlanRegisterNotification(clientHandle, WlanNotificationSource.All, false, wlanNotificationCallback, IntPtr.Zero, IntPtr.Zero, out prevSrc));
81 | }
82 | catch
83 | {
84 | WlanInterop.WlanCloseHandle(clientHandle, IntPtr.Zero);
85 | throw;
86 | }
87 | }
88 |
89 | ~WlanClient()
90 | {
91 | // Free the handle when deconstructing the client. There won't be a handle if its xp sp 2 without wlanapi installed
92 | try
93 | {
94 | WlanInterop.WlanCloseHandle(clientHandle, IntPtr.Zero);
95 | }
96 | catch
97 | { }
98 | }
99 |
100 | // Called from interop
101 | private void OnWlanNotification(ref WlanNotificationData notifyData, IntPtr context)
102 | {
103 | if (NoWifiAvailable)
104 | return;
105 |
106 | WlanInterface wlanIface = ifaces.ContainsKey(notifyData.interfaceGuid) ? ifaces[notifyData.interfaceGuid] : null;
107 |
108 | switch(notifyData.notificationSource)
109 | {
110 | case WlanNotificationSource.ACM:
111 | switch((WlanNotificationCodeAcm)notifyData.notificationCode)
112 | {
113 | case WlanNotificationCodeAcm.ConnectionStart:
114 | case WlanNotificationCodeAcm.ConnectionComplete:
115 | case WlanNotificationCodeAcm.ConnectionAttemptFail:
116 | case WlanNotificationCodeAcm.Disconnecting:
117 | case WlanNotificationCodeAcm.Disconnected:
118 | WlanConnectionNotificationData? connNotifyData = WlanHelpers.ParseWlanConnectionNotification(ref notifyData);
119 |
120 | if (connNotifyData.HasValue && wlanIface != null)
121 | wlanIface.OnWlanConnection(notifyData, connNotifyData.Value);
122 |
123 | break;
124 | case WlanNotificationCodeAcm.ScanFail:
125 | int expectedSize = Marshal.SizeOf(typeof(int));
126 |
127 | if (notifyData.dataSize >= expectedSize)
128 | {
129 | int reasonInt = Marshal.ReadInt32(notifyData.dataPtr);
130 |
131 | // Want to make sure this doesn't crash if windows sends a reasoncode not defined in the enum.
132 | if (Enum.IsDefined(typeof(WlanReasonCode), reasonInt))
133 | {
134 | WlanReasonCode reasonCode = (WlanReasonCode)reasonInt;
135 |
136 | if (wlanIface != null)
137 | wlanIface.OnWlanReason(notifyData, reasonCode);
138 | }
139 | }
140 | break;
141 | }
142 | break;
143 | case WlanNotificationSource.MSM:
144 | switch((WlanNotificationCodeMsm)notifyData.notificationCode)
145 | {
146 | case WlanNotificationCodeMsm.Associating:
147 | case WlanNotificationCodeMsm.Associated:
148 | case WlanNotificationCodeMsm.Authenticating:
149 | case WlanNotificationCodeMsm.Connected:
150 | case WlanNotificationCodeMsm.RoamingStart:
151 | case WlanNotificationCodeMsm.RoamingEnd:
152 | case WlanNotificationCodeMsm.Disassociating:
153 | case WlanNotificationCodeMsm.Disconnected:
154 | case WlanNotificationCodeMsm.PeerJoin:
155 | case WlanNotificationCodeMsm.PeerLeave:
156 | case WlanNotificationCodeMsm.AdapterRemoval:
157 | WlanConnectionNotificationData? connNotifyData = WlanHelpers.ParseWlanConnectionNotification(ref notifyData);
158 |
159 | if (connNotifyData.HasValue && wlanIface != null)
160 | wlanIface.OnWlanConnection(notifyData, connNotifyData.Value);
161 |
162 | break;
163 | }
164 | break;
165 | }
166 |
167 | if (wlanIface != null)
168 | wlanIface.OnWlanNotification(notifyData);
169 | }
170 |
171 | ///
172 | /// Gets the WLAN interfaces.
173 | ///
174 | /// Possible Win32 exceptions:
175 | ///
176 | /// ERROR_INVALID_PARAMETER: A parameter is incorrect. This error is returned if the hClientHandle or ppInterfaceList parameter is NULL. This error is returned if the pReserved is not NULL. This error is also returned if the hClientHandle parameter is not valid.
177 | /// ERROR_INVALID_HANDLE: The handle hClientHandle was not found in the handle table.
178 | /// RPC_STATUS: Various error codes.
179 | /// ERROR_NOT_ENOUGH_MEMORY: Not enough memory is available to process this request and allocate memory for the query results.
180 | ///
181 | /// The WLAN interfaces.
182 | public WlanInterface[] Interfaces
183 | {
184 | get
185 | {
186 | if (NoWifiAvailable)
187 | return null;
188 | IntPtr ifaceList;
189 |
190 | WlanInterop.ThrowIfError(WlanInterop.WlanEnumInterfaces(clientHandle, IntPtr.Zero, out ifaceList));
191 |
192 | try
193 | {
194 | WlanInterfaceInfoListHeader header = (WlanInterfaceInfoListHeader) Marshal.PtrToStructure(ifaceList, typeof (WlanInterfaceInfoListHeader));
195 |
196 | Int64 listIterator = ifaceList.ToInt64() + Marshal.SizeOf(header);
197 | WlanInterface[] interfaces = new WlanInterface[header.numberOfItems];
198 | List currentIfaceGuids = new List();
199 |
200 | for (int i = 0; i < header.numberOfItems; ++i)
201 | {
202 | WlanInterfaceInfo info = (WlanInterfaceInfo) Marshal.PtrToStructure(new IntPtr(listIterator), typeof(WlanInterfaceInfo));
203 |
204 | listIterator += Marshal.SizeOf(info);
205 | currentIfaceGuids.Add(info.interfaceGuid);
206 |
207 | WlanInterface wlanIface;
208 | if (ifaces.ContainsKey(info.interfaceGuid))
209 | wlanIface = ifaces[info.interfaceGuid];
210 | else
211 | wlanIface = new WlanInterface(this, info);
212 |
213 | interfaces[i] = wlanIface;
214 | ifaces[info.interfaceGuid] = wlanIface;
215 | }
216 |
217 | // Remove stale interfaces
218 | Queue deadIfacesGuids = new Queue();
219 | foreach (Guid ifaceGuid in ifaces.Keys)
220 | {
221 | if (!currentIfaceGuids.Contains(ifaceGuid))
222 | deadIfacesGuids.Enqueue(ifaceGuid);
223 | }
224 |
225 | while(deadIfacesGuids.Count != 0)
226 | {
227 | Guid deadIfaceGuid = deadIfacesGuids.Dequeue();
228 | ifaces.Remove(deadIfaceGuid);
229 | }
230 |
231 | return interfaces;
232 | }
233 | finally
234 | {
235 | WlanInterop.WlanFreeMemory(ifaceList);
236 | }
237 | }
238 | }
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/SimpleWifi/Win32/WlanInterface.cs:
--------------------------------------------------------------------------------
1 | using SimpleWifi.Win32.Interop;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Net.NetworkInformation;
6 | using System.Runtime.InteropServices;
7 | using System.Text;
8 | using System.Threading;
9 |
10 | namespace SimpleWifi.Win32
11 | {
12 | ///
13 | /// Represents a Wifi network interface.
14 | ///
15 | public class WlanInterface
16 | {
17 | private WlanClient client;
18 | private WlanInterfaceInfo info;
19 |
20 | #region Events
21 | ///
22 | /// Represents a method that will handle events.
23 | ///
24 | /// The notification data.
25 | public delegate void WlanNotificationEventHandler(WlanNotificationData notifyData);
26 |
27 | ///
28 | /// Represents a method that will handle events.
29 | ///
30 | /// The notification data.
31 | /// The notification data.
32 | public delegate void WlanConnectionNotificationEventHandler(WlanNotificationData notifyData, WlanConnectionNotificationData connNotifyData);
33 |
34 | ///
35 | /// Represents a method that will handle events.
36 | ///
37 | /// The notification data.
38 | /// The reason code.
39 | public delegate void WlanReasonNotificationEventHandler(WlanNotificationData notifyData, WlanReasonCode reasonCode);
40 |
41 | ///
42 | /// Occurs when an event of any kind occurs on a WLAN interface.
43 | ///
44 | public event WlanNotificationEventHandler WlanNotification;
45 |
46 | ///
47 | /// Occurs when a WLAN interface changes connection state.
48 | ///
49 | public event WlanConnectionNotificationEventHandler WlanConnectionNotification;
50 |
51 | ///
52 | /// Occurs when a WLAN operation fails due to some reason.
53 | ///
54 | public event WlanReasonNotificationEventHandler WlanReasonNotification;
55 |
56 | private bool queueEvents;
57 | private AutoResetEvent eventQueueFilled = new AutoResetEvent(false);
58 | private Queue