c++ WlanAPI 承載網絡 連接無線網絡

最近在玩樹莓派,燒錄的也是win10  IOT 系統,然後想弄一個界面可以手動設置wifi熱點,所以找了找windows的wlanAPI.


然後發現網上很多關於 保存了密碼的無線網絡 的連接方法,如:http://blog.csdn.net/lincyang/article/details/34430939這位仁兄的文章,
但是如何設置熱點的幾乎沒有!


所以只能自己弄,麻煩的要命,其實在電腦上是不需要這麼麻煩的用代碼來實現的,直接用dos命令就能搞定,這只是個人的愛好和需要。dos命令就不介紹了百度一大堆!



#include <windows.h>
#include <wlanapi.h>
#include <objbase.h>
#include <wtypes.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
// Need to link with Wlanapi.lib and Ole32.lib
#pragma comment(lib, "wlanapi.lib")
#pragma comment(lib, "ole32.lib")
#include <atlconv.h>


#include <iostream>
using namespace std;


#include <atlstr.h>








#include <netcon.h>
#include <NetCon.h>
#include <locale.h>
#include <WinNetWk.h>
#include <netlistmgr.h>
#include <ShObjIdl.h>
#pragma comment (lib,"Mpr.lib")
#pragma comment(lib, "oleaut32.lib")


// 設置internet 連接共享(ICS)
HRESULT AddSharingNet( INetSharingManager* pNSM )
{


INetConnection * pNC = NULL; 


INetSharingEveryConnectionCollection * pNSECC = NULL;
// 枚舉設備(即本地連接,無線網絡連接。。。)
HRESULT hr = pNSM->get_EnumEveryConnection( &pNSECC );
if (!pNSECC)
{
wprintf( L"failed to get EveryConnectionCollection!\r\n" );
}
else // 反之獲取 枚舉列表成功 
{
IEnumVARIANT * pEV = NULL;
IUnknown * pUnk = NULL;
hr = pNSECC->get__NewEnum( &pUnk );
if (pUnk)
{
hr = pUnk->QueryInterface( __uuidof(IEnumVARIANT), (void**)&pEV );
pUnk->Release( );
}


if (pEV)
{
VARIANT v;
VariantInit( &v );// 初始化 錯誤 類型VARIANT(是錯誤可捕捉)
BOOL bFoundIt = FALSE;
INetSharingConfiguration * pNSC = NULL;
INetSharingConfiguration * pVWifiNSC = NULL;
NETCON_PROPERTIES* pVWifi = NULL;
while (S_OK == pEV->Next( 1, &v, NULL ))// 枚舉序列中的元素 ,返回錯誤值
{
if (V_VT( &v ) == VT_UNKNOWN)// 返回位置類型
{
V_UNKNOWN( &v )->QueryInterface( __uuidof(INetConnection), (void**)&pNC );  // 查詢設備是否支持接口
if (pNC)
{
NETCON_PROPERTIES* pNP = NULL;
pNC->GetProperties( &pNP );// 獲取設備屬性
setlocale( LC_ALL, "chs" );
wprintf( L"pszwName--%s\n", pNP->pszwName );
wprintf( L"pszwDeviceName--%s\n", pNP->pszwDeviceName );
wprintf( L"Status--%d\n", pNP->Status );// 這個值是表示網絡是否禁用
wprintf( L"MediaType--%d\n", pNP->MediaType );
wprintf( L"dwCharacter--%d\n", pNP->dwCharacter );
wprintf( L"clsidThisObject--%d\n", pNP->clsidThisObject );
wprintf( L"clsidUiObject--%d\n", pNP->clsidUiObject );
wprintf( L"\n" );


//  被共享的網絡設置爲公開共享
USES_CONVERSION;
std::string  str( W2A( pNP->pszwDeviceName ) );
/* 這裏我是爲了開一個虛擬的網絡(一般電腦上都會有本地連接,無線網絡這兩個,而我需要設置wifi熱點, 即承載網絡)*/
if (pNP->Status == NCS_CONNECTED && (- 1 == str.find( "Virtual" )))
{
hr = pNSM->get_INetSharingConfigurationForINetConnection( pNC, &pNSC );
hr = pNSC->EnableSharing( ICSSHARINGTYPE_PUBLIC );
pNSC->Release( );
}

/* 虛擬無線網絡設置(本地網絡或者是無線網絡都可以,前提是這個網絡需要是能連接上外網的,上面那個就是共享的它的外網)*/
if (pNP->Status == NCS_CONNECTED && (-1 != str.find( "Virtual" )))
{
pVWifi = pNP;
hr = pNSM->get_INetSharingConfigurationForINetConnection( pNC, &pVWifiNSC );
pVWifiNSC->EnableSharing( ICSSHARINGTYPE_PRIVATE );
wprintf( L"\nIs this VWifi?--%s\n\n", pVWifi->pszwDeviceName );
}
}
}
}
// 因設計需要 必須要有一個 虛擬的網絡  如果沒有那麼這個指針爲空
if (pVWifiNSC == NULL )
{
cout << "pVWifiNSC NULL" << endl;
return -1;
}


INetSharingPortMapping * pNSPM = NULL;
BSTR pszwName = pVWifi->pszwName;
wprintf( L"BSTR--------------%s\n", pszwName );    // 被設置的虛擬網絡
pVWifiNSC->Release( );
if (pNSPM)
{
wprintf( L"just added ........................................................!\r\n" );
hr = pNSPM->Enable( );
wprintf( L"just enabled port mapping!\r\n" );


INetSharingPortMappingProps* pMapping = NULL;
pNSPM->get_Properties( &pMapping );
BSTR result = NULL;
long port = 0;
pMapping->get_Name( &result );
pMapping->get_ExternalPort( &port );
wprintf( L"NAMEEEEE::::%s\n", result );
wprintf( L"exPortttttt::::%d\n", port );
pNSPM->Release( );
}
}
}


return hr;
}






