# Coding - 午夜场

想法 玩物 创意


  • Home

  • Tags1

  • Categories1

  • Archives12

  • About

Visual C++ 编程实现Soft AP (HostedNetwork/承载网络) 功能

Posted on 2013-09-14 | Edited on 2019-04-14

从Windows 7开始,微软在操作系统中加入的Soft AP功能,使用户能够通过无线网卡,开启虚拟AP,从而实现网络共享。Soft AP又称HostedNetwork(承载网络),在Windows SDK中,提供了相应的API,以WlanHostedNetwork***开头的一系列函数。

要编码实现Soft AP,首先需要添加相应的头文件及lib库

1
2
3
4
5
6
#include <wlanapi.h>
#include <iphlpapi.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "Wlanapi.lib")
#pragma comment(lib, "IPHLPAPI.lib"

其中,wlanapi.h是无线网络API的声明文件,函数名一般以Wlan开头。iphlpapi.h用于调用GetAdapterInfo函数,获取网络虚拟接口信息。

和winsock套接字编程类似,Wlan库使用前需获得句柄,并进行版本协商,只不过都在WlanOpenHandle实现了。使用完句柄后,调用WlanCloseHandle关闭以释放资源。

WlanOpenHandle原形如下:

1
2
3
4
5
6
DWORD WINAPI WlanOpenHandle(
_In_ DWORD dwClientVersion,
_Reserved_ PVOID pReserved,
_Out_ PDWORD pdwNegotiatedVersion,
_Out_ PHANDLE phClientHandle
);

dwClientVersion指定程序期望使用的Wlan版本,使用宏WLAN_API_VERSION代替。从vista开始,版本号为2,xp系统为1。协商后的版本通过参数pdwNegotiatedVersion返回,通过检查主版本号来验证(如下代码所示)。句柄通过phClient返回。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
DWORD dwError = 0;
DWORD dwServiceVersion = 0;
HANDLE hClient = NULL;

if (ERROR_SUCCESS != (dwError = WlanOpenHandle(
WLAN_API_VERSION,
NULL, // reserved
&dwServiceVersion,
&hClient
)))
{
return -1;
}

// check service version
if (WLAN_API_VERSION_MAJOR(dwServiceVersion) < WLAN_API_VERSION_MAJOR(WLAN_API_VERSION_2_0))
{
WlanCloseHandle(hClient, NULL);
}

启动承载网络前,需要将模式配置为allow状态,并设置SSID和密码。可以调用WlanHostedNetworkSetProperty进行设置,WlanHostedNetworkSetProperty原型如下:

1
2
3
4
5
6
7
8
DWORD WINAPI WlanHostedNetworkSetProperty(
_In_ HANDLE hClientHandle,
_In_ WLAN_HOSTED_NETWORK_OPCODE OpCode,
_In_ DWORD dwDataSize,
_In_ PVOID pvData,
_Out_opt_ PWLAN_HOSTED_NETWORK_REASON pFailReason,
_Reserved_ PVOID pvReserved
);

其中hClientHandle是我们之前调用WlanOpenHnadle获得的句柄;dwDataSize指定了pvData缓冲区的大小,而pvData指向的变量类型取决与OpCode的取值。OpCode为WLAN_HOSTED_NETWORK_OPCODE枚举,如果指定为wlan_hosted_network_opcode_enable,那么pvData传入一个BOOL型的变量指针,用于指示承载网络模式为允许还是禁止(allow/disallow);如果OpCode为wlan_hosted_network_opcode_connection_settings,那么pvData指向WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS结构体,指定承载网络的SSID和最大连接数目(peer count).

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
    // 设置承载网络模式为允许
BOOL bIsAllow = TRUE;
WLAN_HOSTED_NETWORK_REASON dwFailedReason;
DWORD dwReturnValue = WlanHostedNetworkSetProperty(hWlanClient,
wlan_hosted_network_opcode_enable,
sizeof(BOOL),
&bIsAllow,
&dwFailedReason,
NULL);

if(ERROR_SUCCESS != dwReturnValue)
{
return -1;
}




// 设置承载网络的SSID和最大连接数
WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS wlanConnectionSetting;
memset(&wlanConnectionSetting, 0, sizeof(WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS));

// WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS中的SSID字段必须为ANSI类型,因此如果程序使用的是Unicode,则需要做转换。
#ifdef _UNICODE
WideCharToMultiByte(CP_ACP,
0,
strSSID.GetBuffer(0), // 保存SSID的CString类型
strSSID.GetLength(), // SSID字符串的长度
(LPSTR)wlanConnectionSetting.hostedNetworkSSID.ucSSID,
32,
NULL,
NULL);
#else
memcpy(wlanConnectionSetting.hostedNetworkSSID.ucSSID, strSSID.GetBuffer(0), strlen(strSSID.GetBuffer(0)));
#endif

wlanConnectionSetting.hostedNetworkSSID.uSSIDLength = strlen((const char*)wlanConnectionSetting.hostedNetworkSSID.ucSSID);
wlanConnectionSetting.dwMaxNumberOfPeers = 100;

dwReturnValue = WlanHostedNetworkSetProperty(m_hWlanClient,
wlan_hosted_network_opcode_connection_settings,
sizeof(WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS),
&wlanConnectionSetting,
&dwFailedReason,
NULL);
if(ERROR_SUCCESS != dwReturnValue)
{
return -1;
}

调用WlanHostedNetworkSetSecondaryKey函数,设置承载网络的连接密码,函数原型如下:

1
2
3
4
5
6
7
8
9
DWORD WINAPI WlanHostedNetworkSetSecondaryKey(
_In_ HANDLE hClientHandle,
_In_ DWORD dwKeyLength,
_In_ PUCHAR pucKeyData,
_In_ BOOL bIsPassPhrase,
_In_ BOOL bPersistent,
_Out_opt_ PWLAN_HOSTED_NETWORK_REASON pFailReason,
_Reserved_ PVOID pvReserved
);

