VC++ win7 下實現 WIFI 共享工具 附源代碼(無線承載網絡)

宿舍用手機連 wifi 總是要用瀏覽器登錄聯通的 wlan 登陸頁面,無奈手機太挫內存只有 512M,開個網頁再幹其他的事情就卡的要死,所以果斷下載了個 wifi 共享精靈。用了一次就果斷卸載了,爲啥呢?竟然有廣告,受不了啊。正好在學 VC++ 算了自己做一個吧。  

關於無線承載網絡

無線承載網絡 (Wireless Hosted Network) 是指安裝有無線局域網服務的 Windows 7 和 Windows Server 2008 R2 所提供的一種 WLAN 功能,具備兩項主要功能:

第一、把一個物理無線網卡虛擬化成一個或多個虛擬無線網卡,稱爲虛擬的 WiFi。

第二、藉助無線網卡把當前接網絡虛擬成爲一個基於軟件的無線接入點,稱爲虛擬 AP 或軟 AP。

========================= 萬惡的分割線 ===========================

項目需要包含 wlanapi.h 頭文件和 wlanapi.lib 庫

備註:測試環境 win7_64, 建議關閉一些安全軟件,(比如我測試的時候忘了關 comodo 導致防火牆總是拒絕其他設備的連接)。

=============================================================

功能不復雜,用到的主要函數有下面幾個

1. 調用 WlanOpenHandled 得到一個連接 hClientHandle,下面的操作都要用到這個連接。當然程序退出的時候記得調用 WlanCloseHandle 關閉這個連接。

DWORD WINAPI WlanOpenHandle(
  _In_        DWORD dwClientVersion,
  _Reserved_  PVOID pReserved,
  _Out_       PDWORD pdwNegotiatedVersion,
  _Out_       PHANDLE phClientHandle
);

DWORD WINAPI WlanCloseHandle(
  _In_        HANDLE hClientHandle,
  _Reserved_  PVOID pReserved
);

 

 

 

2. 下面的函數用來設置承載網絡的一些屬性。

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
);typedef enum _WLAN_HOSTED_NETWORK_OPCODE { 
  wlan_hosted_network_opcode_connection_settings,          //設置一些連接屬性
  wlan_hosted_network_opcode_security_settings,            //設置安全屬性
  wlan_hosted_network_opcode_station_profile,              //query the wireless Hosted Network station profile
  wlan_hosted_network_opcode_enable                        //query or set the wireless Hosted Network enabled flag
} WLAN_HOSTED_NETWORK_OPCODE, *PWLAN_HOSTED_NETWORK_OPCODE;

 

3. 啓用和禁用無線承載網絡。

打開網絡和共享中心 單擊更改適配器設置,如果啓用了無線承載網絡 面板裏面就會有描述爲 Microsoft Virtual WiFi Miniport Adapter 的一個虛擬網卡。禁用之後這個虛擬網卡就會消失了。

當然只有啓用了無線承載網絡才能分享 wifi 啦

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
);

 

 

4. 連接和斷開網絡

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
);

 

5. 用來查詢承載網絡的網絡狀況。

DWORD WINAPI WlanHostedNetworkQueryStatus(
  _In_        HANDLE hClientHandle,
  _Out_       PWLAN_HOSTED_NETWORK_STATUS *ppWlanHostedNetworkStatus,
  _Reserved_  PVOID pvReserved
);

 

typedef struct _WLAN_HOSTED_NETWORK_STATUS {
  WLAN_HOSTED_NETWORK_STATE      HostedNetworkState;
  GUID                           IPDeviceID;
  DOT11_MAC_ADDRESS              wlanHostedNetworkBSSID;
  DOT11_PHY_TYPE                 dot11PhyType;
  ULONG                          ulChannelFrequency;
  DWORD                          dwNumberOfPeers;            //已連接的節點數目
  WLAN_HOSTED_NETWORK_PEER_STATE PeerList[1];                //存放節點信息的數組
} WLAN_HOSTED_NETWORK_STATUS, *PWLAN_HOSTED_NETWORK_STATUS;

typedef struct _WLAN_HOSTED_NETWORK_PEER_STATE {
  DOT11_MAC_ADDRESS                   PeerMacAddress;        //節點設備的MAC地址
  WLAN_HOSTED_NETWORK_PEER_AUTH_STATE PeerAuthState;            //節點的認證狀態
} WLAN_HOSTED_NETWORK_PEER_STATE, *PWLAN_HOSTED_NETWORK_PEER_STATE;