int main( )
{


CoInitialize( NULL );
CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL );


INetSharingManager * pNSM = NULL;
HRESULT hr = ::CoCreateInstance( __uuidof(NetSharingManager), NULL, CLSCTX_ALL,
__uuidof(INetSharingManager), (void**)&pNSM );


if (!pNSM)
{
wprintf( L"failed to create NetSharingManager object\r\n" );
}
// 添加共享功能
AddSharingNet( pNSM );




DWORD dError = 0;
DWORD dwServiceVersion = 0;
HANDLE hClient = NULL;
if (ERROR_SUCCESS != (dError = WlanOpenHandle(
WLAN_API_VERSION,
NULL,               
&dwServiceVersion,
&hClient
)))
{
cout << "WlanOpenHandle ret dwError = " << dError << endl;
return -1;
}
// check service version
if (WLAN_API_VERSION_MAJOR( dwServiceVersion ) < WLAN_API_VERSION_MAJOR( WLAN_API_VERSION_2_0 ))
{
cout << "WlanCloseHandle " << endl;
WlanCloseHandle( hClient, NULL );
}






// 設置承載網絡模式爲允許
BOOL bIsAllow = TRUE;
WLAN_HOSTED_NETWORK_REASON dwFailedReason;
DWORD dwReturnValue = WlanHostedNetworkSetProperty( hClient,
wlan_hosted_network_opcode_enable,
sizeof( BOOL ),
&bIsAllow,
&dwFailedReason,
NULL );
if (ERROR_SUCCESS != dwReturnValue)
{


cout << "WlanHostedNetworkSetProperty  ret dwReturnValue" << dwReturnValue <<endl;
return -1;
}


// dwReturnValue = WlanHostedNetworkStopUsing( hClient, &dwFailedReason, NULL );


// 設置承載網絡的SSID和最大連接數
WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS wlanConnectionSetting;
memset( &wlanConnectionSetting, 0, sizeof( WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS ) );






string strSSIDInsert;
cout << "設置熱點名稱:";
cin >> strSSIDInsert;
//CString strSSID = _T("chenzhen3");
CString strSSID( strSSIDInsert.c_str( ) );




// 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( hClient,
wlan_hosted_network_opcode_connection_settings,
sizeof( WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS ),
&wlanConnectionSetting,
&dwFailedReason,
NULL );
if (ERROR_SUCCESS != dwReturnValue)
{
cout << "WlanHostedNetworkSetProperty ret " << dwReturnValue << endl;
return -1;
}

string strPass("");
cout << "設置熱點密碼:";
cin >> strPass;
//CString strSecondaryKey = _T( "12345678" );
CString strSecondaryKey( strPass.c_str( ) );


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
// 設置密碼
PVOID  pvReserved = NULL;
dwReturnValue = WlanHostedNetworkSetSecondaryKey( hClient,
strlen( (const char*)keyBuf ) + 1,
keyBuf,
TRUE,
FALSE,
&dwFailedReason,
pvReserved );
if (ERROR_SUCCESS != dwReturnValue)
{
if ( ERROR_INVALID_PARAMETER == dwReturnValue )
{
if (hClient == NULL)
{
cout << "hClient == NULL" << endl;
}
if ( keyBuf == NULL )
{
cout << "keyBuf == NULL" << endl;
}
if (pvReserved != NULL)
{
cout << "pvReserved != NULL" << endl;
}
cout << dwReturnValue << "---"<< ERROR_INVALID_PARAMETER << endl;
}
return -1;
}
// 啓用承載網絡設置
dwReturnValue = WlanHostedNetworkStartUsing( hClient, &dwFailedReason, NULL );
if (ERROR_SUCCESS != dwReturnValue)
{
if (wlan_hosted_network_reason_interface_unavailable == dwFailedReason)
{
cout << "無線承載網絡禁用" << endl;
return 0;
}
cout << "未知失敗" << endl;
return -1;
}
//  停止Soft AP
// dwReturnValue = WlanHostedNetworkStopUsing( hClient, &dwFailedReason, NULL );
// if (ERROR_SUCCESS != dwReturnValue)
// {
// if (ERROR_INVALID_HANDLE == dwReturnValue || ERROR_INVALID_PARAMETER == dwReturnValue ||
// ERROR_INVALID_STATE == dwReturnValue || ERROR_SERVICE_NOT_ACTIVE == dwReturnValue)
// {
// cout << dwReturnValue << endl;
// }
// 
// cout << dwReturnValue << endl;
// return -1;
// }
// // 啓用承載網絡
dwReturnValue = WlanHostedNetworkForceStart( hClient, &dwFailedReason, NULL );
if (ERROR_SUCCESS != dwReturnValue)
{
cout << "ri" << endl;
return -1;
}




system( "pause" );


return 0;
}




要用的可以直接拷貝,可以編譯直接使用,當然這是個demo,看着不舒服的自己改改哈!

另:https://msdn.microsoft.com/en-us/library/windows/desktop/dd439506(v=vs.85).aspx  微軟官方API地址!




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章