hClientHandle是我们之前调用WlanOpenHnadle获得的句柄;

bIsPassPhrase表明传入pucKeyData的密码是否为口令格式,如果是口令格式,则是8-63位的ASCII字符串,该参数设置为TRUE;如果为16进制的binary,参数设置为FALSE;

dwKeyLength是密码缓冲区的长度,密码为口令格式时,必须包括结尾的’\0’

pucKeyData如果字符串,则必须为ANSI类型,因此如果IDE环境将字符串配置为UNICODE,需要做转换,可使用WideCharToMultiByte,或者T2A,W2A宏。

bPersistent用来指示密码是否是持久的。如果不是,那么该密码只在本次启动有效;否则下次启动Soft AP依然使用本次设置的密码。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    UCHAR keyBuf[100] = {0};
#ifdef _UNICODE
WideCharToMultiByte(CP_ACP,
0,
strSecondaryKey.GetBuffer(0),
strSecondaryKey.GetLength(),
(LPSTR)keyBuf,
100,
NULL,
NULL);
#else
memcpy(keyBuf, strSecondaryKey.GetBuffer(0), strlen(strSecondaryKey.GetBuffer(0)));
#endif
dwReturnValue = WlanHostedNetworkSetSecondaryKey(m_hWlanClient,
strlen((const char*)keyBuf) + 1,
keyBuf,
TRUE,
FALSE,
&dwFailedReason,
NULL);
if(ERROR_SUCCESS != dwReturnValue)
{
return -1;
}

启动或者停止Soft AP,需要用到如下四个函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
DWORD WINAPI WlanHostedNetworkStartUsing(
_In_ HANDLE hClientHandle,
_Out_opt_ PWLAN_HOSTED_NETWORK_REASON pFailReason,
_Reserved_ PVOID pvReserved
);


DWORD WINAPI WlanHostedNetworkStopUsing(
_In_ HANDLE hClientHandle,
_Out_opt_ PWLAN_HOSTED_NETWORK_REASON pFailReason,
_Reserved_ PVOID pvReserved
);

DWORD WINAPI WlanHostedNetworkForceStart(
_In_ HANDLE hClientHandle,
_Out_opt_ PWLAN_HOSTED_NETWORK_REASON pFailReason,
_Reserved_ PVOID pvReserved
);

DWORD WINAPI WlanHostedNetworkForceStop(
_In_ HANDLE hClientHandle,
_Out_opt_ PWLAN_HOSTED_NETWORK_REASON pFailReason,
_Reserved_ PVOID pvReserved
);

参数的含义很直观,这里不再做更多地解释。值得注意的是,如果用StartUsing或者StopUsing版本的函数时,如果有客户端连接到了AP,调用WlanHostedNetworkStopUsing并不能立即停止Soft AP,而要等到客户端主动断开连接后,Soft AP才会停止。如果调用带Force的函数版本,则会强制停止Soft AP,不管是否有客户端正在连接到该AP上。当然,调用带Force的函数版本需要程序以管理员方式启动。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
dwReturnValue = WlanHostedNetworkStartUsing(m_hWlanClient, &dwFailedReason, NULL);
if(ERROR_SUCCESS != dwReturnValue)
{
if (wlan_hosted_network_reason_interface_unavailable == dwFailedReason)
{
return 0;
}
return -1;
}

dwReturnValue = WlanHostedNetworkStopUsing(m_hWlanClient, &dwFailedReason, NULL);
if (ERROR_SUCCESS != dwReturnValue)
{
return -1;
}

启动Soft AP后,绑定Ip需要一定的时间,一般为2-3秒。Ip地址一般为192.168.173.1(也有可能是192.168.137.1).

调试程序时,可使用命令行方式使用Soft AP(管理员方式打开cmd):

查看当前承载网络状态 - netsh wlan show hostednetwork

配置承载网络属性,如SSID,密码等 - netsh wlan set hostednetwork ssid=***** key=***** mode=allow|disallow (星号部分为ascii字符,key必须在8-63个字符之间)

启动承载网络 - netsh wlan start hostednetwork

关闭承载网络 - netsh wlan stop hostednetwork

Windows 8 / 8.1 禁用驱动签名最详细图文教程

Posted on 2013-09-10 | Edited on 2019-04-14

Windows 8

鼠标右上角/右下角弹出边栏,选择“设置”

点击“更改电脑设置”

选择“常规”,右侧拖到底,点击“高级启动”-“立即重启”;

稍后进入恢复页面,选择“疑难解答”

进入疑难解答后,选择“高级选项”;

进入高级选项后,选择“启动设置”;

点击“重启”;

重启后,按键盘上的数字键7即可。


Windows 8.1

鼠标右上角/右下角弹出边栏,选择“设置”

点击“更改电脑设置”

在电脑设置里,点击“更新和恢复”;

在更新和恢复里,点击“恢复”,在右侧点击“高级启动”-“立即重启”;

稍后进入恢复界面,点击“疑难解答”;

之后的步骤和Windows 8一致,选择“高级选项”-“启动设置”-“重启”-键盘数字键7,即可。

1…56
Justin Su

Justin Su

想法 玩物 创意
12 posts
1 categories
1 tags
E-Mail GitHub Twitter Instagram
© 2013 – 2019 radiolover
Powered by Hexo v3.8.0
|
Theme – NexT.Pisces v7.1.0
- 科技美学 - 爱好天文的工程师 - 上海 - WIRELESS - 区块链 - 自驾旅行 - 尼康爱好者 - EDM - 火车迷 - 极简主义 -