調用 WlanHostedNetworkQueryStatus 將得到一個 WLAN_HOSTED_NETWORK_STATUS 結構體,就可以查詢一些網絡基本信息了,比如 dwNumberOfPeers 連接到這個網絡的節點數,PeerList 數組存放着對應節點的詳細信息,包括 MAC 地址和認證狀態。

6. 用來設置密碼

注意密碼長度必須 大於 8  小於 63 否則會調用失敗

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
);

 

====================== 貼代碼 ==========================

 

//WIFIMAIN.h  實現文件
#pragma once
#include <wlanapi.h>
#pragma comment(lib,"wlanapi.lib")

// WIFIMAIN

class WIFIMAIN : public CWnd
{
	DECLARE_DYNAMIC(WIFIMAIN)

public:
	WIFIMAIN();
	virtual ~WIFIMAIN();

protected:
	DECLARE_MESSAGE_MAP()
private:
	bool allow;
	bool start;
	HANDLE hClient;
public:
	int Init(void);
	int AllowHostedNetWork(void);
	int DisallowHostedNetWork(void);
	int StartHostedNetWork(void);
	int StopHostedNetWork(void);
	bool isStart(void);
	bool isAllow(void);
	int Resume(void);
	int getpeernumber(void);
	int SetKEY(CString key);
	int SetSSID(CString ssidname);
};

 

 

 

// WIFIMAIN.cpp : 實現文件
//

#include "stdafx.h"
#include "wifi共享1028.h"
#include "WIFIMAIN.h"


// WIFIMAIN

IMPLEMENT_DYNAMIC(WIFIMAIN, CWnd)

WIFIMAIN::WIFIMAIN()
: allow(false)
, start(false)
{
	Init();
}

WIFIMAIN::~WIFIMAIN()
{
	StopHostedNetWork();
	WlanCloseHandle(hClient, NULL);
}


BEGIN_MESSAGE_MAP(WIFIMAIN, CWnd)
END_MESSAGE_MAP()



// WIFIMAIN 消息處理程序






int WIFIMAIN::Init(void)
{
	DWORD dwCurVersion = 0;
    DWORD dwResult = 0;
    
    dwResult = WlanOpenHandle(WLAN_API_VERSION, NULL, &dwCurVersion, &hClient);
	if( ERROR_SUCCESS != dwResult )
	{
		return -1;
	}


	BOOL bIsAllow = true;
    WLAN_HOSTED_NETWORK_REASON dwFailedReason;
	dwResult = WlanHostedNetworkSetProperty(hClient,
											wlan_hosted_network_opcode_enable, 
											sizeof(BOOL),
											&bIsAllow,
											&dwFailedReason,
											NULL);
	if( ERROR_SUCCESS != dwResult )
	{
		return -2;
	}
	
	return 0;
}


int WIFIMAIN::AllowHostedNetWork(void)
{
	PWLAN_HOSTED_NETWORK_REASON pFailReason = NULL;
	
	DWORD dwResult= 0;
	dwResult=WlanHostedNetworkForceStart(hClient,pFailReason,NULL);
	if( dwResult != ERROR_SUCCESS )
	{
		return -1;
	}
	allow=true;
	return 0;
}


int WIFIMAIN::DisallowHostedNetWork(void)
{
	PWLAN_HOSTED_NETWORK_REASON pFailReason = NULL;
	DWORD dwResult= 0;
	dwResult=WlanHostedNetworkForceStop(hClient,pFailReason,NULL);
	if( dwResult != ERROR_SUCCESS )
	{
		return -1;
	}
	allow=false;
	return 0;
}


int WIFIMAIN::StartHostedNetWork(void)
{
	PWLAN_HOSTED_NETWORK_REASON pFailReason = NULL;
	DWORD dwResult= 0;
	dwResult=WlanHostedNetworkStartUsing(hClient,pFailReason,NULL);
	if( dwResult != ERROR_SUCCESS )
	{
		return -1;
	}
	start=true;
	return 0;
}


int WIFIMAIN::StopHostedNetWork(void)
{
	PWLAN_HOSTED_NETWORK_REASON pFailReason = NULL;
	DWORD dwResult= 0;
	dwResult=WlanHostedNetworkStopUsing(hClient,pFailReason,NULL);
	if( dwResult != ERROR_SUCCESS )
	{
		return -1;
	}
	start=false;
	return 0;
}



bool WIFIMAIN::isStart(void)
{
	return start;
}


bool WIFIMAIN::isAllow(void)
{
	return allow;
}


