【此刻我要大大地記錄一下!】

這個折騰了我好幾天的Windows 7 API終於讓我搞定了!

利用Windows ICS API 和Windows 7 API中全新的Wireless Hosted Network,將本地的有線連接共享給Microsoft虛擬Wifi,使得本地計算機在windows 7下變成AP!

這個操作的手動操作部分,我在前一篇文章[譯] 關於無線承載網絡(Wireless Hosted Network)中已經講明白了,但是Windows 7為我們提供了相關操作的API,所以,我想,可否不需要去記錄那些繁瑣的命令,也不要打開命令行,只需要用一個C++程序,將所有的操作封裝在一起,那麼便可以實現!

於是,開啓了我苦逼地閲讀Windows API的旅程。。

其實原理非常簡單,首先想辦法開啓Windows的ICS服務,然後開啓Wireless Hosted Network,再將兩個關聯起來。可是,就是這麼easy的邏輯,老紙找這些API找了好久啊~~~主要也是之前不懂這些API怎麼用,再加上一直查不到相關的資料,最後,幾番折騰,終於在官方文檔、走過無數彎路、MSDN的友情幫助,以及各大論壇的細枝末節中,我終於找到蛛絲馬跡,將功能完全實現了!

廢話不多説,直接上代碼!

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 

// Copyright (C) Microsoft.  All rights reserved.
 
#define WIN32_LEAN_AND_MEAN
 
#include "stdafx.h"
 
#include <windows.h>
#include <objbase.h>
#include <netcon.h>
#include <stdio.h>
 
#include <NetCon.h>
 
#include <locale.h>
 
#include <wlanapi.h>
#include <WinNetWk.h>
#include <netlistmgr.h>
 
#include <ShObjIdl.h>
 
#pragma comment (lib, "wlanapi.lib")
#pragma comment (lib,"Mpr.lib")
 
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "oleaut32.lib")
 
// as in winsock.h
#define NAT_PROTOCOL_TCP 6
#define NAT_PROTOCOL_UDP 17
 
HRESULT AddSharingNet (INetSharingManager* pNSM)
{
INetConnection * pNC = NULL; // fill this out for part 2 below
 
    INetSharingEveryConnectionCollection * pNSECC = NULL;
    HRESULT hr = pNSM->get_EnumEveryConnection (&pNSECC);
    if (!pNSECC)
        wprintf (L"failed to get EveryConnectionCollection!\r\n");
    else {
        // enumerate connections
        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);
            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");
 
if(pNP->Status == NCS_CONNECTED){
hr = pNSM->get_INetSharingConfigurationForINetConnection (pNC, &pNSC);
hr = pNSC->EnableSharing(ICSSHARINGTYPE_PUBLIC);
pNSC->Release();
 
}
 
if(!strcmp((char*)(pNP->pszwName),(char*)(L"leonchiao"))){
pVWifi = pNP;
hr = pNSM->get_INetSharingConfigurationForINetConnection(pNC,&pVWifiNSC);
pVWifiNSC->EnableSharing(ICSSHARINGTYPE_PRIVATE);
wprintf(L"\nIs this VWifi?--%s\n\n",pVWifi->pszwDeviceName);
}
}
}
}
 
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;
}
 
HRESULT StartHostednetwork()
{
DWORD dwNegotiatedVersion = 1;
HANDLE hClientHandle = 0;
DWORD dwClientVersion = 2;
 
DWORD hWlan;
DWORD hStart;
WLAN_HOSTED_NETWORK_REASON failReason;
char result[600];
 
DWORD dwKeyLength = 10;
BOOL bIsPassPhrase = true;
BOOL bPersistent = true;
DWORD hSecondkey;
 
hWlan = WlanOpenHandle(dwClientVersion,NULL,&dwNegotiatedVersion,&hClientHandle);
 
DWORD dwRetVal;
TCHAR UserName[80];
    DWORD dwNameLength = sizeof(UserName);
 
if(hWlan == ERROR_SUCCESS)
{
hStart = WlanHostedNetworkStartUsing (hClientHandle,&failReason,NULL);
wprintf(L"Starting Hostednetwork!\n");
}
 
return hStart;
 
}
 
int main()
{
CoInitialize (NULL);
 
    // init security to enum RAS connections
    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");
else{
AddSharingNet(pNSM);
StartHostednetwork();
}
 
getchar();
 
return (int)hr;
}

 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

我簡單解釋一下代碼:(1)第一個函數是HRESULT AddSharingNet (INetSharingManager* pNSM),這個函數的作用就是開啓ICS服務,並且將ICS服務共享出去。除此之外,我在函數中將所有的網絡適配器都打印了出來,可以為進一步開發做鋪墊。這裏面比較重要的一個地方是用紅色標記出來的,也就是説,ICS需要PUBLIC的共享。另一個重要的地方是用藍色標記出來的,這裏主要説明的是,在找到Microsoft 虛擬Wifi之後,你需要為這個虛擬wifi做映射,那麼映射之前你得先找到這個網絡適配器,所以就先將它保存在pVWifiNSC中,然後這個時候記錄下來的適配器是虛擬Wifi,這是將虛擬wifi進行PRIVATE共享,它會自動和本機的有線連接進行關聯,實現內部的ICS共享。這一步就是這麼簡單,但是就是這麼簡單,然我嘗試了N種方法,最終終於搞定!

(2)第二個函數是HRESULT StartHostednetwork(),這個函數很簡單,就是開啓Wireless Hosted Network,如果你對這裏不熟悉,很容易在Windows 7 API W部分找到這些API,而且我的上一篇文章頁提到了如何使用這些API。

 

就這樣,整個工作就結束了,老紙可是花了九牛二虎之力才搞定的,真的不容易啊!

期間走了很多彎路,而且發現沒有其他人寫過類似的代碼,連個可以參考的都沒有,最後自己摸黑走,實驗了很多種API,思來想去找了很多種辦法,都不成功,最後幾經周折,功夫不負有心人,終於將問題搞定!

不得不感嘆一下啊!哈哈~