2078 lines
68 KiB
C++
2078 lines
68 KiB
C++
#include "pch.h"
|
|
#pragma hdrstop
|
|
#include "connutil.h"
|
|
#include "ncnetcon.h"
|
|
#include "ncperms.h"
|
|
#include "ncui.h"
|
|
#include "lanui.h"
|
|
#include "xpsp1res.h"
|
|
#include "eapolui.h"
|
|
#include "util.h"
|
|
#include "lanhelp.h"
|
|
#include "wzcprops.h"
|
|
#include "eapolpage.h"
|
|
#include "wzcpage.h"
|
|
#include "wzcui.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// CWZCConfig related stuff
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
// constructor
|
|
CWZCConfig::CWZCConfig(DWORD dwFlags, PWZC_WLAN_CONFIG pwzcConfig)
|
|
{
|
|
m_dwFlags = dwFlags;
|
|
CopyMemory(&m_wzcConfig, pwzcConfig, sizeof(WZC_WLAN_CONFIG));
|
|
m_pPrev = m_pNext = this;
|
|
m_nListIndex = -1;
|
|
m_pEapolConfig = NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// destructor
|
|
CWZCConfig::~CWZCConfig()
|
|
{
|
|
// remove the object from the list
|
|
m_pPrev->m_pNext = m_pNext;
|
|
m_pNext->m_pPrev = m_pPrev;
|
|
if (m_pEapolConfig != NULL)
|
|
{
|
|
delete m_pEapolConfig;
|
|
m_pEapolConfig = NULL;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// checks whether this configuration matches with the one from pwzcConfig
|
|
BOOL
|
|
CWZCConfig::Match(PWZC_WLAN_CONFIG pwzcConfig)
|
|
{
|
|
BOOL bMatch;
|
|
|
|
// check whether the InfrastructureMode matches
|
|
bMatch = (m_wzcConfig.InfrastructureMode == pwzcConfig->InfrastructureMode);
|
|
// check whether the SSIDs are of the same length
|
|
bMatch = bMatch && (m_wzcConfig.Ssid.SsidLength == pwzcConfig->Ssid.SsidLength);
|
|
if (bMatch && m_wzcConfig.Ssid.SsidLength != 0)
|
|
{
|
|
// in case of Non empty SSIDs, check if they're the same
|
|
bMatch = (memcmp(m_wzcConfig.Ssid.Ssid,
|
|
pwzcConfig->Ssid.Ssid,
|
|
m_wzcConfig.Ssid.SsidLength)) == 0;
|
|
}
|
|
|
|
return bMatch;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// checks whether this configuration is weaker than the one given as parameter
|
|
BOOL
|
|
CWZCConfig::Weaker(PWZC_WLAN_CONFIG pwzcConfig)
|
|
{
|
|
BOOL bWeaker = FALSE;
|
|
|
|
// a configuration is stronger if its privacy bit is set while the matching one is not set
|
|
if (m_wzcConfig.Privacy != pwzcConfig->Privacy)
|
|
bWeaker = pwzcConfig->Privacy;
|
|
// if privacy bits are identical, a configuration is stronger if it has Open Auth mode
|
|
else if (m_wzcConfig.AuthenticationMode != pwzcConfig->AuthenticationMode)
|
|
bWeaker = (pwzcConfig->AuthenticationMode == Ndis802_11AuthModeOpen);
|
|
|
|
return bWeaker;
|
|
}
|
|
|
|
DWORD
|
|
CWZCConfig::AddConfigToListView(HWND hwndLV, INT nPos)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
// ugly but this is life. In order to convert the SSID to LPWSTR we need a buffer.
|
|
// We know an SSID can't exceed 32 chars (see NDIS_802_11_SSID from ntddndis.h) so
|
|
// make room for the null terminator and that's it. We could do mem alloc but I'm
|
|
// not sure it worth the effort (at runtime).
|
|
WCHAR wszSSID[33];
|
|
UINT nLenSSID = 0;
|
|
|
|
// convert the LPSTR (original SSID format) to LPWSTR (needed in List Ctrl)
|
|
if (m_wzcConfig.Ssid.SsidLength != 0)
|
|
{
|
|
nLenSSID = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
(LPCSTR)m_wzcConfig.Ssid.Ssid,
|
|
m_wzcConfig.Ssid.SsidLength,
|
|
wszSSID,
|
|
celems(wszSSID));
|
|
|
|
if (nLenSSID == 0)
|
|
dwErr = GetLastError();
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
LVITEM lvi={0};
|
|
UINT nImgIdx;
|
|
|
|
// put the null terminator
|
|
wszSSID[nLenSSID]=L'\0';
|
|
|
|
// get the item's image index
|
|
if (m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure)
|
|
{
|
|
nImgIdx = (m_dwFlags & WZC_DESCR_ACTIVE) ? WZCIMG_INFRA_ACTIVE :
|
|
((m_dwFlags & WZC_DESCR_VISIBLE) ? WZCIMG_INFRA_AIRING : WZCIMG_INFRA_SILENT);
|
|
}
|
|
else
|
|
{
|
|
nImgIdx = (m_dwFlags & WZC_DESCR_ACTIVE) ? WZCIMG_ADHOC_ACTIVE :
|
|
((m_dwFlags & WZC_DESCR_VISIBLE) ? WZCIMG_ADHOC_AIRING : WZCIMG_ADHOC_SILENT);
|
|
}
|
|
|
|
lvi.iItem = nPos;
|
|
lvi.iSubItem = 0;
|
|
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
|
lvi.pszText = wszSSID;
|
|
lvi.iImage = nImgIdx;
|
|
lvi.lParam = (LPARAM)this;
|
|
// store the list position in the object
|
|
m_nListIndex = ListView_InsertItem(hwndLV, &lvi);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// CWZeroConfPage related stuff
|
|
//
|
|
#define RFSH_TIMEOUT 3500
|
|
UINT g_TimerID = 371;
|
|
|
|
//+=================== PRIVATE MEMBERS =================================
|
|
DWORD
|
|
CWZeroConfPage::InitListViews()
|
|
{
|
|
RECT rc;
|
|
LV_COLUMN lvc = {0};
|
|
DWORD dwStyle;
|
|
|
|
// initialize the image list styles
|
|
dwStyle = ::GetWindowLong(m_hwndVLV, GWL_STYLE);
|
|
::SetWindowLong(m_hwndVLV, GWL_STYLE, (dwStyle | LVS_SHAREIMAGELISTS));
|
|
dwStyle = ::GetWindowLong(m_hwndPLV, GWL_STYLE);
|
|
::SetWindowLong(m_hwndPLV, GWL_STYLE, (dwStyle | LVS_SHAREIMAGELISTS));
|
|
|
|
// Create state image lists
|
|
m_hImgs = ImageList_LoadBitmapAndMirror(
|
|
_Module.GetResourceInstance(),
|
|
MAKEINTRESOURCE(IDB_WZCSTATE),
|
|
16,
|
|
0,
|
|
PALETTEINDEX(6));
|
|
|
|
ListView_SetImageList(m_hwndVLV, m_hImgs, LVSIL_SMALL);
|
|
ListView_SetImageList(m_hwndPLV, m_hImgs, LVSIL_SMALL);
|
|
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
|
|
::GetClientRect(m_hwndVLV, &rc);
|
|
lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
|
|
//lvc.cx = rc.right;
|
|
ListView_InsertColumn(m_hwndVLV, 0, &lvc);
|
|
|
|
::GetClientRect(m_hwndPLV, &rc);
|
|
lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL);
|
|
//lvc.cx = rc.right;
|
|
ListView_InsertColumn(m_hwndPLV, 0, &lvc);
|
|
|
|
ListView_SetExtendedListViewStyleEx(m_hwndPLV, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
|
|
ListView_SetExtendedListViewStyleEx(m_hwndVLV, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//+=================== PUBLIC MEMBERS =================================
|
|
//+---------------------------------------------------------------------
|
|
// CWZeroConfPage constructor
|
|
CWZeroConfPage::CWZeroConfPage(
|
|
IUnknown* punk,
|
|
INetCfg* pnc,
|
|
INetConnection* pconn,
|
|
const DWORD * adwHelpIDs)
|
|
{
|
|
m_pconn = pconn;
|
|
m_pnc = pnc;
|
|
m_adwHelpIDs = adwHelpIDs;
|
|
|
|
// initialize the WZC data
|
|
m_bHaveWZCData = FALSE;
|
|
ZeroMemory(&m_IntfEntry, sizeof(INTF_ENTRY));
|
|
m_dwOIDFlags = 0;
|
|
m_nTimer = 0;
|
|
m_hCursor = NULL;
|
|
|
|
// initialize all the control's handles
|
|
m_hckbEnable = NULL;
|
|
m_hwndVLV = NULL;
|
|
m_hwndPLV = NULL;
|
|
m_hbtnCopy = NULL;
|
|
m_hbtnRfsh = NULL;
|
|
m_hbtnAdd = NULL;
|
|
m_hbtnRem = NULL;
|
|
m_hbtnUp = NULL;
|
|
m_hbtnDown = NULL;
|
|
m_hbtnAdvanced = NULL;
|
|
m_hbtnProps = NULL;
|
|
m_hlblVisNet = NULL;
|
|
m_hlblPrefNet = NULL;
|
|
m_hlblAvail = NULL;
|
|
m_hlblPrefDesc = NULL;
|
|
m_hlblAdvDesc = NULL;
|
|
m_hbtnProps = NULL;
|
|
|
|
m_hImgs = NULL;
|
|
m_hIcoUp = NULL;
|
|
m_hIcoDown = NULL;
|
|
|
|
// default the infrastructure mode to Auto
|
|
m_dwCtlFlags = (INTFCTL_ENABLED | INTFCTL_FALLBACK | Ndis802_11AutoUnknown);
|
|
|
|
// init the internal list heads
|
|
m_pHdVList = NULL;
|
|
m_pHdPList = NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
CWZeroConfPage::~CWZeroConfPage()
|
|
{
|
|
if (m_hImgs != NULL)
|
|
ImageList_Destroy(m_hImgs);
|
|
if (m_hIcoUp != NULL)
|
|
DeleteObject(m_hIcoUp);
|
|
if (m_hIcoDown != NULL)
|
|
DeleteObject(m_hIcoDown);
|
|
|
|
// delete the internal INTF_ENTRY object
|
|
WZCDeleteIntfObj(&m_IntfEntry);
|
|
|
|
// delete the internal list of visible configurations
|
|
// (is like filling it with NULL)
|
|
FillVisibleList(NULL);
|
|
|
|
// delete the internal list of preferred configurations
|
|
// (is like filling it with NULL)
|
|
FillPreferredList(NULL);
|
|
|
|
if (m_nTimer != 0)
|
|
KillTimer(m_nTimer);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
// IsWireless - loads data from WZC if needed and checks whether the
|
|
// interface is wireless or not.
|
|
BOOL
|
|
CWZeroConfPage::IsWireless()
|
|
{
|
|
if (!m_bHaveWZCData)
|
|
{
|
|
BOOL bOk;
|
|
WCHAR wszGuid[c_cchGuidWithTerm];
|
|
NETCON_PROPERTIES *pProps = NULL;
|
|
|
|
bOk = SUCCEEDED(m_pconn->GetProperties(&pProps));
|
|
|
|
if (bOk)
|
|
{
|
|
UINT cch;
|
|
cch = ::StringFromGUID2(
|
|
pProps->guidId,
|
|
wszGuid,
|
|
c_cchGuidWithTerm);
|
|
FreeNetconProperties(pProps);
|
|
bOk = (cch != 0);
|
|
}
|
|
|
|
if (bOk)
|
|
{
|
|
WZCDeleteIntfObj(&m_IntfEntry);
|
|
ZeroMemory(&m_IntfEntry, sizeof(INTF_ENTRY));
|
|
m_IntfEntry.wszGuid = (LPWSTR)RpcCAlloc(sizeof(WCHAR)*c_cchGuidWithTerm);
|
|
bOk = (m_IntfEntry.wszGuid != NULL);
|
|
}
|
|
|
|
if (bOk)
|
|
{
|
|
DWORD dwErr;
|
|
|
|
CopyMemory(m_IntfEntry.wszGuid, wszGuid, c_cchGuidWithTerm*sizeof(WCHAR));
|
|
m_IntfEntry.wszDescr = NULL;
|
|
m_dwOIDFlags = 0;
|
|
|
|
dwErr = GetOIDs(INTF_ALL, &m_dwOIDFlags);
|
|
|
|
// if getting the oids failed or we could get the OIDs but the driver/firmware
|
|
// is not capable of doing the BSSID_LIST_SCAN it means we don't have enough
|
|
// driver/firmware support for having Zero Configuration running. This will
|
|
// result in not showing the Zero Configuration tab at all.
|
|
bOk = (dwErr == ERROR_SUCCESS) && (m_IntfEntry.dwCtlFlags & INTFCTL_OIDSSUPP);
|
|
|
|
if (m_IntfEntry.nAuthMode < 0)
|
|
m_IntfEntry.nAuthMode = 0;
|
|
if (m_IntfEntry.nInfraMode < 0)
|
|
m_IntfEntry.nInfraMode = 0;
|
|
|
|
if (!bOk)
|
|
{
|
|
WZCDeleteIntfObj(&m_IntfEntry);
|
|
ZeroMemory(&m_IntfEntry, sizeof(INTF_ENTRY));
|
|
}
|
|
}
|
|
|
|
m_bHaveWZCData = bOk;
|
|
}
|
|
|
|
return m_bHaveWZCData && (m_IntfEntry.ulPhysicalMediaType == NdisPhysicalMediumWirelessLan);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------
|
|
// GetOIDs - gets the OIDs for the m_IntfEntry member. It assumes the
|
|
// GUID is set already
|
|
DWORD
|
|
CWZeroConfPage::GetOIDs(DWORD dwInFlags, LPDWORD pdwOutFlags)
|
|
{
|
|
DWORD rpcStatus, dwOutFlags;
|
|
|
|
if (dwInFlags & INTF_DESCR)
|
|
{
|
|
RpcFree(m_IntfEntry.wszDescr);
|
|
m_IntfEntry.wszDescr = NULL;
|
|
}
|
|
if (dwInFlags & INTF_PREFLIST)
|
|
{
|
|
RpcFree(m_IntfEntry.rdStSSIDList.pData);
|
|
m_IntfEntry.rdStSSIDList.dwDataLen = 0;
|
|
m_IntfEntry.rdStSSIDList.pData = NULL;
|
|
}
|
|
if (dwInFlags & INTF_SSID)
|
|
{
|
|
RpcFree(m_IntfEntry.rdSSID.pData);
|
|
m_IntfEntry.rdSSID.dwDataLen = 0;
|
|
m_IntfEntry.rdSSID.pData = NULL;
|
|
}
|
|
if (dwInFlags & INTF_BSSID)
|
|
{
|
|
RpcFree(m_IntfEntry.rdBSSID.pData);
|
|
m_IntfEntry.rdBSSID.dwDataLen = 0;
|
|
m_IntfEntry.rdBSSID.pData = NULL;
|
|
}
|
|
if (dwInFlags & INTF_BSSIDLIST)
|
|
{
|
|
RpcFree(m_IntfEntry.rdBSSIDList.pData);
|
|
m_IntfEntry.rdBSSIDList.dwDataLen = 0;
|
|
m_IntfEntry.rdBSSIDList.pData = NULL;
|
|
}
|
|
rpcStatus = WZCQueryInterface(
|
|
NULL,
|
|
dwInFlags,
|
|
&m_IntfEntry,
|
|
pdwOutFlags);
|
|
|
|
return rpcStatus;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
// HelpCenter - brings up the help topic given as parameter
|
|
DWORD
|
|
CWZeroConfPage::HelpCenter(LPCTSTR wszTopic)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
SHELLEXECUTEINFO shexinfo = {0};
|
|
|
|
shexinfo.cbSize = sizeof (shexinfo);
|
|
shexinfo.fMask = SEE_MASK_FLAG_NO_UI;
|
|
shexinfo.nShow = SW_SHOWNORMAL;
|
|
shexinfo.lpFile = wszTopic;
|
|
shexinfo.lpVerb = _T("open");
|
|
|
|
// since help center doesn't properly call AllowSetForegroundWindow when it defers
|
|
// to an existing process we just give it to the next taker.
|
|
AllowSetForegroundWindow(-1);
|
|
|
|
ShellExecuteEx(&shexinfo);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
// IsConfigInList - checks whether the pwzcConfig (WZC_WLAN_CONFIG object) is present
|
|
// in the list given as the first param
|
|
BOOL
|
|
CWZeroConfPage::IsConfigInList(CWZCConfig *pHdList, PWZC_WLAN_CONFIG pwzcConfig, CWZCConfig **ppMatchingConfig)
|
|
{
|
|
BOOL bYes = FALSE;
|
|
|
|
if (pHdList != NULL)
|
|
{
|
|
CWZCConfig *pConfig;
|
|
|
|
pConfig = pHdList;
|
|
do
|
|
{
|
|
if (pConfig->Match(pwzcConfig))
|
|
{
|
|
if (ppMatchingConfig != NULL)
|
|
*ppMatchingConfig = pConfig;
|
|
|
|
bYes = TRUE;
|
|
break;
|
|
}
|
|
pConfig = pConfig->m_pNext;
|
|
} while(pConfig != pHdList);
|
|
}
|
|
|
|
return bYes;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Adds the given configuration to the internal lists. The entries in the lists
|
|
// are ordered on InfrastructureMode in descending order. This way the Infrastructure
|
|
// entries will be on the top of the list while the adhoc entries will be on the
|
|
// bottom. (we rely on the order as it is given in NDIS_802_11_NETWORK_INFRASTRUCTURE)
|
|
DWORD
|
|
CWZeroConfPage::AddUniqueConfig(
|
|
DWORD dwOpFlags,
|
|
DWORD dwEntryFlags,
|
|
PWZC_WLAN_CONFIG pwzcConfig,
|
|
CEapolConfig *pEapolConfig,
|
|
CWZCConfig **ppNewNode)
|
|
{
|
|
LRESULT dwErr = ERROR_SUCCESS;
|
|
CWZCConfig *pHdList;
|
|
|
|
if (dwEntryFlags & WZC_DESCR_PREFRD)
|
|
{
|
|
pHdList = m_pHdPList;
|
|
}
|
|
else
|
|
{
|
|
UINT i;
|
|
pHdList = m_pHdVList;
|
|
|
|
// skip the null SSIDs from the visible list (coming from APs
|
|
// not responding to broadcast SSID).
|
|
for (i = pwzcConfig->Ssid.SsidLength; i > 0 && pwzcConfig->Ssid.Ssid[i-1] == 0; i--);
|
|
if (i == 0)
|
|
goto exit;
|
|
}
|
|
|
|
// if the list is currently empty, create the first entry as the head of the list
|
|
if (pHdList == NULL)
|
|
{
|
|
pHdList = new CWZCConfig(dwEntryFlags, pwzcConfig);
|
|
if (pHdList == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else if (pEapolConfig == NULL)
|
|
{
|
|
pHdList->m_pEapolConfig = new CEapolConfig;
|
|
if (pHdList->m_pEapolConfig == NULL)
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
else
|
|
dwErr = pHdList->m_pEapolConfig->LoadEapolConfig(m_IntfEntry.wszGuid, &(pHdList->m_wzcConfig.Ssid));
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
delete pHdList;
|
|
pHdList = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pHdList->m_pEapolConfig = pEapolConfig;
|
|
}
|
|
|
|
// if the caller wants, return the pointer to the newly created object
|
|
if (ppNewNode != NULL)
|
|
*ppNewNode = pHdList;
|
|
}
|
|
else
|
|
{
|
|
// else the list already contains at least one element
|
|
CWZCConfig *pCrt, *pHdGroup;
|
|
|
|
// scan the list (keep in mind it is ordered descendingly on IM)
|
|
pHdGroup = pCrt = pHdList;
|
|
do
|
|
{
|
|
// check whether we entered a new group of configs (different InfrastructureMode)
|
|
if (pHdGroup->m_wzcConfig.InfrastructureMode != pCrt->m_wzcConfig.InfrastructureMode)
|
|
pHdGroup = pCrt;
|
|
|
|
// if found an identical entry (same SSID and same InfraMode)
|
|
// signal the DUPLICATE_TAG error
|
|
if (pCrt->Match(pwzcConfig))
|
|
{
|
|
// merge the flags first
|
|
pCrt->m_dwFlags |= dwEntryFlags;
|
|
|
|
// If requested, copy over the new configuration.
|
|
// If not explicitly requested, copy over only if the existent configuration
|
|
// prooves to be weaker than the one being added.
|
|
//
|
|
// NOTE: the pCrt->m_pEapolConfig remains untouched since it depends exclusively
|
|
// on the SSID & Infrastructure mode. These are not changing hence there is no
|
|
// reason to reload the 802.1x settings.
|
|
if (dwOpFlags & WZCADD_OVERWRITE ||
|
|
(pHdList == m_pHdVList && pCrt->Weaker(pwzcConfig)))
|
|
{
|
|
memcpy(&(pCrt->m_wzcConfig), pwzcConfig, sizeof(WZC_WLAN_CONFIG));
|
|
// just in case a different pEapolConfig has been provided, destroy
|
|
// the original one (if any) and point to the new object
|
|
if (pEapolConfig != NULL)
|
|
{
|
|
if (pCrt->m_pEapolConfig != NULL)
|
|
delete pCrt->m_pEapolConfig;
|
|
pCrt->m_pEapolConfig = pEapolConfig;
|
|
}
|
|
}
|
|
|
|
// if the caller wants, return the pointer to the matching entry
|
|
if (ppNewNode != NULL)
|
|
*ppNewNode = pCrt;
|
|
|
|
// signal there is already a matching config
|
|
dwErr = ERROR_DUPLICATE_TAG;
|
|
}
|
|
pCrt = pCrt->m_pNext;
|
|
} while (dwErr == ERROR_SUCCESS &&
|
|
pCrt != pHdList &&
|
|
pwzcConfig->InfrastructureMode <= pCrt->m_wzcConfig.InfrastructureMode);
|
|
|
|
// if dwErr is unchanged, this means a new node has to be added ahead of pCrt node
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
// create the new config and insert it ahead of this node.
|
|
CWZCConfig *pNewConfig;
|
|
|
|
pNewConfig = new CWZCConfig(dwEntryFlags, pwzcConfig);
|
|
if (pNewConfig == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else if (pEapolConfig == NULL)
|
|
{
|
|
pNewConfig->m_pEapolConfig = new CEapolConfig;
|
|
if (pNewConfig->m_pEapolConfig == NULL)
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
else
|
|
dwErr = pNewConfig->m_pEapolConfig->LoadEapolConfig(m_IntfEntry.wszGuid, &(pNewConfig->m_wzcConfig.Ssid));
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
{
|
|
delete pNewConfig;
|
|
pNewConfig = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pNewConfig->m_pEapolConfig = pEapolConfig;
|
|
}
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
INT nDiff;
|
|
|
|
// if asked to insert in the head of the group, pCrt should point to this head
|
|
if (dwOpFlags & WZCADD_HIGROUP)
|
|
pCrt = pHdGroup;
|
|
|
|
pNewConfig->m_pPrev = pCrt->m_pPrev;
|
|
pNewConfig->m_pNext = pCrt;
|
|
pCrt->m_pPrev->m_pNext = pNewConfig;
|
|
pCrt->m_pPrev = pNewConfig;
|
|
|
|
// get the difference between the Infrastructure modes for the new node and
|
|
// for the current head
|
|
nDiff = pNewConfig->m_wzcConfig.InfrastructureMode - pHdList->m_wzcConfig.InfrastructureMode;
|
|
|
|
// if the newly entered entry has the largest "key" in
|
|
// the existent sequence, or it has to be inserted in the head of its group and it is
|
|
// in the first group, then the global list head moves to the new entry
|
|
if (nDiff > 0 || ((dwOpFlags & WZCADD_HIGROUP) && (nDiff == 0)))
|
|
pHdList = pNewConfig;
|
|
}
|
|
|
|
// if the caller wants, return the pointer to the newly created object
|
|
if (ppNewNode != NULL)
|
|
*ppNewNode = pNewConfig;
|
|
}
|
|
}
|
|
|
|
if (dwEntryFlags & WZC_DESCR_PREFRD)
|
|
{
|
|
m_pHdPList = pHdList;
|
|
}
|
|
else
|
|
{
|
|
m_pHdVList = pHdList;
|
|
}
|
|
exit:
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
// FillVisibleList - fills in the configs from the WZC_802_11_CONFIG_LIST object
|
|
// into the list of visible configs
|
|
DWORD
|
|
CWZeroConfPage::FillVisibleList(PWZC_802_11_CONFIG_LIST pwzcVList)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
UINT i;
|
|
|
|
// cleanup whatever we might already have in the visible list
|
|
if (m_pHdVList != NULL)
|
|
{
|
|
while (m_pHdVList->m_pNext != m_pHdVList)
|
|
{
|
|
delete m_pHdVList->m_pNext;
|
|
}
|
|
delete m_pHdVList;
|
|
m_pHdVList = NULL;
|
|
}
|
|
|
|
if (pwzcVList != NULL)
|
|
{
|
|
for (i = 0; i < pwzcVList->NumberOfItems; i++)
|
|
{
|
|
dwErr = AddUniqueConfig(
|
|
0, // no op flags
|
|
WZC_DESCR_VISIBLE, // this is a visible entry
|
|
&(pwzcVList->Config[i]));
|
|
|
|
// reset the error if config was just duplicated
|
|
if (dwErr == ERROR_DUPLICATE_TAG)
|
|
dwErr = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
// FillPreferredList - fills in the configs from the WZC_802_11_CONFIG_LIST object
|
|
// into the list of preferred configs
|
|
DWORD
|
|
CWZeroConfPage::FillPreferredList(PWZC_802_11_CONFIG_LIST pwzcPList)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
UINT i;
|
|
|
|
// cleanup whatever we might already have in the preferred list
|
|
if (m_pHdPList != NULL)
|
|
{
|
|
while (m_pHdPList ->m_pNext != m_pHdPList)
|
|
{
|
|
delete m_pHdPList ->m_pNext;
|
|
}
|
|
delete m_pHdPList;
|
|
m_pHdPList = NULL;
|
|
}
|
|
|
|
if (pwzcPList != NULL)
|
|
{
|
|
for (i = 0; i < pwzcPList->NumberOfItems; i++)
|
|
{
|
|
PWZC_WLAN_CONFIG pwzcPConfig = &(pwzcPList->Config[i]);
|
|
DWORD dwFlags = WZC_DESCR_PREFRD;
|
|
|
|
// check whether this preferred is also visible and adjust dwFlags if so
|
|
if (IsConfigInList(m_pHdVList, pwzcPConfig))
|
|
dwFlags |= WZC_DESCR_VISIBLE;
|
|
|
|
dwErr = AddUniqueConfig(
|
|
WZCADD_OVERWRITE, // preferred entries cause info to be overwritten
|
|
dwFlags,
|
|
pwzcPConfig);
|
|
|
|
// reset the error if config was just duplicated
|
|
if (dwErr == ERROR_DUPLICATE_TAG)
|
|
dwErr = ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Fill in the current configuration settings for this adapter
|
|
DWORD
|
|
CWZeroConfPage::FillCurrentConfig(PINTF_ENTRY pIntf)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WZC_WLAN_CONFIG wzcCurrent = {0};
|
|
CWZCConfig *pConfig = NULL;
|
|
|
|
wzcCurrent.InfrastructureMode = (NDIS_802_11_NETWORK_INFRASTRUCTURE)pIntf->nInfraMode;
|
|
wzcCurrent.Ssid.SsidLength = pIntf->rdSSID.dwDataLen;
|
|
CopyMemory(wzcCurrent.Ssid.Ssid, pIntf->rdSSID.pData, pIntf->rdSSID.dwDataLen);
|
|
// another bit of a hack. Code in the authentication mode for this adapter in the highest
|
|
// of the two reserved bits from WZC_WLAN_CONFIG
|
|
//NWB_SET_AUTHMODE(&wzcCurrent, pIntf->nAuthMode);
|
|
wzcCurrent.AuthenticationMode = (NDIS_802_11_AUTHENTICATION_MODE)pIntf->nAuthMode;
|
|
// set the privacy field based on the adapter's WEP status.
|
|
wzcCurrent.Privacy = (pIntf->nWepStatus == Ndis802_11WEPEnabled);
|
|
|
|
if (IsConfigInList(m_pHdVList, &wzcCurrent, &pConfig))
|
|
pConfig->m_dwFlags |= WZC_DESCR_ACTIVE;
|
|
|
|
if (IsConfigInList(m_pHdPList, &wzcCurrent, &pConfig))
|
|
pConfig->m_dwFlags |= WZC_DESCR_ACTIVE;
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Display the Visible & Preferred lists into their controls
|
|
DWORD
|
|
CWZeroConfPage::RefreshListView(DWORD dwFlags)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
CWZCConfig *pActive = NULL;
|
|
|
|
while (dwFlags != 0)
|
|
{
|
|
HWND hwndLV;
|
|
CWZCConfig *pHdList;
|
|
|
|
// the logic below allows iteration through all the lists
|
|
// requested by the caller
|
|
if (dwFlags & WZCOP_VLIST)
|
|
{
|
|
dwFlags ^= WZCOP_VLIST;
|
|
hwndLV = m_hwndVLV;
|
|
pHdList = m_pHdVList;
|
|
}
|
|
else if (dwFlags & WZCOP_PLIST)
|
|
{
|
|
dwFlags ^= WZCOP_PLIST;
|
|
hwndLV = m_hwndPLV;
|
|
pHdList = m_pHdPList;
|
|
}
|
|
else
|
|
break;
|
|
|
|
// clear first the list
|
|
ListView_DeleteAllItems(hwndLV);
|
|
|
|
if (pHdList != NULL)
|
|
{
|
|
CWZCConfig *pCrt;
|
|
UINT i;
|
|
|
|
pCrt = pHdList;
|
|
i = 0;
|
|
do
|
|
{
|
|
// add in the list all the entries if AutoMode or we're filling the
|
|
// visible list.
|
|
// Otherwise (!AutoMode & Preferred list) put in just the entries for
|
|
// the corresponding infrastructure mode
|
|
if ((m_dwCtlFlags & INTFCTL_CM_MASK) == Ndis802_11AutoUnknown ||
|
|
hwndLV == m_hwndVLV ||
|
|
(m_dwCtlFlags & INTFCTL_CM_MASK) == pCrt->m_wzcConfig.InfrastructureMode)
|
|
{
|
|
pCrt->m_nListIndex = i;
|
|
pCrt->AddConfigToListView(hwndLV, i++);
|
|
if (pCrt->m_dwFlags & WZC_DESCR_ACTIVE)
|
|
pActive = pCrt;
|
|
}
|
|
else
|
|
{
|
|
pCrt->m_nListIndex = -1;
|
|
}
|
|
pCrt = pCrt->m_pNext;
|
|
} while (pCrt != pHdList);
|
|
|
|
if (pActive != NULL)
|
|
{
|
|
ListView_SetItemState(hwndLV, pActive->m_nListIndex, LVIS_SELECTED, LVIS_SELECTED);
|
|
ListView_EnsureVisible(hwndLV, pActive->m_nListIndex, FALSE);
|
|
}
|
|
else if (i > 0)
|
|
{
|
|
ListView_SetItemState(hwndLV, 0, LVIS_SELECTED, LVIS_SELECTED);
|
|
ListView_EnsureVisible(hwndLV, 0, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
CWZeroConfPage::RefreshButtons()
|
|
{
|
|
CWZCConfig *pVConfig = NULL;
|
|
CWZCConfig *pPConfig = NULL;
|
|
LVITEM lvi = {0};
|
|
INT iSelected;
|
|
BOOL bEnabled;
|
|
|
|
// get the selected item from the visible list
|
|
iSelected = ListView_GetNextItem(m_hwndVLV, -1, LVNI_SELECTED);
|
|
if (iSelected >= 0)
|
|
{
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = iSelected;
|
|
if (ListView_GetItem(m_hwndVLV, &lvi))
|
|
{
|
|
pVConfig = (CWZCConfig*)lvi.lParam;
|
|
}
|
|
}
|
|
// get the selected item from the preferred list
|
|
iSelected = ListView_GetNextItem(m_hwndPLV, -1, LVNI_SELECTED);
|
|
if (iSelected >= 0)
|
|
{
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = iSelected;
|
|
if (ListView_GetItem(m_hwndPLV, &lvi))
|
|
{
|
|
pPConfig = (CWZCConfig*)lvi.lParam;
|
|
}
|
|
}
|
|
|
|
// enable buttons only if not during refresh - otherwise disable all
|
|
bEnabled = (m_dwOIDFlags & INTF_BSSIDLIST);
|
|
|
|
// "Refresh" button is enabled if we do have the visible list
|
|
// "Refresh" button might be enabled even if the service is disabled. User can see what is visible
|
|
::EnableWindow(m_hbtnRfsh, bEnabled);
|
|
|
|
bEnabled = bEnabled && (m_dwCtlFlags & INTFCTL_ENABLED);
|
|
|
|
// "Copy" button is enabled if there is any selection in the Visible list
|
|
::EnableWindow(m_hbtnCopy, bEnabled && (pVConfig != NULL) &&
|
|
((m_dwCtlFlags & INTFCTL_CM_MASK) == Ndis802_11AutoUnknown ||
|
|
(m_dwCtlFlags & INTFCTL_CM_MASK) == pVConfig->m_wzcConfig.InfrastructureMode));
|
|
|
|
// "Add" Button is always enabled, regardless the selections
|
|
::EnableWindow(m_hbtnAdd, bEnabled);
|
|
|
|
// "Remove" button is active only if there is any selection in the Preferred list
|
|
::EnableWindow(m_hbtnRem, bEnabled && (pPConfig != NULL));
|
|
|
|
// Same test for "properties" button as for "remove"
|
|
::EnableWindow(m_hbtnProps, bEnabled && (pPConfig != NULL));
|
|
|
|
// "Up" button is active only for preferred entries.
|
|
// It also is active only if the entry is not the first in the
|
|
// list and the entry preceding it has the same InfrastructureMode
|
|
bEnabled = bEnabled && (pPConfig != NULL);
|
|
bEnabled = bEnabled && (pPConfig != m_pHdPList);
|
|
bEnabled = bEnabled &&
|
|
(pPConfig->m_wzcConfig.InfrastructureMode == pPConfig->m_pPrev->m_wzcConfig.InfrastructureMode);
|
|
::EnableWindow(m_hbtnUp, bEnabled);
|
|
|
|
// "Down" button is active only for preferred or preferred entries.
|
|
// It also is active only if the entry is not the last in the list
|
|
// and it precedes another entry of exactly the same InfrastructureMode
|
|
bEnabled = (m_dwCtlFlags & INTFCTL_ENABLED) && (m_dwOIDFlags & INTF_BSSIDLIST);
|
|
bEnabled = bEnabled && (pPConfig != NULL);
|
|
bEnabled = bEnabled && (pPConfig->m_pNext != m_pHdPList);
|
|
bEnabled = bEnabled &&
|
|
(pPConfig->m_wzcConfig.InfrastructureMode == pPConfig->m_pNext->m_wzcConfig.InfrastructureMode);
|
|
::EnableWindow(m_hbtnDown, bEnabled);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
DWORD
|
|
CWZeroConfPage::SwapConfigsInListView(INT nIdx1, INT nIdx2, CWZCConfig * & pConfig1, CWZCConfig * & pConfig2)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
LVITEM lvi1 = {0};
|
|
LVITEM lvi2 = {0};
|
|
WCHAR wszSSID1[33];
|
|
WCHAR wszSSID2[33];
|
|
|
|
// since we take all what is known about an item this includes
|
|
// images indices and selection state
|
|
// get the first item
|
|
lvi1.iItem = nIdx1;
|
|
lvi1.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE | LVIF_PARAM;
|
|
lvi1.stateMask = (UINT)-1;
|
|
lvi1.pszText = wszSSID1;
|
|
lvi1.cchTextMax = sizeof(wszSSID1)/sizeof(WCHAR);
|
|
if (!ListView_GetItem(m_hwndPLV, &lvi1))
|
|
{
|
|
dwErr = ERROR_GEN_FAILURE;
|
|
goto exit;
|
|
}
|
|
pConfig1 = (CWZCConfig*)lvi1.lParam;
|
|
|
|
// get the second item
|
|
lvi2.iItem = nIdx2;
|
|
lvi2.mask = LVIF_TEXT | LVIF_STATE | LVIF_IMAGE | LVIF_PARAM;
|
|
lvi2.stateMask = (UINT)-1;
|
|
lvi2.pszText = wszSSID2;
|
|
lvi2.cchTextMax = sizeof(wszSSID2)/sizeof(WCHAR);
|
|
if (!ListView_GetItem(m_hwndPLV, &lvi2))
|
|
{
|
|
dwErr = ERROR_GEN_FAILURE;
|
|
goto exit;
|
|
}
|
|
pConfig2 = (CWZCConfig*)lvi2.lParam;
|
|
|
|
// swap the indices and reset the items at their new positions
|
|
lvi1.iItem = nIdx2;
|
|
lvi2.iItem = nIdx1;
|
|
if (!ListView_SetItem(m_hwndPLV, &lvi1) ||
|
|
!ListView_SetItem(m_hwndPLV, &lvi2))
|
|
{
|
|
dwErr = ERROR_GEN_FAILURE;
|
|
goto exit;
|
|
}
|
|
// if everything went fine, swap the indices in the objects
|
|
pConfig1->m_nListIndex = nIdx2;
|
|
pConfig2->m_nListIndex = nIdx1;
|
|
// make visible the selected entry
|
|
ListView_EnsureVisible(m_hwndPLV, nIdx1, FALSE);
|
|
|
|
exit:
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
DWORD
|
|
CWZeroConfPage::SavePreferredConfigs(PINTF_ENTRY pIntf)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
CWZCConfig *pCrt = NULL;
|
|
UINT nPrefrd = 0;
|
|
|
|
if (m_pHdPList != NULL)
|
|
{
|
|
// count first the number of preferred entries in the list
|
|
pCrt = m_pHdPList;
|
|
do
|
|
{
|
|
nPrefrd++;
|
|
pCrt = pCrt->m_pNext;
|
|
} while(pCrt != m_pHdPList);
|
|
}
|
|
|
|
if (nPrefrd > 0)
|
|
{
|
|
PWZC_802_11_CONFIG_LIST pwzcPrefrdList;
|
|
UINT nwzcPrefrdSize;
|
|
|
|
nwzcPrefrdSize = sizeof(WZC_802_11_CONFIG_LIST)+ (nPrefrd-1)*sizeof(WZC_WLAN_CONFIG);
|
|
|
|
// allocate as much memory as needed for storing all the preferred SSIDs
|
|
pwzcPrefrdList = (PWZC_802_11_CONFIG_LIST)RpcCAlloc(nwzcPrefrdSize);
|
|
if (pwzcPrefrdList == NULL)
|
|
{
|
|
dwErr = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
DWORD dwLErr;
|
|
|
|
pwzcPrefrdList->NumberOfItems = 0;
|
|
// we have now all we need - start copying the preferred
|
|
pCrt = m_pHdPList;
|
|
do
|
|
{
|
|
PWZC_WLAN_CONFIG pPrefrdConfig;
|
|
|
|
pPrefrdConfig = &(pwzcPrefrdList->Config[pwzcPrefrdList->NumberOfItems++]);
|
|
CopyMemory(pPrefrdConfig, &pCrt->m_wzcConfig, sizeof(WZC_WLAN_CONFIG));
|
|
|
|
// fix 802.1X state for infrastructure networks only.
|
|
// don't touch the 802.1X state for ad hoc networks since this might mess the setting for a
|
|
// corresponding Infrastructure network (802.1X engine doesn't make the difference between SSID infra
|
|
// and SSID ad hoc) and besides, the 802.1X engine is smart enough to not act on ad hoc networks
|
|
if (pCrt->m_pEapolConfig != NULL &&
|
|
pPrefrdConfig->InfrastructureMode == Ndis802_11Infrastructure)
|
|
{
|
|
dwLErr = pCrt->m_pEapolConfig->SaveEapolConfig(m_IntfEntry.wszGuid, &(pCrt->m_wzcConfig.Ssid));
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
dwErr = dwLErr;
|
|
}
|
|
|
|
pCrt = pCrt->m_pNext;
|
|
} while(pwzcPrefrdList->NumberOfItems < nPrefrd && pCrt != m_pHdPList);
|
|
|
|
// since we don't want any "one time configuration" logic to apply here,
|
|
// we need to put in the whole number of items in the "Index" field
|
|
pwzcPrefrdList->Index = pwzcPrefrdList->NumberOfItems;
|
|
|
|
pIntf->rdStSSIDList.dwDataLen = nwzcPrefrdSize;
|
|
pIntf->rdStSSIDList.pData = (LPBYTE)pwzcPrefrdList;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pIntf->rdStSSIDList.dwDataLen = 0;
|
|
pIntf->rdStSSIDList.pData = NULL;
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT CWZeroConfPage::OnInitDialog(
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
BOOL& bHandled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bEnableAll;
|
|
BOOL bEnableVisible;
|
|
|
|
// get the controls as the first thing to do
|
|
m_hckbEnable = GetDlgItem(IDC_WZC_CHK_EnableWZC);
|
|
m_hlblVisNet = GetDlgItem(IDC_WZC_LBL_VisNet);
|
|
m_hlblPrefNet = GetDlgItem(IDC_WZC_LBL_PrefNet);
|
|
m_hlblAvail = GetDlgItem(IDC_AVAILLABEL);
|
|
m_hlblPrefDesc = GetDlgItem(IDC_PREFERLABEL);
|
|
m_hlblAdvDesc = GetDlgItem(IDC_ADVANCEDLABEL);
|
|
m_hwndVLV = GetDlgItem(IDC_WZC_LVW_BSSIDList);
|
|
m_hwndPLV = GetDlgItem(IDC_WZC_LVW_StSSIDList);
|
|
m_hbtnUp = GetDlgItem(IDC_WZC_BTN_UP);
|
|
m_hbtnDown = GetDlgItem(IDC_WZC_BTN_DOWN);
|
|
m_hbtnCopy = GetDlgItem(IDC_WZC_BTN_COPY);
|
|
m_hbtnRfsh = GetDlgItem(IDC_WZC_BTN_RFSH);
|
|
m_hbtnAdd = GetDlgItem(IDC_WZC_BTN_ADD);
|
|
m_hbtnRem = GetDlgItem(IDC_WZC_BTN_REM);
|
|
m_hbtnAdvanced = GetDlgItem(IDC_ADVANCED);
|
|
m_hbtnProps = GetDlgItem(IDC_PROPERTIES);
|
|
|
|
// Initialize the list view controls
|
|
InitListViews();
|
|
|
|
// enable UI only for Admins and if the interface is wireless
|
|
// As a side effect, IsWireless() loads the data from the WZC
|
|
bEnableAll = /*FIsUserAdmin() &&*/ IsWireless();
|
|
bEnableVisible = bEnableAll;
|
|
|
|
if (bEnableAll)
|
|
{
|
|
// set the configuration mode to the one for this interface
|
|
m_dwCtlFlags = m_IntfEntry.dwCtlFlags;
|
|
|
|
// if service disabled, gray out everything
|
|
bEnableAll = (m_dwCtlFlags & INTFCTL_ENABLED);
|
|
|
|
// set the control check boxes
|
|
CheckDlgButton(IDC_WZC_CHK_EnableWZC,
|
|
(m_dwCtlFlags & INTFCTL_ENABLED) ? BST_CHECKED : BST_UNCHECKED);
|
|
|
|
// the UI can be filled in only when we were able to retrieve the list of
|
|
// visible configs (even if it is NULL/empty). Otherwise, the UI is locked.
|
|
if (m_dwOIDFlags & INTF_BSSIDLIST)
|
|
{
|
|
// add the list of visible configs for this adapter
|
|
FillVisibleList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdBSSIDList.pData);
|
|
// add the list of preferred configs for this adapter
|
|
FillPreferredList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdStSSIDList.pData);
|
|
// add to the visible list the current settings
|
|
FillCurrentConfig(&m_IntfEntry);
|
|
// dump the resulting lists in their List Views
|
|
RefreshListView(WZCOP_VLIST|WZCOP_PLIST);
|
|
// if we got a visible list, have to enable it here
|
|
bEnableVisible = TRUE;
|
|
|
|
}
|
|
else
|
|
{
|
|
// mark that we don't have WZC data yet
|
|
m_bHaveWZCData = FALSE;
|
|
// the list of preferred configs still needs to be filled up here
|
|
FillPreferredList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdStSSIDList.pData);
|
|
// switch the cursor to "App starting"
|
|
m_hCursor = SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
|
|
// we should fill in the UI after Tr (see the WZC state machine)
|
|
// Tr is 3secs (defined in ..zeroconf\server\state.h)
|
|
m_nTimer = SetTimer(g_TimerID, RFSH_TIMEOUT, 0);
|
|
// don't enable any control if refreshing
|
|
bEnableAll = FALSE;
|
|
// actually disable even the "Enable" button
|
|
::EnableWindow(m_hckbEnable, FALSE);
|
|
// and also disable the visible list
|
|
bEnableVisible = FALSE;
|
|
}
|
|
// refresh the buttons
|
|
RefreshButtons();
|
|
}
|
|
|
|
// the controls related to the visible list should be enabled if:
|
|
// - WZC can operate on this adapter
|
|
// - we got a BSSIDLIST from the very first shot.
|
|
// otherwise these controls should remain disabled
|
|
::EnableWindow(m_hlblVisNet, bEnableVisible);
|
|
::EnableWindow(m_hwndVLV, bEnableVisible);
|
|
::EnableWindow(m_hlblAvail, bEnableVisible);
|
|
|
|
// all the remaining controls should be enabled only if:
|
|
// - WZC can operate on the adapter
|
|
// - WZC is enabled as a service
|
|
// - we got the BSSIDLIST from the very first shot
|
|
// otherwise these controls should remain disabled
|
|
::EnableWindow(m_hlblPrefNet, bEnableAll);
|
|
::EnableWindow(m_hwndPLV, bEnableAll);
|
|
::EnableWindow(m_hlblPrefDesc, bEnableAll);
|
|
|
|
::EnableWindow(m_hlblAdvDesc, bEnableAll);
|
|
::EnableWindow(m_hbtnAdvanced, bEnableAll);
|
|
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT CWZeroConfPage::OnApply(
|
|
int idCtrl,
|
|
LPNMHDR pnmh,
|
|
BOOL& bHandled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR wszGuid[c_cchGuidWithTerm];
|
|
NETCON_PROPERTIES *pProps = NULL;
|
|
DWORD rpcStatus = ERROR_SUCCESS;
|
|
BOOL bOk;
|
|
|
|
hr = m_pconn->GetProperties(&pProps);
|
|
bOk = SUCCEEDED(hr);
|
|
|
|
if (bOk)
|
|
{
|
|
UINT cch;
|
|
cch = ::StringFromGUID2(
|
|
pProps->guidId,
|
|
wszGuid,
|
|
c_cchGuidWithTerm);
|
|
FreeNetconProperties(pProps);
|
|
bOk = (cch != 0);
|
|
}
|
|
|
|
if (bOk)
|
|
{
|
|
UINT nText;
|
|
INTF_ENTRY Intf;
|
|
BOOL bDirty;
|
|
DWORD dwOneXErr;
|
|
|
|
ZeroMemory(&Intf, sizeof(INTF_ENTRY));
|
|
Intf.wszGuid = wszGuid;
|
|
|
|
// copy the configuration mode
|
|
Intf.dwCtlFlags = m_dwCtlFlags;
|
|
// save the preferred config list
|
|
dwOneXErr = SavePreferredConfigs(&Intf);
|
|
|
|
bDirty = (Intf.dwCtlFlags != m_IntfEntry.dwCtlFlags);
|
|
bDirty = bDirty || (Intf.rdStSSIDList.dwDataLen != m_IntfEntry.rdStSSIDList.dwDataLen);
|
|
bDirty = bDirty || ((Intf.rdStSSIDList.dwDataLen != 0) &&
|
|
memcmp(Intf.rdStSSIDList.pData, m_IntfEntry.rdStSSIDList.pData, Intf.rdStSSIDList.dwDataLen));
|
|
|
|
if (bDirty)
|
|
{
|
|
rpcStatus = WZCSetInterface(
|
|
NULL,
|
|
INTF_ALL_FLAGS | INTF_PREFLIST,
|
|
&Intf,
|
|
NULL);
|
|
}
|
|
|
|
if (dwOneXErr != ERROR_SUCCESS || rpcStatus == ERROR_PARTIAL_COPY)
|
|
{
|
|
NcMsgBox(
|
|
WZCGetSPResModule(),
|
|
m_hWnd,
|
|
IDS_LANUI_ERROR_CAPTION,
|
|
IDS_WZC_PARTIAL_APPLY,
|
|
MB_ICONEXCLAMATION|MB_OK);
|
|
|
|
rpcStatus = RPC_S_OK;
|
|
}
|
|
|
|
bOk = (rpcStatus == RPC_S_OK);
|
|
|
|
// wszGuid field is not pointing to heap memory hence it should not
|
|
// be deleted -> set the pointer to NULL to avoid this to happen
|
|
Intf.wszGuid = NULL;
|
|
WZCDeleteIntfObj(&Intf);
|
|
}
|
|
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
extern const WCHAR c_szNetCfgHelpFile[];
|
|
LRESULT
|
|
CWZeroConfPage::OnContextMenu(
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
BOOL& fHandled)
|
|
{
|
|
if (m_adwHelpIDs != NULL)
|
|
{
|
|
::WinHelp(m_hWnd,
|
|
c_szNetCfgHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(ULONG_PTR)m_adwHelpIDs);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
LRESULT
|
|
CWZeroConfPage::OnHelp(
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
BOOL& fHandled)
|
|
{
|
|
LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
|
|
|
|
if ((m_adwHelpIDs != NULL) && (HELPINFO_WINDOW == lphi->iContextType))
|
|
{
|
|
::WinHelp(static_cast<HWND>(lphi->hItemHandle),
|
|
c_szNetCfgHelpFile,
|
|
HELP_WM_HELP,
|
|
(ULONG_PTR)m_adwHelpIDs);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT
|
|
CWZeroConfPage::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
|
|
{
|
|
if (m_nTimer != 0)
|
|
{
|
|
BOOL bEnableAll;
|
|
|
|
// switch the cursor back to whatever it was
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
KillTimer(m_nTimer);
|
|
m_nTimer = 0;
|
|
|
|
// attempt to requery the service for all the OIDs. Regardless we could or not
|
|
// obtain the OIDs, fill the UI with what we have.
|
|
if (GetOIDs(INTF_ALL_OIDS, &m_dwOIDFlags) == ERROR_SUCCESS)
|
|
{
|
|
CWZCConfig *pPConfig = NULL;
|
|
|
|
// add the list of visible configs for this adapter
|
|
FillVisibleList((PWZC_802_11_CONFIG_LIST)m_IntfEntry.rdBSSIDList.pData);
|
|
// Update the visibility flag for each of the preferred configs
|
|
pPConfig = m_pHdPList;
|
|
if (pPConfig != NULL)
|
|
{
|
|
do
|
|
{
|
|
// by default, none of the preferred entries is marked as "active".
|
|
// This will be taken care of later, when calling FillCurrentConfig().
|
|
pPConfig->m_dwFlags &= ~WZC_DESCR_ACTIVE;
|
|
if (IsConfigInList(m_pHdVList, &pPConfig->m_wzcConfig))
|
|
pPConfig->m_dwFlags |= WZC_DESCR_VISIBLE;
|
|
else
|
|
pPConfig->m_dwFlags &= ~WZC_DESCR_VISIBLE;
|
|
pPConfig = pPConfig->m_pNext;
|
|
} while(pPConfig != m_pHdPList);
|
|
}
|
|
// add the current settings to the visible list
|
|
FillCurrentConfig(&m_IntfEntry);
|
|
}
|
|
|
|
// even in case of failure, at this point we should live with whatever
|
|
// visible list (if any) we have. Hence, flag BSSIDLIST as "visible"
|
|
m_dwOIDFlags |= INTF_BSSIDLIST;
|
|
|
|
// dump the resulting lists in their List Views
|
|
RefreshListView(WZCOP_VLIST|WZCOP_PLIST);
|
|
// refresh the buttons
|
|
RefreshButtons();
|
|
|
|
// if service disabled, gray out all the other controls
|
|
bEnableAll = (m_dwCtlFlags & INTFCTL_ENABLED);
|
|
|
|
// enable all the UI when done refreshing
|
|
::EnableWindow(m_hckbEnable, TRUE);
|
|
|
|
// enable everything related to the visible list
|
|
::EnableWindow(m_hlblVisNet, TRUE);
|
|
::EnableWindow(m_hwndVLV, TRUE);
|
|
::EnableWindow(m_hlblAvail, TRUE);
|
|
|
|
::EnableWindow(m_hlblPrefNet, bEnableAll);
|
|
::EnableWindow(m_hwndPLV, bEnableAll);
|
|
::EnableWindow(m_hlblPrefDesc, bEnableAll);
|
|
|
|
::EnableWindow(m_hlblAdvDesc, bEnableAll);
|
|
::EnableWindow(m_hbtnAdvanced, bEnableAll);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT CWZeroConfPage::OnDblClick(
|
|
int idCtrl,
|
|
LPNMHDR pnmh,
|
|
BOOL& bHandled)
|
|
{
|
|
HWND hwndLV;
|
|
HRESULT hr = S_OK;
|
|
LPNMLISTVIEW pnmhLv = (LPNMLISTVIEW) pnmh;
|
|
|
|
if (idCtrl == IDC_WZC_LVW_BSSIDList)
|
|
{
|
|
hwndLV = m_hwndVLV;
|
|
}
|
|
else
|
|
{
|
|
hwndLV = m_hwndPLV;
|
|
}
|
|
|
|
bHandled = FALSE;
|
|
if (pnmhLv->iItem != -1)
|
|
{
|
|
ListView_SetItemState(hwndLV, pnmhLv->iItem, LVIS_SELECTED, LVIS_SELECTED);
|
|
hr = _DoProperties(hwndLV, pnmhLv->iItem);
|
|
bHandled = TRUE;
|
|
}
|
|
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT CWZeroConfPage::OnClick(
|
|
int idCtrl,
|
|
LPNMHDR pnmh,
|
|
BOOL& bHandled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPNMLISTVIEW pnmhLv = (LPNMLISTVIEW) pnmh;
|
|
|
|
if (idCtrl == IDC_LEARNABOUT)
|
|
{
|
|
HelpCenter(SzLoadString(_Module.GetResourceInstance(), IDS_WZC_LEARNCMD));
|
|
}
|
|
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT CWZeroConfPage::OnReturn(
|
|
int idCtrl,
|
|
LPNMHDR pnmh,
|
|
BOOL& bHandled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPNMLISTVIEW pnmhLv = (LPNMLISTVIEW) pnmh;
|
|
|
|
if (idCtrl == IDC_LEARNABOUT)
|
|
{
|
|
HelpCenter(SzLoadString(_Module.GetResourceInstance(), IDS_WZC_LEARNCMD));
|
|
}
|
|
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT CWZeroConfPage::OnItemChanged(
|
|
int idCtrl,
|
|
LPNMHDR pnmh,
|
|
BOOL& bHandled)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
RefreshButtons();
|
|
bHandled = TRUE;
|
|
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT CWZeroConfPage::OnChkWZCEnable(
|
|
WORD wNotifyCode,
|
|
WORD wID,
|
|
HWND hWndCtl,
|
|
BOOL& bHandled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL bEnable;
|
|
|
|
bEnable = (IsDlgButtonChecked(IDC_WZC_CHK_EnableWZC) == BST_CHECKED);
|
|
m_dwCtlFlags &= ~INTFCTL_ENABLED;
|
|
if (bEnable)
|
|
m_dwCtlFlags |= INTFCTL_ENABLED;
|
|
|
|
// enable everything related to the visible list
|
|
::EnableWindow(m_hlblVisNet, TRUE);
|
|
::EnableWindow(m_hwndVLV, TRUE);
|
|
::EnableWindow(m_hlblAvail, TRUE);
|
|
|
|
::EnableWindow(m_hlblPrefNet, bEnable);
|
|
::EnableWindow(m_hwndPLV, bEnable);
|
|
::EnableWindow(m_hlblPrefDesc, bEnable);
|
|
|
|
::EnableWindow(m_hlblAdvDesc, bEnable);
|
|
::EnableWindow(m_hbtnAdvanced, bEnable);
|
|
|
|
RefreshButtons();
|
|
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT
|
|
CWZeroConfPage::OnPushAddOrCopy(
|
|
WORD wNotifyCode,
|
|
WORD wID,
|
|
HWND hWndCtl,
|
|
BOOL& bHandled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LVITEM lvi = {0};
|
|
BOOL bOk;
|
|
INT iSelected;
|
|
CWZCConfig *pConfig = NULL;
|
|
CWZCConfigPage PpWzcProps(WZCDLG_PROPS_RWALL|WZCDLG_PROPS_DEFOK|WZCDLG_PROPS_ONEX_CHECK);
|
|
CEapolConfig *pEapolConfig = NULL;
|
|
|
|
// in case of success, the object allocated here is linked to the
|
|
// newly created or updated CWZCConfig and will be deleted when
|
|
// this latter one gets destroyed.
|
|
pEapolConfig = new CEapolConfig;
|
|
bOk = (pEapolConfig != NULL);
|
|
|
|
if (bOk)
|
|
{
|
|
if (hWndCtl == m_hbtnCopy)
|
|
{
|
|
// get the selected item from the Visible list
|
|
iSelected = ListView_GetNextItem(m_hwndVLV, -1, LVNI_SELECTED);
|
|
bOk = (iSelected != -1);
|
|
|
|
// there is a valid selection to copy (it couldn't be otherwise since
|
|
// "Copy" shouldn't be enabled if there is no such selection)
|
|
// Find the CWZCConfig for the selection
|
|
if (bOk)
|
|
{
|
|
LVITEM lvi = {0};
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = iSelected;
|
|
if (ListView_GetItem(m_hwndVLV, &lvi))
|
|
{
|
|
pConfig = (CWZCConfig*)lvi.lParam;
|
|
if (pConfig != NULL)
|
|
{
|
|
UINT nVisPrivacy = pConfig->m_wzcConfig.Privacy;
|
|
// check whether this config is in the preferred list. If IsConfigInList
|
|
// succeeds, it returns in pConfig the pointer to the preferred config - this is
|
|
// what we need to show the properties for.
|
|
// If this network is not in the preferred list, pConfig will not be modified hence
|
|
// the properties coming from the AP will be loaded. Again what we want.
|
|
IsConfigInList(m_pHdPList, &pConfig->m_wzcConfig, &pConfig);
|
|
// copy in the newly created 802.1x object what we have for this configuration
|
|
pEapolConfig->CopyEapolConfig(pConfig->m_pEapolConfig);
|
|
// upload the 802.11 settings into the property page
|
|
PpWzcProps.UploadWzcConfig(pConfig);
|
|
// However, even if we're showing up preferred, settings, the Privacy bit from the AP
|
|
// (the visible configuration) takes precedence.
|
|
if (nVisPrivacy)
|
|
{
|
|
PpWzcProps.m_wzcConfig.Privacy = nVisPrivacy;
|
|
}
|
|
}
|
|
}
|
|
bOk = (pConfig != NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// this is a brand new network, we don't know even the SSID,
|
|
// let 802.1x start with its defaults then.
|
|
pEapolConfig->LoadEapolConfig(m_IntfEntry.wszGuid, NULL);
|
|
bOk = TRUE;
|
|
}
|
|
}
|
|
|
|
// we have the CWZCConfig object, prompt the user with it allowing
|
|
// him to change whatever params he want
|
|
if (bOk)
|
|
{
|
|
CWLANAuthenticationPage PpAuthProps(NULL, m_pnc, m_pconn, g_aHelpIDs_IDD_SECURITY);
|
|
|
|
// if the mode is not "auto", freeze it in the dialog
|
|
if ((m_dwCtlFlags & INTFCTL_CM_MASK) != Ndis802_11AutoUnknown)
|
|
{
|
|
PpWzcProps.m_wzcConfig.InfrastructureMode = (NDIS_802_11_NETWORK_INFRASTRUCTURE)(m_dwCtlFlags & INTFCTL_CM_MASK);
|
|
PpWzcProps.SetFlags(WZCDLG_PROPS_RWINFR, 0);
|
|
}
|
|
|
|
PpAuthProps.UploadEapolConfig(pEapolConfig, &PpWzcProps);
|
|
PpWzcProps.UploadEapolConfig(pEapolConfig);
|
|
bOk = (_DoModalPropSheet(&PpWzcProps, &PpAuthProps) > 0);
|
|
}
|
|
|
|
// the dialog was ack-ed, the dialog contains the WZC_WLAN_CONFIG to be added
|
|
// go ahead and create the list entry for it.
|
|
if (bOk)
|
|
{
|
|
DWORD dwFlags = WZC_DESCR_PREFRD;
|
|
DWORD dwErr;
|
|
|
|
// it could happen that the newly added config is visible
|
|
if (IsConfigInList(m_pHdVList, &PpWzcProps.m_wzcConfig))
|
|
dwFlags |= WZC_DESCR_VISIBLE;
|
|
|
|
// we have now a WZC_WLAN_CONFIG structure in the dialog
|
|
// we have to add it to the list view and to the internal list as
|
|
// a preferred one. This call doesn't fix the list index
|
|
// and doesn't insert the new config in the ListView.
|
|
|
|
dwErr = AddUniqueConfig(
|
|
WZCADD_OVERWRITE | WZCADD_HIGROUP,
|
|
dwFlags,
|
|
&PpWzcProps.m_wzcConfig,
|
|
pEapolConfig, // 802.1x settings need to be updated no matter what
|
|
&pConfig);
|
|
|
|
// if the addition returns success, it means this is a brand new
|
|
// entry! Then fix the indices and add the entry to the list view
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
CWZCConfig *pCrt = pConfig;
|
|
INT nCrtIdx = 0;
|
|
|
|
// if everything went up fine, we need to fix the indices and
|
|
// create/add the list view item
|
|
// find the first index above the newly entry item.
|
|
// pConfig already has the m_nListIndex set to -1;
|
|
if (pConfig == m_pHdPList)
|
|
{
|
|
nCrtIdx = 0;
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
pCrt = pCrt->m_pPrev;
|
|
if (pCrt->m_nListIndex != -1)
|
|
{
|
|
nCrtIdx = pCrt->m_nListIndex+1;
|
|
break;
|
|
}
|
|
} while(pCrt != m_pHdPList);
|
|
}
|
|
|
|
pConfig->m_nListIndex = nCrtIdx++;
|
|
pCrt = pConfig->m_pNext;
|
|
|
|
while(pCrt != m_pHdPList)
|
|
{
|
|
if (pCrt->m_nListIndex != -1)
|
|
pCrt->m_nListIndex = nCrtIdx++;
|
|
pCrt = pCrt->m_pNext;
|
|
}
|
|
|
|
pConfig->AddConfigToListView(m_hwndPLV, pConfig->m_nListIndex);
|
|
}
|
|
|
|
bOk = (dwErr == ERROR_SUCCESS) || (dwErr == ERROR_DUPLICATE_TAG);
|
|
}
|
|
|
|
if (bOk)
|
|
{
|
|
ListView_SetItemState(m_hwndPLV, pConfig->m_nListIndex, LVIS_SELECTED, LVIS_SELECTED);
|
|
ListView_EnsureVisible(m_hwndPLV, pConfig->m_nListIndex, FALSE);
|
|
RefreshButtons();
|
|
}
|
|
|
|
if (!bOk && pEapolConfig != NULL)
|
|
delete pEapolConfig;
|
|
|
|
bHandled = bOk;
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT
|
|
CWZeroConfPage::OnPushRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD rpcStatus;
|
|
DWORD dwOutFlags;
|
|
|
|
// since we are here, it means we have already got the info for this adapter, hence
|
|
// we already have its GUID in the m_IntfEntry member.
|
|
// All we have to do is to ask WZCSVC for a visible list rescan
|
|
|
|
rpcStatus = WZCRefreshInterface(
|
|
NULL,
|
|
INTF_LIST_SCAN,
|
|
&m_IntfEntry,
|
|
&dwOutFlags);
|
|
|
|
// if everything went fine, just disable the "Refresh" button and set
|
|
// the timer for the future query
|
|
if (rpcStatus == RPC_S_OK &&
|
|
dwOutFlags & INTF_LIST_SCAN)
|
|
{
|
|
::EnableWindow(m_hbtnRfsh, FALSE);
|
|
// mark that we don't have WZC data yet
|
|
m_bHaveWZCData = FALSE;
|
|
// switch the cursor to the "app starting"
|
|
m_hCursor = SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
|
|
m_nTimer = SetTimer(g_TimerID, RFSH_TIMEOUT, 0);
|
|
// indicate we don't have the visible list in order
|
|
// to disable all the buttons
|
|
m_dwOIDFlags &= ~INTF_BSSIDLIST;
|
|
RefreshButtons();
|
|
// disable all the UI while refreshing
|
|
::EnableWindow(m_hckbEnable, FALSE);
|
|
::EnableWindow(m_hwndVLV, FALSE);
|
|
::EnableWindow(m_hwndPLV, FALSE);
|
|
::EnableWindow(m_hlblVisNet, FALSE);
|
|
::EnableWindow(m_hlblPrefNet, FALSE);
|
|
::EnableWindow(m_hlblAvail, FALSE);
|
|
::EnableWindow(m_hlblPrefDesc, FALSE);
|
|
::EnableWindow(m_hlblAdvDesc, FALSE);
|
|
::EnableWindow(m_hbtnAdvanced, FALSE);
|
|
}
|
|
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT
|
|
CWZeroConfPage::OnPushUpOrDown(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
INT iSelected;
|
|
INT iOther;
|
|
CWZCConfig *pConfig, *pOther;
|
|
|
|
// no matter what, get the selected item from the list
|
|
iSelected = ListView_GetNextItem(m_hwndPLV, -1, LVNI_SELECTED);
|
|
|
|
// since we are here it means there is another entry up/down side
|
|
// with which the selected one needs to change place
|
|
// first delete the entry from its current position in the list
|
|
iOther = (hWndCtl == m_hbtnDown)? iSelected+1 : iSelected-1;
|
|
// swap first the visual elements (entries in the List View)
|
|
// This returns the CWZCConfig pointers with their indices already
|
|
// adjusted
|
|
if (SwapConfigsInListView(iSelected, iOther, pConfig, pOther) == ERROR_SUCCESS)
|
|
{
|
|
// if need to go down one hop..
|
|
if (hWndCtl == m_hbtnDown)
|
|
{
|
|
// swap positions in the list
|
|
// remove the entry from its current position
|
|
pOther->m_pPrev = pConfig->m_pPrev;
|
|
pConfig->m_pPrev->m_pNext = pOther;
|
|
// and put it back down to its successor
|
|
pConfig->m_pPrev = pOther;
|
|
pConfig->m_pNext = pOther->m_pNext;
|
|
pOther->m_pNext->m_pPrev = pConfig;
|
|
pOther->m_pNext = pConfig;
|
|
// fix the m_pHdPList if needed;
|
|
if (m_pHdPList == pConfig)
|
|
m_pHdPList = pOther;
|
|
}
|
|
// if need to go up one hop..
|
|
else
|
|
{
|
|
// swap positions in the list
|
|
// remove the entry from its current position
|
|
pOther->m_pNext = pConfig->m_pNext;
|
|
pConfig->m_pNext->m_pPrev = pOther;
|
|
// and put it back in front of its predecessor
|
|
pConfig->m_pNext = pOther;
|
|
pConfig->m_pPrev = pOther->m_pPrev;
|
|
pOther->m_pPrev->m_pNext = pConfig;
|
|
pOther->m_pPrev = pConfig;
|
|
// fix the m_pHdPList if needed
|
|
if (m_pHdPList == pOther)
|
|
m_pHdPList = pConfig;
|
|
}
|
|
}
|
|
|
|
// need to refresh the buttons such that the "Up"/"Down" buttons
|
|
// get updated for the new position of the selection
|
|
RefreshButtons();
|
|
bHandled = TRUE;
|
|
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------
|
|
LRESULT CWZeroConfPage::OnPushRemove(
|
|
WORD wNotifyCode,
|
|
WORD wID,
|
|
HWND hWndCtl,
|
|
BOOL& bHandled)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LVITEM lvi = {0};
|
|
CWZCConfig *pConfig, *pCrt;
|
|
INT iSelected;
|
|
|
|
iSelected = ListView_GetNextItem(m_hwndPLV, -1, LVNI_SELECTED);
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = iSelected;
|
|
if (!ListView_GetItem(m_hwndPLV, &lvi))
|
|
goto exit;
|
|
// get the CWZCConfig from it
|
|
pConfig = (CWZCConfig*)lvi.lParam;
|
|
|
|
// adjust the list indices for all the entries that follow
|
|
// the selected one
|
|
for (pCrt = pConfig->m_pNext; pCrt != m_pHdPList; pCrt = pCrt->m_pNext)
|
|
{
|
|
if (pCrt->m_nListIndex != -1)
|
|
pCrt->m_nListIndex--;
|
|
}
|
|
// determine first which entry gets the selection
|
|
// the selection moves down if there is any other entry down, or up otherwise
|
|
pCrt = (pConfig->m_pNext == m_pHdPList) ? pConfig->m_pPrev : pConfig->m_pNext;
|
|
|
|
// if after that the selection still points to the same object, it means
|
|
// it is the only one in the list so the head and selection are set to NULL
|
|
if (pCrt == pConfig)
|
|
{
|
|
m_pHdPList = pCrt = NULL;
|
|
}
|
|
// otherwise, if it is the head of the list which gets removed, the head
|
|
// moves down to the next entry
|
|
else if (m_pHdPList == pConfig)
|
|
{
|
|
m_pHdPList = pConfig->m_pNext;
|
|
}
|
|
|
|
// delete now the selected entry from the list
|
|
ListView_DeleteItem(m_hwndPLV, iSelected);
|
|
// and destroy its object (desctructor takes care of list removal)
|
|
delete pConfig;
|
|
|
|
// set the new selection if any
|
|
if (pCrt != NULL)
|
|
{
|
|
ListView_SetItemState(m_hwndPLV, pCrt->m_nListIndex, LVIS_SELECTED, LVIS_SELECTED);
|
|
ListView_EnsureVisible(m_hwndPLV, pCrt->m_nListIndex, FALSE);
|
|
}
|
|
// refresh the buttons' state
|
|
RefreshButtons();
|
|
|
|
bHandled = TRUE;
|
|
|
|
exit:
|
|
return LresFromHr(hr);
|
|
}
|
|
|
|
LRESULT CWZeroConfPage::OnPushAdvanced(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
|
|
{
|
|
bHandled = TRUE;
|
|
DialogBoxParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDD_LAN_WZC_ADVANCED), m_hWnd, AdvancedDialogProc, (LPARAM) this);
|
|
RefreshListView(WZCOP_VLIST|WZCOP_PLIST);
|
|
RefreshButtons();
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CWZeroConfPage::OnPushProperties(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
|
|
{
|
|
bHandled = TRUE;
|
|
int iItem = ListView_GetNextItem(m_hwndPLV, -1, LVNI_SELECTED);
|
|
if (-1 != iItem)
|
|
{
|
|
_DoProperties(m_hwndPLV, iItem);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
HRESULT CWZeroConfPage::_DoProperties(HWND hwndLV, int iItem)
|
|
{
|
|
LV_ITEM lvi = {0};
|
|
|
|
// we need to get to the corresponding config object
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = iItem;
|
|
|
|
if (ListView_GetItem(hwndLV, &lvi) && lvi.lParam != NULL)
|
|
{
|
|
CWZCConfig *pConfig = (CWZCConfig*)lvi.lParam;
|
|
|
|
if (hwndLV == m_hwndVLV)
|
|
{
|
|
CWZCConfigProps dlgProps;
|
|
|
|
dlgProps.UploadWzcConfig(pConfig);
|
|
// bring up the info dialog (it only has "Close" so the user can't
|
|
// change anything there, hence there is no reason to do anything
|
|
// more here.
|
|
dlgProps.DoModal(m_hWnd);
|
|
}
|
|
else
|
|
{
|
|
BOOL bOk = FALSE;
|
|
CWZCConfigPage PpWzcProps(WZCDLG_PROPS_RWAUTH|WZCDLG_PROPS_RWWEP);
|
|
CEapolConfig *pEapolConfig;
|
|
|
|
PpWzcProps.UploadWzcConfig(pConfig);
|
|
|
|
pEapolConfig = new CEapolConfig;
|
|
bOk = (pEapolConfig != NULL);
|
|
|
|
if (bOk)
|
|
{
|
|
CWLANAuthenticationPage PpAuthProps(NULL, m_pnc, m_pconn, g_aHelpIDs_IDD_SECURITY);
|
|
|
|
pEapolConfig->CopyEapolConfig(pConfig->m_pEapolConfig);
|
|
PpAuthProps.UploadEapolConfig(pEapolConfig, &PpWzcProps);
|
|
PpWzcProps.UploadEapolConfig(pEapolConfig);
|
|
bOk = (_DoModalPropSheet(&PpWzcProps, &PpAuthProps, TRUE) > 0);
|
|
}
|
|
|
|
// bring up the modal property sheet
|
|
if (bOk)
|
|
{
|
|
// copy over the info from the dialog. SSID & Infra Mode should have been locked
|
|
// so the position of this entry in the internal and UI list has not changed
|
|
memcpy(&pConfig->m_wzcConfig, &PpWzcProps.m_wzcConfig, sizeof(WZC_WLAN_CONFIG));
|
|
|
|
delete pConfig->m_pEapolConfig;
|
|
pConfig->m_pEapolConfig = pEapolConfig;
|
|
}
|
|
|
|
if (!bOk && pEapolConfig != NULL)
|
|
delete pEapolConfig;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
INT CWZeroConfPage::_DoModalPropSheet(CWZCConfigPage *pPpWzcPage, CWLANAuthenticationPage *pPpAuthPage, BOOL bCustomizeTitle)
|
|
{
|
|
INT retCode = 0;
|
|
PROPSHEETHEADER psh;
|
|
HPROPSHEETPAGE hpsp[2];
|
|
INT npsp = 0;
|
|
LPWSTR pwszCaption = NULL;
|
|
WCHAR wszBuffer[64];
|
|
|
|
hpsp[0] = pPpWzcPage->CreatePage(
|
|
IDC_WZC_DLG_PROPS,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
WZCGetSPResModule());
|
|
npsp++;
|
|
if (hpsp[0] == NULL)
|
|
return -1;
|
|
|
|
if(pPpAuthPage != NULL)
|
|
{
|
|
hpsp[1] = pPpAuthPage->CreatePage(
|
|
IDD_LAN_SECURITY,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
WZCGetSPResModule());
|
|
npsp++;
|
|
if (hpsp[1] == NULL)
|
|
return -1;
|
|
}
|
|
|
|
ZeroMemory (&psh, sizeof(psh));
|
|
psh.dwSize = sizeof( PROPSHEETHEADER );
|
|
psh.dwFlags = PSH_NOAPPLYNOW ;
|
|
psh.hwndParent = m_hWnd;
|
|
psh.hInstance = WZCGetSPResModule();
|
|
psh.nPages = npsp;
|
|
psh.phpage = hpsp;
|
|
psh.nStartPage = 0;
|
|
|
|
// just double check the SsidLength is no larger than the allowed size!
|
|
if (bCustomizeTitle && pPpWzcPage->m_wzcConfig.Ssid.SsidLength <= 32)
|
|
{
|
|
// SzLoadString returns either the right string or " " (space)
|
|
//LPCWSTR pwszSuffix = SzLoadString(WZCGetSPResModule(), IDS_WZC_DLG_CAP_SUFFIX);
|
|
LPCWSTR pwszSuffix = wszBuffer;
|
|
UINT nLen = 0;
|
|
|
|
LoadString(WZCGetSPResModule(), IDS_WZC_DLG_CAP_SUFFIX, wszBuffer, sizeof(wszBuffer));
|
|
|
|
// alocate space enough for the SSID (32 ACP chars can't result in more than 32 WCHARs)
|
|
// the space between the SSID and the suffix, the suffix itself and the null-terminator
|
|
pwszCaption = new WCHAR [wcslen(pwszSuffix) + pPpWzcPage->m_wzcConfig.Ssid.SsidLength + 2];
|
|
// in case of failure put in just the suffix!
|
|
if (pwszCaption == NULL)
|
|
{
|
|
psh.pszCaption = pwszSuffix;
|
|
}
|
|
else
|
|
{
|
|
if (pPpWzcPage->m_wzcConfig.Ssid.SsidLength)
|
|
{
|
|
nLen = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
(LPCSTR)pPpWzcPage->m_wzcConfig.Ssid.Ssid,
|
|
pPpWzcPage->m_wzcConfig.Ssid.SsidLength,
|
|
pwszCaption,
|
|
32); // no more than 32 WCHARs reserved for the SSID
|
|
}
|
|
pwszCaption[nLen] = L' ';
|
|
// this copies the null terminator as well
|
|
wcscpy(&(pwszCaption[nLen + 1]), pwszSuffix);
|
|
psh.pszCaption = pwszCaption;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LoadString(WZCGetSPResModule(), IDS_WZC_DLG_CAPTION, wszBuffer, sizeof(wszBuffer));
|
|
//psh.pszCaption = SzLoadString(WZCGetSPResModule(), IDS_WZC_DLG_CAPTION);
|
|
psh.pszCaption = wszBuffer;
|
|
}
|
|
|
|
retCode = PropertySheet(&psh);
|
|
|
|
if (pwszCaption != NULL)
|
|
delete pwszCaption;
|
|
|
|
return retCode;
|
|
}
|
|
|
|
// Advanced dialog
|
|
INT_PTR CALLBACK CWZeroConfPage::AdvancedDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// Get the pointer to our instance from where we stashed it.
|
|
CWZeroConfPage* pThis = (CWZeroConfPage*) ::GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
if (!pThis)
|
|
{
|
|
if (WM_INITDIALOG == uMsg)
|
|
{
|
|
// Stash our instance pointer
|
|
pThis = (CWZeroConfPage*) lParam;
|
|
::SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) pThis);
|
|
}
|
|
}
|
|
|
|
if (pThis)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
// select the correct item by default
|
|
NDIS_802_11_NETWORK_INFRASTRUCTURE mode = (NDIS_802_11_NETWORK_INFRASTRUCTURE)(pThis->m_dwCtlFlags & INTFCTL_CM_MASK);
|
|
UINT idSelect;
|
|
switch (mode)
|
|
{
|
|
case Ndis802_11IBSS:
|
|
// Computer-to-computer
|
|
idSelect = IDC_ADHOC;
|
|
break;
|
|
case Ndis802_11Infrastructure:
|
|
// infrastructure (access point) network
|
|
idSelect = IDC_INFRA;
|
|
break;
|
|
case Ndis802_11AutoUnknown:
|
|
default:
|
|
// Any network (access point preferred)
|
|
idSelect = IDC_ANYNET;
|
|
};
|
|
|
|
// Select the right radio button
|
|
::SendDlgItemMessage(hwnd, idSelect, BM_SETCHECK, BST_CHECKED, 0);
|
|
|
|
// Check the "fallback to visible networks" checkbox if necessary
|
|
::SendDlgItemMessage(hwnd, IDC_WZC_CHK_Fallback, BM_SETCHECK, (pThis->m_dwCtlFlags & INTFCTL_FALLBACK) ? BST_CHECKED : BST_UNCHECKED, 0);
|
|
}
|
|
|
|
return TRUE;
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
{
|
|
// ...Set the connectivity mode...
|
|
NDIS_802_11_NETWORK_INFRASTRUCTURE mode = Ndis802_11AutoUnknown;
|
|
|
|
// See what type of network connectivity the user selected
|
|
if (BST_CHECKED == ::SendDlgItemMessage(hwnd, IDC_ADHOC, BM_GETCHECK, 0, 0))
|
|
{
|
|
// Computer-to-computer
|
|
mode = Ndis802_11IBSS;
|
|
}
|
|
else if (BST_CHECKED == ::SendDlgItemMessage(hwnd, IDC_INFRA, BM_GETCHECK, 0, 0))
|
|
{
|
|
// infrastructure (access point) network
|
|
mode = Ndis802_11Infrastructure;
|
|
}
|
|
else if (BST_CHECKED == ::SendDlgItemMessage(hwnd, IDC_ANYNET, BM_GETCHECK, 0, 0))
|
|
{
|
|
// Any network (access point preferred)
|
|
mode = Ndis802_11AutoUnknown;
|
|
}
|
|
|
|
pThis->m_dwCtlFlags &= ~INTFCTL_CM_MASK;
|
|
pThis->m_dwCtlFlags |= (((DWORD) mode) & INTFCTL_CM_MASK);
|
|
|
|
|
|
// Set the "fallback to visible networks" flag
|
|
pThis->m_dwCtlFlags &= ~INTFCTL_FALLBACK;
|
|
if (BST_CHECKED == ::SendDlgItemMessage(hwnd, IDC_WZC_CHK_Fallback, BM_GETCHECK, 0, 0))
|
|
{
|
|
pThis->m_dwCtlFlags |= INTFCTL_FALLBACK;
|
|
}
|
|
|
|
|
|
::EndDialog(hwnd, IDOK);
|
|
}
|
|
return TRUE;
|
|
}
|
|
break;
|
|
case WM_CLOSE:
|
|
::EndDialog(hwnd, IDCANCEL);
|
|
return TRUE;
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
::WinHelp(hwnd,
|
|
c_szNetCfgHelpFile,
|
|
HELP_CONTEXTMENU,
|
|
(ULONG_PTR)g_aHelpIDs_IDC_WZC_ADVANCED);
|
|
return TRUE;
|
|
}
|
|
case WM_HELP:
|
|
{
|
|
LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
|
|
::WinHelp(static_cast<HWND>(lphi->hItemHandle),
|
|
c_szNetCfgHelpFile,
|
|
HELP_WM_HELP,
|
|
(ULONG_PTR)g_aHelpIDs_IDC_WZC_ADVANCED);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|