int WIFIMAIN::Resume(void)
{
	DWORD dwResult = 0;
    
	BOOL bIsAllow = false;
    WLAN_HOSTED_NETWORK_REASON dwFailedReason;
	dwResult = WlanHostedNetworkSetProperty(hClient,
											wlan_hosted_network_opcode_enable, 
											sizeof(BOOL),
											&bIsAllow,
											&dwFailedReason,
											NULL);
	if( ERROR_SUCCESS != dwResult )
	{
		return -2;
	}
	
	return 0;
}


int WIFIMAIN::getpeernumber(void)
{
	PWLAN_HOSTED_NETWORK_STATUS ppWlanHostedNetworkStatus=NULL;
	int retval = WlanHostedNetworkQueryStatus(hClient,&ppWlanHostedNetworkStatus,NULL);
	if(  retval != ERROR_SUCCESS ){
		return -1;
	}
	return ppWlanHostedNetworkStatus->dwNumberOfPeers;
}


int WIFIMAIN::SetKEY(CString key)
{
	char chkey[64];
	int index;
	for(index=0; index<key.GetLength(); index++ )
	{
		chkey[index] = key[index];
	}
	chkey[index]='\0';


	WLAN_HOSTED_NETWORK_REASON dwFailedReason;
		
	DWORD dwResult= 0;
	dwResult = WlanHostedNetworkSetSecondaryKey(hClient,
												strlen((const char*)chkey) + 1,
												(PUCHAR)chkey,
												TRUE,
												FALSE,
												&dwFailedReason,
												NULL);
    if(ERROR_SUCCESS != dwResult)
    {
       return -1;
    }

	return 0;
}


int WIFIMAIN::SetSSID(CString ssidname)
{
	
	char chname[64];
	int index;
	for(index=0; index<ssidname.GetLength(); index++ )
	{
		chname[index] = ssidname[index];
	}
	chname[index]='\0';
	
	DWORD dwResult= 0;
	WLAN_HOSTED_NETWORK_REASON dwFailedReason;
	WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS cfg;
    memset(&cfg, 0sizeof(WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS));

	memcpy( cfg.hostedNetworkSSID.ucSSID, chname, strlen(chname)  ) ;
    cfg.hostedNetworkSSID.uSSIDLength = strlen((const char*)cfg.hostedNetworkSSID.ucSSID);
    cfg.dwMaxNumberOfPeers = 20;		//最大連接數    

    dwResult = WlanHostedNetworkSetProperty(hClient, 
											wlan_hosted_network_opcode_connection_settings, 
											sizeof(WLAN_HOSTED_NETWORK_CONNECTION_SETTINGS), 
											&cfg,
											&dwFailedReason,
											NULL);
     if(ERROR_SUCCESS != dwResult )
	 {
		return -1;
	 }

	 return 0;
}

 

 

==========================================

這裏只貼出了比較重要的代碼,其他的略去了,需要的可以去我的網盤下載完整項目代碼。

代碼和程序下載:http://pan.baidu.com/s/1GI0kG
程序只完成了基本功能,還有待完善,但是學習的過程還是很有意思的。

下面是幾篇關於無線承載網絡比較不錯的文章,當時對我幫助很大。

關於無線承載網絡 http://blog.wbpluto.com/2010/08/about-wireless-hosted-network/

==========================================

2014-3-14 修改:

實在抱歉,以前寫的時候有些東西沒有補充完整,導致讓好多網友走了彎路,今天把大家問的幾個較多的問題回覆補充一下,以免給大家在帶來困擾。

1. 我寫程序的時候環境是 win7 64 位,vs2010. 需要用到的某些 api 可能在 xp 下無法編譯。

2. 這個版本的程序還沒有加入 自動設置網絡連接共享的功能,需要手動設置在網卡(接入 internet 的網卡)屬性中設置網絡連接共享,相關 api 參考 http://msdn.microsoft.com/en-us/library/bb525393%28v=vs.85%29.aspx

3. 面板上的開機自動啓動代碼沒有加入,發佈的時候都忘記取消這個控件了,哎 犯罪了。

4.win8 下會提示某些運行庫找不到,這個屬於兼容性問題,屬性中設置以 win7 兼容模式運行即可。部分電腦需要以管理員權限運行。(估計是啓用虛擬網卡的 api 需要較高權限吧)

本來準備過年就寫個新版本的,但是開學太忙就一直拖着沒開始。等時間多了我會針對大家反映的問題推出一個新的版本。

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