извините, похоже, что SO «вставить код» плохо обрабатывает длинные списки кодов, поэтому коды выглядят плохо. Пожалуйста, скопируйте/вставьте их в свой редактор и переформатируйте.
пункты (1), (2), (3) довольно тривиальны - это просто определения классов/структур/функций экспорта. В пункте (4) происходит вся магия, но я не смог вставить его сюда (слишком длинный), поэтому скопировал его в PasteBin (ссылка ниже). Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы - я постараюсь вам помочь - но идея состоит в том, чтобы использовать низкоуровневую функцию DeviceIoControl для связи с адаптером.
пожалуйста, взгляните на коды. Я не думаю, что вы сможете их скомпилировать, однако они должны дать вам представление о том, что происходит под капотом. Дисклеймер - я их писал 5-6 лет назад, а сейчас сделал бы совсем по другому :)
Оболочка С# для dll С++:
открытый класс WiFiDllWrapper { частный класс DllFunctions { [DllImport ("ewf.dll")] внутренний статический внешний логический TurnWlanOn();
[DllImport("ewf.dll")]
internal static extern bool FindWirelessAdapter();
[DllImport("ewf.dll")]
internal static extern bool ConnectToAdapter();
[DllImport("ewf.dll")]
internal static extern bool DisconnectFromAdapter();
[DllImport("ewf.dll")]
internal static extern bool StartScan();
// gets a list of APs from NIC
[DllImport("ewf.dll")]
internal static extern bool GetAPsList([In, Out] APInfo[] pAPs, int maxAPs, ref int foundAPs);
// connects to a selected AP
[DllImport("ewf.dll")]
internal static extern bool ConnectToAP(int maxWaitTimeSeconds, string ssid, bool isWepEnabled, string wepKey);
[DllImport("ewf.dll")]
internal static extern bool RenewIPAddress(int maxWaitTimeSeconds);
}
public static bool TurnWlanOn()
{
return DllFunctions.TurnWlanOn();
}
public static bool FindWirelessAdapter()
{
return DllFunctions.FindWirelessAdapter();
}
public static bool ConnectToNdis()
{
bool bDisableWzcViaDriver = (Settings.GetOSVersion() != OSVersion.WM2003);
bool bRes = DllFunctions.ConnectToAdapter();
return bRes;
}
public static bool DisconnectFromNdis()
{
return DllFunctions.DisconnectFromAdapter();
}
public static void StartScan()
{
DllFunctions.StartScan();
}
public static bool ConnectToAP(int maxWaitTimeSeconds, string ssid, bool isWepEnabled, string wepKey)
{
DllFunctions.ConnectToAP(maxWaitTimeSeconds, ssid, isWepEnabled, wepKey);
return true;
}
public static bool RenewIPAddress(int maxWaitTimeSeconds)
{
return DllFunctions.RenewIPAddress(maxWaitTimeSeconds);
}
public static List<AccessPoint> GetAPsList()
{
int numberOfItems = 0; // gets a number of actually found devices
APInfo[] OutputList = new APInfo[30];
if (DllFunctions.GetAPsList(OutputList, OutputList.Length, ref numberOfItems) == false)
throw new Exception("AP scan failed!");
List<AccessPoint> lst = new List<AccessPoint>();
for (int i = 0; i < numberOfItems; i++)
lst.Add(new AccessPoint(OutputList[i]));
return lst;
}
}
Определение модели AccessPoint:
// just took enums from NTDDNDIS.H file...
перечисление NDIS_802_11_WEP_STATUS {Ndis802_11WEPEnabled, Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, Ndis802_11WEPDisabled, Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, Ndis802_11WEPKeyAbsent, Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, Ndis802_11WEPNotSupported, Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, Ndis802_11Encryption2Enabled, Ndis802_11Encryption2KeyAbsent, Ndis802_11Encryption3Enabled, Ndis802_11Encryption3KeyAbsent};
enum NDIS_802_11_NETWORK_INFRASTRUCTURE { Ndis802_11IBSS, Ndis802_11Infrastructure, Ndis802_11AutoUnknown, Ndis802_11InfrastructureMax // Не реальное значение, определенное как верхняя граница };
enum NDIS_802_11_NETWORK_TYPE { Ndis802_11FH, Ndis802_11DS, Ndis802_11OFDM5, // Добавлены новые типы для OFDM 5G и 2.4G Ndis802_11OFDM24, Ndis802_11NetworkTypeMax // не реальный тип, определенный как верхняя граница };
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct APInfo { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 40)] public string _ssid; // SSID точки доступа
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string _mac; // MAC address of the AP
//[MarshalAs(UnmanagedType.U4)]
public int _rssi; // signal strength in dB
//[MarshalAs(UnmanagedType.U4)]
public uint _wepStatus;
[MarshalAs(UnmanagedType.I4)]
public NDIS_802_11_NETWORK_INFRASTRUCTURE _networkInfrastructure;
[MarshalAs(UnmanagedType.I4)]
public NDIS_802_11_NETWORK_TYPE _networkType;
[MarshalAs(UnmanagedType.U4)]
public uint BeaconPeriod; // units are Kusec
[MarshalAs(UnmanagedType.U4)]
public uint DSConfig; // Frequency, units are kHz
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] _rates; // MSDN: Each byte describes a single rate in units of 0.5 Mbps
}
public class AccessPoint { // если уровень мощности (в дБм) ниже этого, то сигнал слабый const int STRONG_WEEK_dBm_THRESHOLD = -70;
public static bool IsSignalWeak(int SignalStrengthdBm)
{
return SignalStrengthdBm < STRONG_WEEK_dBm_THRESHOLD;
}
internal AccessPoint(APInfo apInfo)
{
_ssid = apInfo._ssid;
_mac = apInfo._mac;
_rssi = apInfo._rssi;
_wepStatus = apInfo._wepStatus;
_networkInfrastructure = apInfo._networkInfrastructure;
_networkType = apInfo._networkType;
BeaconPeriod = apInfo.BeaconPeriod;
DSConfig = apInfo.DSConfig;
_rates = apInfo._rates;
}
private string _ssid; // SSID of the AP
private string _mac; // MAC address of the AP
private int _rssi; // signal strength in dB
private uint _wepStatus;
private NDIS_802_11_NETWORK_INFRASTRUCTURE _networkInfrastructure;
private NDIS_802_11_NETWORK_TYPE _networkType;
private uint BeaconPeriod; // units are Kusec
private uint DSConfig; // Frequency, units are kHz
private byte[] _rates; // MSDN: Each byte describes a single rate in units of 0.5 Mbps
public bool IsEncrypted
{
get
{
return _wepStatus != 0;
}
}
/// <summary>
/// Beacon Interval in ms
/// </summary>
public ulong BeaconInterval
{
get { return BeaconPeriod; }
}
/// <summary>
/// Frequency in MHz
/// </summary>
public ulong Frequency
{
get { return (DSConfig / 1000); }
}
/// <summary>
/// Supported Rates by AP. Part of them belongs to Basic Rate Set.
/// </summary>
public string Rates
{
get
{
Array.Sort(_rates);
string basicRateSet = "", notBasicRateSet = "";
for (int i = 0; i < _rates.Length; i++)
{
if (_rates[i] == 0)
continue;
// Each supported rate from the BSSBasicRateSet is encoded as a byte with the most significant bit (bit 7) set to 1.
if ((_rates[i] & (1 << 7)) > 0)
basicRateSet += ((_rates[i] - 128) / 2).ToString() + "; ";
// Rates that are not included in the BSSBasicRateSet are encoded with the most significant bit set to zero.
else
notBasicRateSet += (_rates[i] / 2).ToString() + "; ";
}
return "BSSBasicRateSet: {" + basicRateSet + "}. other: {" + notBasicRateSet + "}";
}
}
/// <summary>
/// Number of wireless channel
/// </summary>
public ulong Channel
{
get
{
ulong centralFreqMHz = DSConfig / 1000;
if (centralFreqMHz > 2400 && centralFreqMHz < 2500) // then this is 802.11b/g
{
/*
Regional allocated use of 802.11b/g channels
1 to 11 -- North America (USA and Canada)
1 to 13 -- Austria, Belgium, Denmark, Finland, France, Germany, Greece, Iceland, Ireland, Italy, Liechtenstein, Luxembourg, Netherlands, Norway, Portugal, Spain, Sweden, Switzerland, United Kingdom.
1 to 14 -- Japan, China, Hong Kong, Philippines, Taiwan, Thailand, Singapore, South Korea
*/
switch (centralFreqMHz)
{
case 2412:
return 1;
case 2417:
return 2;
case 2422:
return 3;
case 2427:
return 4;
case 2432:
return 5;
case 2437:
return 6;
case 2442:
return 7;
case 2447:
return 8;
case 2452:
return 9;
case 2457:
return 10;
case 2462:
return 11;
case 2467:
return 12;
case 2472:
return 13;
case 2484:
return 14;
default:
return 0;
}
}
else if (centralFreqMHz > 5100 && centralFreqMHz < 5900) // this is 802.11a
{
switch (centralFreqMHz)
{
case 5170:
return 34;
case 5180:
return 36;
case 5190:
return 38;
case 5200:
return 40;
case 5210:
return 42;
case 5220:
return 44;
case 5230:
return 46;
case 5240:
return 48;
case 5260:
return 52;
case 5280:
return 56;
case 5300:
return 60;
case 5320:
return 64;
case 5500:
return 100;
case 5520:
return 104;
case 5540:
return 108;
case 5560:
return 112;
case 5580:
return 116;
case 5600:
return 120;
case 5620:
return 124;
case 5640:
return 128;
case 5660:
return 132;
case 5680:
return 136;
case 5700:
return 140;
case 5745:
return 149;
case 5765:
return 153;
case 5785:
return 157;
case 5805:
return 161;
default:
return 0;
}
}
else
return 0;
}
}
/// <summary>
/// SSID of the AP
/// </summary>
public string SSID
{
get { return _ssid; }
}
/// <summary>
/// MAC address "XX-XX-XX-XX-XX-XX"
/// </summary>
public string MAC
{
get { return _mac; }
}
/// <summary>
/// Signal strength in dB
/// </summary>
public int SignalStrength
{
get { return (int)_rssi; }
}
/// <summary>
/// MSDN:
/// Specifies a WEP/WPA/WPA2 encryption requirement. A value of 0 indicates that privacy is disabled.
/// A value of 1 indicates that privacy is enabled.
/// </summary>
public string WEP
{
get { return (_wepStatus == 0 ? "WEP disabled" : "WEP enabled"); }
}
/// <summary>
/// Indicates the physical layer for the AP
/// </summary>
public string NetworkType
{
get
{
if (_networkType == NDIS_802_11_NETWORK_TYPE.Ndis802_11FH)
return "frequency-hopping spread-spectrum PHY";
else if (_networkType == NDIS_802_11_NETWORK_TYPE.Ndis802_11DS)
return "direct-sequence spread-spectrum PHY";
else if (_networkType == NDIS_802_11_NETWORK_TYPE.Ndis802_11OFDM24)
return "OFDM 2.4 GHz";
else if (_networkType == NDIS_802_11_NETWORK_TYPE.Ndis802_11OFDM5)
return "OFDM 5 GHz";
else
return "PHY is not FH, nor DS";
}
}
/// <summary>
/// Indicates current network mode for AP
/// </summary>
public string NetworkMode
{
get
{
if (_networkInfrastructure == NDIS_802_11_NETWORK_INFRASTRUCTURE.Ndis802_11IBSS)
return "IBSS (ad hoc) mode";
else if (_networkInfrastructure == NDIS_802_11_NETWORK_INFRASTRUCTURE.Ndis802_11Infrastructure)
return "Infrastructure (ESS) mode";
else if (_networkInfrastructure == NDIS_802_11_NETWORK_INFRASTRUCTURE.Ndis802_11AutoUnknown)
return "Automatic network mode";
else
return "not specified";
}
}
}
Файл C++ №1 — экспортируемые функции:
включить "stdafx.h"
включить "ewf.h"
включить "NdisConnect.h"
включают
NdisConnect g_NdisAdapter(L"ewf_log.txt");
внешний дескриптор g_NdisConnectedEvent;
extern "C" EWF_API BOOL WINAPI FindWirelessAdapter() { ENTER;
try
{
return g_NdisAdapter.FindWirelessAdapter();
}
catch (NdisException* e)
{
LOG_EXCEPTION(e);
return FALSE;
}
LEAVE;
return TRUE;
}
// 1. Инициализация адаптера: CreateFile(NDISUIO_DEVICE_NAME, — делается в g_NdisAdapter ctor // 2. Отключение WZC // 3. Повторное связывание адаптера // 4. Открытие внешнего адаптера "C" EWF_API BOOL WINAPI ConnectToAdapter() { ENTER;
try
{
if (FALSE == g_NdisAdapter.FindWirelessAdapter())
return FALSE;
if (false == g_NdisAdapter.DisableWZC_Driver())
g_NdisAdapter.DisableWZC_API();
g_NdisAdapter.RebindAdapter();
g_NdisAdapter.OpenDevice();
}
catch (NdisException* e)
{
LOG_EXCEPTION(e);
return FALSE;
}
LEAVE;
return TRUE;
}
extern "C" EWF_API BOOL WINAPI TurnWlanOn() { return g_NdisAdapter.TurnWlanOn(); }
extern "C" EWF_API BOOL WINAPI DisconnectFromAdapter() { ENTER; попробуйте {g_NdisAdapter.Disassociate(); } поймать (NdisException* e) { LOG_EXCEPTION(e); вернуть ЛОЖЬ;
}
LEAVE;
return TRUE;
}
extern "C" EWF_API BOOL StartScan() { ENTER; g_NdisAdapter.ScanForAPs();
return TRUE;
}
extern "C" EWF_API BOOL GetAPsList(APInfo* pAPs, int maxAPs, int* foundAPs) { ENTER; BOOL рез = ЛОЖЬ;
try
{
res = g_NdisAdapter.GetAPList(pAPs, maxAPs, foundAPs);
}
catch (NdisException* e)
{
LOG_EXCEPTION(e);
return FALSE;
}
LEAVE;
return TRUE;
}
extern "C" EWF_API BOOL ConnectToAP(int maxWaitTimeSeconds, const wchar_t* ssid, bool isWepEnabled, const wchar_t* wepKey) { char cSSID[33], cWepKey[30]; localFunctionCT2A (ssid, cSSID, sizeof (cSSID)); localFunctionCT2A(wepKey, cWepKey, sizeof(cWepKey));
ENTER_FUNC("SSID = " << cSSID << ", wep enabled = " << isWepEnabled << ", wep key = '" << cWepKey << "'");
g_NdisAdapter.Disassociate();
Sleep(2000);
ResetEvent(g_NdisConnectedEvent);
g_NdisAdapter.ConnectToAP(cSSID, isWepEnabled, cWepKey);
if (WAIT_OBJECT_0 != WaitForSingleObject(g_NdisConnectedEvent, maxWaitTimeSeconds*1000))
{
LOG("Did not get CONNECTED event from NDIS...");
return FALSE;
}
LEAVE;
return TRUE;
}
- Класс NdisConnect — здесь происходит вся магия NDIS:
‹‹ когда я вставлял сюда код, я преодолел ограничение в 30 КБ для сообщения, поэтому я создал файл PasteBin>> - http://pastebin.com/wMBZAYCQ
person
avs099
schedule
11.03.2012