|
|
#include <precomp.h>
#include "wzcatl.h"
#include "quickcfg.h"
#include "eapolcfg.h"
#include "wzccore.h"
#include "wzchelp.h"
#define RFSH_TIMEOUT 3500
UINT g_TimerID = 373; // g_wszHiddWebK is a string of 26 bullets (0x25cf - the hidden password char) and a NULL
WCHAR g_wszHiddWepK[] = {0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x25cf, 0x0000};
#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0]))
// Enhanced message box function
int DisplayFormatMessage(HWND hwnd, UINT idCaption, UINT idFormatString, UINT uType, ...);
//+---------------------------------------------------------------------------
// checks the validity of the WEP Key material and selects the
// material from the first invalid char (non hexa in hexa format or longer
// than the specified length
DWORD CWZCQuickCfg::GetWepKMaterial(UINT *pnKeyLen, LPBYTE *ppbKMat, DWORD *pdwCtlFlags) { DWORD dwErr = ERROR_SUCCESS; UINT nKeyLen = ::GetWindowTextLength(m_hEdtWepK); DWORD dwCtlFlags = 0; LPSTR pszKMat = NULL;
// we only accept the follwing material for WEP keys:
// - no text (length 0) => there is no WEP key provided
// - 5 chars or 10 hexadecimal digits (5byte / 40bit key)
// - 13 chars or 26 hexadecimal digits (13byte / 104bit key)
// - 16 chars or 32 hexadecimal digits (16byte / 128bit key)
if (nKeyLen != 0 && nKeyLen != WZC_WEPKMAT_40_ASC && nKeyLen != WZC_WEPKMAT_40_HEX && nKeyLen != WZC_WEPKMAT_104_ASC && nKeyLen != WZC_WEPKMAT_104_HEX && nKeyLen != WZC_WEPKMAT_128_ASC && nKeyLen != WZC_WEPKMAT_128_HEX) { dwErr = ERROR_INVALID_DATA; } else if (nKeyLen != 0) // the key is either ascii or hexadecimal, 40 or 104bit
{ dwCtlFlags = WZCCTL_WEPK_PRESENT;
pszKMat = new CHAR[nKeyLen + 1]; if (pszKMat == NULL) dwErr = ERROR_NOT_ENOUGH_MEMORY;
// get the current key material from the edit control
if (dwErr == ERROR_SUCCESS) { if (nKeyLen != ::GetWindowTextA(m_hEdtWepK, pszKMat, nKeyLen+1)) dwErr = GetLastError(); }
// now we have the key material
if (dwErr == ERROR_SUCCESS) { // if the key is provided in hexadecimal digits, mark it in
// the ctl flags and do the conversion
if (nKeyLen == WZC_WEPKMAT_40_HEX || nKeyLen == WZC_WEPKMAT_104_HEX || nKeyLen == WZC_WEPKMAT_128_HEX) { UINT i = 0, j = 0;
dwCtlFlags |= WZCCTL_WEPK_XFORMAT; while (i < nKeyLen && pszKMat[i] != '\0') { BYTE chHexByte = 0; if (!isxdigit(pszKMat[i]) || !isxdigit(pszKMat[i+1])) { dwErr = ERROR_INVALID_DATA; break; } chHexByte = HEX(pszKMat[i]) << 4; i++; chHexByte |= HEX(pszKMat[i]); i++; pszKMat[j++] = chHexByte; }
// if everything went fine, since we parsed hexadecimal digits
// it means the real length is half of the text length (two hexadecimal
// digits per byte)
if (dwErr == ERROR_SUCCESS) nKeyLen /= 2; } } }
if (dwErr == ERROR_SUCCESS) { if (pdwCtlFlags != NULL) *pdwCtlFlags = dwCtlFlags;
if (pnKeyLen != NULL) *pnKeyLen = nKeyLen;
if (ppbKMat != NULL) *ppbKMat = (LPBYTE)pszKMat; else if (pszKMat != NULL) delete pszKMat; } else { if (pszKMat != NULL) delete pszKMat; }
return dwErr; }
//+---------------------------------------------------------------------
// IsConfigInList - checks whether the pwzcConfig (WZC_WLAN_CONFIG object) is
// in the list provided as the first parameter.
BOOL CWZCQuickCfg::IsConfigInList(CWZCConfig *pHdList, PWZC_WLAN_CONFIG pwzcConfig, CWZCConfig **ppMatchingConfig) { BOOL bYes = FALSE;
if (pHdList != NULL) { CWZCConfig *pwzcCrt;
pwzcCrt = pHdList; do { if (pwzcCrt->Match(pwzcConfig)) { if (ppMatchingConfig != NULL) *ppMatchingConfig = pwzcCrt;
bYes = TRUE; break; } pwzcCrt = pwzcCrt->m_pNext; } while(pwzcCrt != pHdList); }
return bYes; }
//+---------------------------------------------------------------------
// InitListView - initializes the networks list view (doesn't fill it in)
DWORD CWZCQuickCfg::InitListView() { RECT rc; LV_COLUMN lvc = {0}; DWORD dwStyle;
// initialize the image list styles
dwStyle = ::GetWindowLong(m_hLstNetworks, GWL_STYLE); ::SetWindowLong(m_hLstNetworks, GWL_STYLE, (dwStyle | LVS_SHAREIMAGELISTS));
// Create state image lists
m_hImgs = ImageList_LoadImage( _Module.GetResourceInstance(), MAKEINTRESOURCE(IDB_WZC_LISTICONS), 16, 0, PALETTEINDEX(6), IMAGE_BITMAP, 0);
ListView_SetImageList(m_hLstNetworks, m_hImgs, LVSIL_SMALL); lvc.mask = LVCF_FMT | LVCF_WIDTH; lvc.fmt = LVCFMT_LEFT;
::GetClientRect(m_hLstNetworks, &rc); lvc.cx = rc.right - GetSystemMetrics(SM_CXVSCROLL); //lvc.cx = rc.right;
ListView_InsertColumn(m_hLstNetworks, 0, &lvc);
ListView_SetExtendedListViewStyleEx(m_hLstNetworks, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
return ERROR_SUCCESS; }
//+---------------------------------------------------------------------
// GetOIDs - gets the OIDs for the m_IntfEntry member. It assumes the
// GUID is set already
DWORD CWZCQuickCfg::GetOIDs(DWORD dwInFlags, LPDWORD pdwOutFlags) { DWORD dwError = ERROR_SUCCESS; DWORD dwOutFlags;
if (m_IntfEntry.wszGuid == NULL) { m_IntfEntry.wszGuid = (LPWSTR)RpcCAlloc(sizeof(WCHAR)*GUID_NCH); if (m_IntfEntry.wszGuid == NULL) { dwError = GetLastError(); } else { // don't care of the return code. If getting the GUID fails (it shouldn't)
// then we end up with a "0000..." GUID which will fail anyhow in the
// RPC call later
StringFromGUID2( m_Guid, m_IntfEntry.wszGuid, GUID_NCH); } }
if (dwError == ERROR_SUCCESS) { 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; } dwError = WZCQueryInterface( NULL, dwInFlags, &m_IntfEntry, pdwOutFlags); }
return dwError; }
//+---------------------------------------------------------------------
// SavePreferredConfigs - fills in the INTF_ENTRY parameter with all
// the preferred networks from the m_pHdPList
DWORD CWZCQuickCfg::SavePreferredConfigs(PINTF_ENTRY pIntf, CWZCConfig *pStartCfg) { 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; pwzcPrefrdList->Index = 0; // we have now all we need - start copying the preferred
pCrt = m_pHdPList; do { PWZC_WLAN_CONFIG pPrefrdConfig;
// if this is the configuration that needs to attempted first,
// mark its index in the Index field.
if (pCrt == pStartCfg) { pwzcPrefrdList->Index = pwzcPrefrdList->NumberOfItems;
// save the 802.1x configuration just for the configuration we're connecting to!
if (pCrt->m_pEapolConfig != NULL) { dwLErr = pCrt->m_pEapolConfig->SaveEapolConfig(m_IntfEntry.wszGuid, &(pCrt->m_wzcConfig.Ssid));
if (dwErr == ERROR_SUCCESS) dwErr = dwLErr; } }
pPrefrdConfig = &(pwzcPrefrdList->Config[pwzcPrefrdList->NumberOfItems++]); CopyMemory(pPrefrdConfig, &pCrt->m_wzcConfig, sizeof(WZC_WLAN_CONFIG));
pCrt = pCrt->m_pNext; } while(pwzcPrefrdList->NumberOfItems < nPrefrd && pCrt != m_pHdPList);
pIntf->rdStSSIDList.dwDataLen = nwzcPrefrdSize; pIntf->rdStSSIDList.pData = (LPBYTE)pwzcPrefrdList; } } else { pIntf->rdStSSIDList.dwDataLen = 0; pIntf->rdStSSIDList.pData = NULL; }
return dwErr; }
//+---------------------------------------------------------------------
// FillVisibleList - fills in the configs from the WZC_802_11_CONFIG_LIST object
// into the list of visible configs
DWORD CWZCQuickCfg::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 CWZCQuickCfg::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]); CWZCConfig *pVConfig = NULL; DWORD dwFlags = WZC_DESCR_PREFRD;
// check whether this preferred is also visible and adjust dwFlags if so
if (IsConfigInList(m_pHdVList, pwzcPConfig, &pVConfig)) { // mark the visible entry as being also preferred!
// NOTE: This is why the visible list needs to be filled in first!
pVConfig->m_dwFlags |= WZC_DESCR_PREFRD; 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; }
//+---------------------------------------------------------------------------
// 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 CWZCQuickCfg::AddUniqueConfig( DWORD dwOpFlags, DWORD dwEntryFlags, PWZC_WLAN_CONFIG pwzcConfig, CWZCConfig **ppNewNode) { DWORD dwErr = ERROR_SUCCESS; CWZCConfig *pHdList = (dwEntryFlags & WZC_DESCR_PREFRD) ? m_pHdPList : m_pHdVList;
// skip the null SSIDs from the visible list (coming from APs
// not responding to broadcast SSID).
if (pHdList == m_pHdVList) { UINT i = pwzcConfig->Ssid.SsidLength; for (; 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 { 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; } }
// 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.
if (dwOpFlags & WZCADD_OVERWRITE || pCrt->Weaker(pwzcConfig)) { memcpy(&(pCrt->m_wzcConfig), pwzcConfig, sizeof(WZC_WLAN_CONFIG)); }
// 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 { 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; } }
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; }
//+---------------------------------------------------------------------------
// Display the Visible & Preferred lists into their controls
DWORD CWZCQuickCfg::RefreshListView() { DWORD dwErr = ERROR_SUCCESS; CWZCConfig *pCrt; UINT i = 0;
// clear first the list
ListView_DeleteAllItems(m_hLstNetworks);
// Add first VPI
if (m_pHdPList != NULL) { pCrt = m_pHdPList; do { if (pCrt->m_dwFlags & WZC_DESCR_VISIBLE && pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure) { pCrt->m_nListIndex = i; pCrt->AddConfigToListView(m_hLstNetworks, i++); } pCrt = pCrt->m_pNext; } while (pCrt != m_pHdPList); }
// Add next VI
if (m_pHdVList != NULL) { pCrt = m_pHdVList; do { if (!(pCrt->m_dwFlags & WZC_DESCR_PREFRD) && pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure) { pCrt->m_nListIndex = i; pCrt->AddConfigToListView(m_hLstNetworks, i++); } pCrt = pCrt->m_pNext; } while (pCrt != m_pHdVList); }
// Add now VPA
if (m_pHdPList != NULL) { pCrt = m_pHdPList; do { if (pCrt->m_dwFlags & WZC_DESCR_VISIBLE && pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS) { pCrt->m_nListIndex = i; pCrt->AddConfigToListView(m_hLstNetworks, i++); } pCrt = pCrt->m_pNext; } while (pCrt != m_pHdPList); }
// Add now VA
if (m_pHdVList != NULL) { pCrt = m_pHdVList; do { if (!(pCrt->m_dwFlags & WZC_DESCR_PREFRD) && pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS) { pCrt->m_nListIndex = i; pCrt->AddConfigToListView(m_hLstNetworks, i++); } pCrt = pCrt->m_pNext; } while (pCrt != m_pHdVList); }
ListView_SetItemState(m_hLstNetworks, 0, LVIS_SELECTED, LVIS_SELECTED); ListView_EnsureVisible(m_hLstNetworks, 0, FALSE);
return dwErr; }
DWORD CWZCQuickCfg::RefreshControls() { DWORD dwError = ERROR_SUCCESS; CWZCConfig *pConfig = NULL; LVITEM lvi = {0}; INT iSelected; BOOL bEnableWepCtrls = FALSE; UINT nKLen = 0; UINT nCheckOneX = BST_UNCHECKED; BOOL bEnableOneX = FALSE;
// get the selected item from the visible list
iSelected = ListView_GetNextItem(m_hLstNetworks, -1, LVNI_SELECTED); if (iSelected >= 0) { lvi.mask = LVIF_PARAM; lvi.iItem = iSelected; if (ListView_GetItem(m_hLstNetworks, &lvi)) { pConfig = (CWZCConfig*)lvi.lParam; } } else { ::EnableWindow(m_hBtnConnect, FALSE); return dwError; }
// since we just switched the networks, yes, the wep key can be seen as touched.
// If we find out there is already a key available, we'll reset this flag and go
// with that one until the user is clicking it.
m_bKMatTouched = TRUE;
if (pConfig != NULL) { CWZCConfig *pVConfig;
// pick up the "privacy" bit from the matching visible configuration
// NOTE: The test below should always succeed actually
if (IsConfigInList(m_pHdVList, &(pConfig->m_wzcConfig), &pVConfig)) bEnableWepCtrls = (pVConfig->m_wzcConfig.Privacy != 0); else bEnableWepCtrls = (pConfig->m_wzcConfig.Privacy != 0);
if (pConfig->m_dwFlags & WZC_DESCR_PREFRD && pConfig->m_wzcConfig.dwCtlFlags & WZCCTL_WEPK_PRESENT && pConfig->m_wzcConfig.KeyLength > 0) { //--- when a password is to be displayed as hidden chars, don't put in
//--- its actual length, but just 8 bulled chars.
nKLen = 8;
m_bKMatTouched = FALSE; }
if (bEnableWepCtrls) { // For networks requiring privacy, 802.1X is going to be by default disabled and
// locked out on all IBSS networks.
if (pConfig->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS) { nCheckOneX = BST_UNCHECKED; bEnableOneX = FALSE; } else { // for all non-preferred Infrastructure networks, 802.1X is going to be by default
// enabled since these networks start with "the key is provided for me automatically"
// which suggests 802.1X.
if (!(pConfig->m_dwFlags & WZC_DESCR_PREFRD)) { nCheckOneX = BST_CHECKED; } else // this is a preferred Infrastructure network
{ // initial 802.1X state is the one from the profile
nCheckOneX = pConfig->m_pEapolConfig->Is8021XEnabled() ? BST_CHECKED: BST_UNCHECKED; } // for Infrastructure networks requiring privacy, user is allowed to change 802.1X state
bEnableOneX = TRUE; } } }
g_wszHiddWepK[nKLen] = L'\0'; ::SetWindowText(m_hEdtWepK, g_wszHiddWepK); ::SetWindowText(m_hEdtWepK2, g_wszHiddWepK); g_wszHiddWepK[nKLen] = 0x25cf;
if (bEnableWepCtrls) { CheckDlgButton(IDC_WZCQCFG_CHK_ONEX, nCheckOneX); ::EnableWindow(m_hChkOneX, bEnableOneX);
if (::IsWindowEnabled(m_hEdtWepK2)) { ::EnableWindow(m_hLblWepK2, FALSE); ::EnableWindow(m_hEdtWepK2, FALSE); }
if (::IsWindowVisible(m_hLblNoWepKInfo)) { ::ShowWindow(m_hWarnIcon, SW_HIDE); ::ShowWindow(m_hLblNoWepKInfo, SW_HIDE); ::ShowWindow(m_hChkNoWepK, SW_HIDE); }
if (!::IsWindowVisible(m_hLblWepKInfo)) { ::ShowWindow(m_hLblWepKInfo, SW_SHOW); ::ShowWindow(m_hLblWepK, SW_SHOW); ::ShowWindow(m_hEdtWepK, SW_SHOW); ::ShowWindow(m_hLblWepK2, SW_SHOW); ::ShowWindow(m_hEdtWepK2, SW_SHOW); ::ShowWindow(m_hChkOneX, SW_SHOW); } } else { if (::IsWindowVisible(m_hLblWepKInfo)) { ::ShowWindow(m_hLblWepKInfo, SW_HIDE); ::ShowWindow(m_hLblWepK, SW_HIDE); ::ShowWindow(m_hEdtWepK, SW_HIDE); ::ShowWindow(m_hLblWepK2, SW_HIDE); ::ShowWindow(m_hEdtWepK2, SW_HIDE); ::ShowWindow(m_hChkOneX, SW_HIDE); }
if (!::IsWindowVisible(m_hLblNoWepKInfo)) { ::ShowWindow(m_hWarnIcon, SW_SHOW); ::ShowWindow(m_hLblNoWepKInfo, SW_SHOW); ::ShowWindow(m_hChkNoWepK, SW_SHOW); CheckDlgButton(IDC_WZCQCFG_CHK_NOWK,BST_UNCHECKED); }
pConfig = NULL; // reset the pointer to the configuration to force disable the "Connect" button
}
::EnableWindow(m_hBtnConnect, pConfig != NULL);
return dwError; }
//+---------------------------------------------------------------------------
// class constructor
CWZCQuickCfg::CWZCQuickCfg(const GUID * pGuid) { // initialize the UI handles
m_hLblInfo = NULL; m_hLblNetworks = NULL; m_hLstNetworks = NULL; m_hLblWepKInfo = NULL; m_hLblWepK = NULL; m_hEdtWepK = NULL; m_hLblWepK2 = NULL; m_hEdtWepK2 = NULL; m_hChkOneX = NULL; m_hWarnIcon = NULL; m_hLblNoWepKInfo = NULL; m_hChkNoWepK = NULL; m_hBtnAdvanced = NULL; m_hBtnConnect = NULL; // initialize the Images handle
m_hImgs = NULL;
// initialize the WZC data
m_bHaveWZCData = FALSE; ZeroMemory(&m_IntfEntry, sizeof(INTF_ENTRY)); m_dwOIDFlags = 0; m_nTimer = 0; m_hCursor = NULL;
if (pGuid != NULL) m_Guid = *pGuid; else ZeroMemory(&m_Guid, sizeof(GUID));
// init the internal list heads
m_pHdVList = NULL; m_pHdPList = NULL;
// init the connection
m_wszTitle = NULL; }
//+---------------------------------------------------------------------------
// class destructor
CWZCQuickCfg::~CWZCQuickCfg() { if (m_hImgs != NULL) ImageList_Destroy(m_hImgs);
// 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); }
//+---------------------------------------------------------------------------
// INIT_DIALOG handler
LRESULT CWZCQuickCfg::OnInitDialog (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { DWORD dwError; DWORD dwInFlags; BOOL bEnableAll;
m_bKMatTouched = TRUE;
// reference the UI controls
m_hLblInfo = GetDlgItem(IDC_WZCQCFG_LBL_INFO); m_hLblNetworks = GetDlgItem(IDC_WZCQCFG_LBL_NETWORKS); m_hLstNetworks = GetDlgItem(IDC_WZCQCFG_NETWORKS); m_hLblWepKInfo = GetDlgItem(IDC_WZCQCFG_LBL_WKINFO); m_hLblWepK = GetDlgItem(IDC_WZCQCFG_LBL_WEPK); m_hEdtWepK = GetDlgItem(IDC_WZCQCFG_WEPK); m_hLblWepK2 = GetDlgItem(IDC_WZCQCFG_LBL_WEPK2); m_hEdtWepK2 = GetDlgItem(IDC_WZCQCFG_WEPK2); m_hChkOneX = GetDlgItem(IDC_WZCQCFG_CHK_ONEX); m_hWarnIcon = GetDlgItem(IDC_WZCQCFG_ICO_WARN); m_hLblNoWepKInfo = GetDlgItem(IDC_WZCQCFG_LBL_NOWKINFO); m_hChkNoWepK = GetDlgItem(IDC_WZCQCFG_CHK_NOWK); m_hBtnAdvanced = GetDlgItem(IDC_WZCQCFG_ADVANCED); m_hBtnConnect = GetDlgItem(IDC_WZCQCFG_CONNECT);
if (m_wszTitle != NULL) SetWindowText(m_wszTitle);
if (m_hWarnIcon != NULL) ::SendMessage(m_hWarnIcon, STM_SETICON, (WPARAM)LoadIcon(NULL, IDI_WARNING), (LPARAM)0);
// sets the icon images for the list view
InitListView();
CenterWindow(); m_dwOIDFlags = 0; dwInFlags = INTF_BSSIDLIST|INTF_PREFLIST|INTF_ALL_FLAGS; dwError = GetOIDs(dwInFlags,&m_dwOIDFlags); if (m_dwOIDFlags == dwInFlags) { // if the OIDs are supported, fill in everything.
if (m_IntfEntry.dwCtlFlags & INTFCTL_OIDSSUPP) { // 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); // fill in the list view
RefreshListView();
m_hCursor = SetCursor(LoadCursor(NULL, IDC_ARROW)); // and enable all controls
bEnableAll = TRUE; } } else { // 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 = (UINT)SetTimer(g_TimerID, RFSH_TIMEOUT); bEnableAll = FALSE; }
// now that the UI is filled up set the remaining controls to their
// respective states.
RefreshControls();
::EnableWindow(m_hLblInfo, bEnableAll); ::EnableWindow(m_hLblNetworks, bEnableAll); ::EnableWindow(m_hLstNetworks, bEnableAll); ::EnableWindow(m_hBtnAdvanced, bEnableAll); ::SetFocus(m_hLstNetworks); bHandled = TRUE; return 0; } //+---------------------------------------------------------------------------
// Help handlers
extern const WCHAR c_szNetCfgHelpFile[]; LRESULT CWZCQuickCfg::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ::WinHelp(m_hWnd, c_wszWzcHelpFile, HELP_CONTEXTMENU, (ULONG_PTR)g_aHelpIDs_IDD_WZCQCFG); bHandled = TRUE; return 0; } LRESULT CWZCQuickCfg::OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { LPHELPINFO lphi = reinterpret_cast<LPHELPINFO>(lParam);
if (HELPINFO_WINDOW == lphi->iContextType) { ::WinHelp(static_cast<HWND>(lphi->hItemHandle), c_wszWzcHelpFile, HELP_WM_HELP, (ULONG_PTR)g_aHelpIDs_IDD_WZCQCFG); bHandled = TRUE; } return 0; } //+---------------------------------------------------------------------
// Refresh timer handler
LRESULT CWZCQuickCfg::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { if (m_nTimer != 0) { BOOL bEnableAll; DWORD dwInFlags;
// switch the cursor back to whatever it was
SetCursor(LoadCursor(NULL, IDC_ARROW)); KillTimer(m_nTimer); m_nTimer = 0;
m_dwOIDFlags = 0; dwInFlags = INTF_BSSIDLIST|INTF_PREFLIST|INTF_ALL_FLAGS; GetOIDs(dwInFlags,&m_dwOIDFlags); bEnableAll = (m_dwOIDFlags == dwInFlags) && (m_IntfEntry.dwCtlFlags & INTFCTL_OIDSSUPP);
if (bEnableAll) { // 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); // fill in the list view
RefreshListView(); }
// now that the UI is filled up set the remaining controls to their
// respective states.
RefreshControls();
// enable all the UI when done refreshing
::EnableWindow(m_hLblInfo, bEnableAll); ::EnableWindow(m_hLblNetworks, bEnableAll); ::EnableWindow(m_hLstNetworks, bEnableAll); ::EnableWindow(m_hBtnAdvanced, bEnableAll); }
return 0; }
//+---------------------------------------------------------------------
// Selection changed in the list
LRESULT CWZCQuickCfg::OnItemChanged( int idCtrl, LPNMHDR pnmh, BOOL& bHandled) { bHandled = TRUE; RefreshControls(); ::SetFocus(m_hLstNetworks); return 0; }
//+---------------------------------------------------------------------
// User clicked an entry in the list
LRESULT CWZCQuickCfg::OnDbClick(int idCtrl, LPNMHDR pnmh, BOOL& bHandled) { if (idCtrl == IDC_WZCQCFG_NETWORKS && ::IsWindowEnabled(m_hBtnConnect)) { OnConnect( (WORD)pnmh->code, (WORD)pnmh->idFrom, pnmh->hwndFrom, bHandled); } return 0; }
//+---------------------------------------------------------------------------
// OnConnect button handler
LRESULT CWZCQuickCfg::OnConnect(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { DWORD dwErr = ERROR_SUCCESS; INT iSelected; CWZCConfig *pConfig = NULL; UINT nKeyLen; LPBYTE pbKMat = NULL; DWORD dwCtlFlags; BOOL bOkToDismiss = TRUE;
// get the selected item from the visible list
iSelected = ListView_GetNextItem(m_hLstNetworks, -1, LVNI_SELECTED); if (iSelected < 0) dwErr = ERROR_GEN_FAILURE;
// iSelected should be 0 otherwise "Connect" won't be enabled
if (dwErr == ERROR_SUCCESS) { LVITEM lvi = {0}; lvi.mask = LVIF_PARAM; lvi.iItem = iSelected; if (ListView_GetItem(m_hLstNetworks, &lvi)) { pConfig = (CWZCConfig*)lvi.lParam; if (pConfig == NULL) dwErr = ERROR_GEN_FAILURE; } else dwErr = ERROR_GEN_FAILURE; } if (dwErr == ERROR_SUCCESS) { // here we should have a valid pConfig
ASSERT(pConfig);
if ((m_IntfEntry.dwCtlFlags & INTFCTL_CM_MASK) != Ndis802_11AutoUnknown && (m_IntfEntry.dwCtlFlags & INTFCTL_CM_MASK) != pConfig->m_wzcConfig.InfrastructureMode) { // User is trying to access a network type (infra or adhoc) that they're not allowed to access.
// Give them an error message
UINT idMessage = (pConfig->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure) ? IDS_CANTACCESSNET_INFRA : IDS_CANTACCESSNET_ADHOC;
WCHAR szSSID[MAX_PATH]; ListView_GetItemText(m_hLstNetworks, iSelected, 0, szSSID, ARRAYSIZE(szSSID));
DisplayFormatMessage(m_hWnd, IDS_WZCERR_CAPTION, idMessage, MB_ICONERROR | MB_OK, szSSID);
// Can't connect - error
dwErr = ERROR_GEN_FAILURE; // Don't close the dialog
bOkToDismiss = FALSE; } }
// get the WEP key only if the user touched it. m_bKMatTouched is FALSE only when the configuration
// selected is already in the preferred list and that preferred config already contained a key which was
// not touched a bit by the user. Otherwise it is TRUE.
if (dwErr == ERROR_SUCCESS && m_bKMatTouched) { UINT nIdsErr;
// check whether the WEP key has the right format
dwErr = GetWepKMaterial(&nKeyLen, &pbKMat, &dwCtlFlags); if (dwErr != ERROR_SUCCESS) { ::SendMessage(m_hEdtWepK, EM_SETSEL, 0, (LPARAM)-1); ::SetFocus(m_hEdtWepK); nIdsErr = IDS_WZCERR_INVALID_WEPK; }
// check whether the WEP key is confirmed correctly
if (dwErr == ERROR_SUCCESS && nKeyLen > 0) { WCHAR wszWepK1[32], wszWepK2[32]; UINT nKeyLen1, nKeyLen2;
nKeyLen1 = ::GetWindowText(m_hEdtWepK, wszWepK1, sizeof(wszWepK1)/sizeof(WCHAR)); nKeyLen2 = ::GetWindowText(m_hEdtWepK2, wszWepK2, sizeof(wszWepK2)/sizeof(WCHAR));
if (nKeyLen1 != nKeyLen2 || nKeyLen1 == 0 || wcscmp(wszWepK1, wszWepK2) != 0) { nIdsErr = IDS_WZCERR_MISMATCHED_WEPK; ::SetWindowText(m_hEdtWepK2, L""); ::SetFocus(m_hEdtWepK2); dwErr = ERROR_INVALID_DATA; } }
if (dwErr != ERROR_SUCCESS) { WCHAR wszBuffer[MAX_PATH]; WCHAR wszCaption[MAX_PATH];
LoadString(nIdsErr == IDS_WZCERR_INVALID_WEPK ? _Module.GetResourceInstance() : WZCGetSPResModule(), nIdsErr, wszBuffer, MAX_PATH); LoadString(_Module.GetResourceInstance(), IDS_WZCERR_CAPTION, wszCaption, MAX_PATH); MessageBox(wszBuffer, wszCaption, MB_ICONERROR|MB_OK); bOkToDismiss = FALSE; } }
// we do have the right WEP key here, lets copy it to the corresponding config
if (dwErr == ERROR_SUCCESS) { // if this configuration is not a preferred one, copy it in the preferred
// list at the top of its group
if (!(pConfig->m_dwFlags & WZC_DESCR_PREFRD)) { // move this configuration out of the visible list
pConfig->m_pNext->m_pPrev = pConfig->m_pPrev; pConfig->m_pPrev->m_pNext = pConfig->m_pNext;
// if the list head pointed on this config, move it to
// the next in the list
if (m_pHdVList == pConfig) m_pHdVList = pConfig->m_pNext;
// if the list head still points on the same config,
// it means this was the only one in the list. So, null out the head.
if (m_pHdVList == pConfig) m_pHdVList = NULL;
//next insert this visible config in the preferred list
if (m_pHdPList == NULL) { m_pHdPList = pConfig; pConfig->m_pNext = pConfig; pConfig->m_pPrev = pConfig; } else { CWZCConfig *pCrt;
// the new preferred config comes on top of the list if:
// (it is infrastructure) or (there are no infrastructures in the preferred list)
if (pConfig->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure || m_pHdPList->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS) { pCrt = m_pHdPList; m_pHdPList = pConfig; } else // it definitely doesn't come the first in the list
{ for (pCrt = m_pHdPList->m_pNext; pCrt != m_pHdPList; pCrt=pCrt->m_pNext) { // if this is the first configuration in the matching group break the loop
if (pCrt->m_wzcConfig.InfrastructureMode == Ndis802_11IBSS) break; } }
// now we have to insert pConfig in the front of pCrt;
pConfig->m_pNext = pCrt; pConfig->m_pPrev = pCrt->m_pPrev; pConfig->m_pNext->m_pPrev = pConfig; pConfig->m_pPrev->m_pNext = pConfig; } } // if the configuration is a preferred one, just make sure we copy over the
// privacy bit from the visible list. That one is the "real" thing
else { CWZCConfig *pVConfig;
if (IsConfigInList(m_pHdVList, &pConfig->m_wzcConfig, &pVConfig)) { pConfig->m_wzcConfig.Privacy = pVConfig->m_wzcConfig.Privacy; } }
// now the configuration is at its right position - put in the new WEP key, if any was typed in
if (pConfig->m_wzcConfig.Privacy && m_bKMatTouched) { // if no key is provided, it means there is no key material.
// All we do is to reset the corresponding bit - whatever material was there
// will be preserved along with its length & format
if (!(dwCtlFlags & WZCCTL_WEPK_PRESENT)) { pConfig->m_wzcConfig.dwCtlFlags &= ~WZCCTL_WEPK_PRESENT; } else { // now if we have a WEP key, copy over its control flags and material
pConfig->m_wzcConfig.dwCtlFlags = dwCtlFlags; ZeroMemory(pConfig->m_wzcConfig.KeyMaterial, WZCCTL_MAX_WEPK_MATERIAL); pConfig->m_wzcConfig.KeyLength = nKeyLen; memcpy(pConfig->m_wzcConfig.KeyMaterial, pbKMat, nKeyLen); } } }
// if all 802.11 params have been taken care of, copy now the 802.1x params (if needed)
if (dwErr == ERROR_SUCCESS && pConfig->m_pEapolConfig != NULL) { // if the network is an infrastructure one fix the 802.1X state.
// For ad hoc networks don't touch the 802.1x since it might mess the setting for a
// corresponding Infrastructure network (802.1X doesn't differentiate between SSID Infra & SSID ad hoc)
// 802.1X engine is smart enough to not act on ad hoc networks regardless its registry state!
if (pConfig->m_wzcConfig.InfrastructureMode == Ndis802_11Infrastructure) { // if the network requires privacy, set its state according to the "Enable 802.1X" checkbox
if (pConfig->m_wzcConfig.Privacy) { pConfig->m_pEapolConfig->Set8021XState(IsDlgButtonChecked(IDC_WZCQCFG_CHK_ONEX) == BST_CHECKED); } else // if the network doesn't require privacy - disable 802.1X!
{ // if the network is either ad hoc or infrastructure with no wep
// explicitly disable 802.1x
pConfig->m_pEapolConfig->Set8021XState(0); } } }
// ok, save the preferred list back to Wireless Zero Configuration Service
if (dwErr == ERROR_SUCCESS) { RpcFree(m_IntfEntry.rdStSSIDList.pData); m_IntfEntry.rdStSSIDList.dwDataLen = 0; m_IntfEntry.rdStSSIDList.pData = NULL; dwErr = SavePreferredConfigs(&m_IntfEntry, pConfig); }
if (dwErr == ERROR_SUCCESS) { // by saving the preferred list here we're forcing a hard reset to
// the WZC State machine. This is what we want since we're here
// as a consequence of a failure and a user intervention.
dwErr = WZCSetInterface( NULL, INTF_PREFLIST, &m_IntfEntry, NULL);
if (dwErr == ERROR_PARTIAL_COPY) { DisplayFormatMessage( m_hWnd, IDS_WZCERR_CAPTION, IDS_WZC_PARTIAL_APPLY, MB_ICONEXCLAMATION|MB_OK);
dwErr = ERROR_SUCCESS; } }
// in case of any failure we might want to warn the user (another popup?)
// the question is what is the user supposed to do in such a case?
if (dwErr != ERROR_SUCCESS) { dwErr = ERROR_SUCCESS; }
if(pbKMat != NULL) delete pbKMat;
if (bOkToDismiss) { bHandled = TRUE; SpEndDialog(IDOK); } return 0; }
//+---------------------------------------------------------------------------
// OK button handler
LRESULT CWZCQuickCfg::OnCancel(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { bHandled = TRUE; SpEndDialog(IDCANCEL); return 0; }
//+---------------------------------------------------------------------------
// Advanced button handler
LRESULT CWZCQuickCfg::OnAdvanced(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { bHandled = TRUE; SpEndDialog(IDC_WZCQCFG_ADVANCED); return 0; }
int DisplayFormatMessage(HWND hwnd, UINT idCaption, UINT idFormatString, UINT uType, ...) { int iResult = IDCANCEL; TCHAR szError[1024 + 1]; *szError = 0; TCHAR szCaption[256 + 1]; TCHAR szFormat[1024 + 1]; *szFormat = 0;
// Load and format the error body
if (LoadString(WZCGetSPResModule(), idFormatString, szFormat, ARRAYSIZE(szFormat))) { va_list arguments; va_start(arguments, uType);
if (FormatMessage(FORMAT_MESSAGE_FROM_STRING, szFormat, 0, 0, szError, ARRAYSIZE(szError), &arguments)) { // Load the caption
if (LoadString(_Module.GetResourceInstance(), idCaption, szCaption, ARRAYSIZE(szCaption))) { iResult = MessageBox(hwnd, szError, szCaption, uType); } }
va_end(arguments); } return iResult; }
//+---------------------------------------------------------------------------
// Notification handler for the wep key edit text box
LRESULT CWZCQuickCfg::OnWepKMatCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { if (wNotifyCode == EN_SETFOCUS) { if (!m_bKMatTouched) { // the user has just clicked for the first time on an existent key.. clear out the fields,
// standing for "The key is provided automatically"
::SetWindowText(m_hEdtWepK, L""); ::SetWindowText(m_hEdtWepK2, L""); ::EnableWindow(m_hLblWepK2, FALSE); // disable confirmation label for empty key
::EnableWindow(m_hEdtWepK2, FALSE); // disable confirmation edit for empty key
m_bKMatTouched = TRUE;
// if the 802.1X checkbox is enabled then we do have to check it here!
if (::IsWindowEnabled(m_hChkOneX)) CheckDlgButton(IDC_WZCQCFG_CHK_ONEX, BST_CHECKED); } } if (wNotifyCode == EN_CHANGE) { UINT nKMatLen = ::GetWindowTextLength(m_hEdtWepK);
if (!::IsWindowEnabled(m_hEdtWepK2) && nKMatLen > 0) { // user just typed in some key material - enable the confirmation text
::EnableWindow(m_hLblWepK2, TRUE); ::EnableWindow(m_hEdtWepK2, TRUE); // also uncheck 802.1x checkbox
if (::IsWindowEnabled(m_hChkOneX)) CheckDlgButton(IDC_WZCQCFG_CHK_ONEX, BST_UNCHECKED); } if (::IsWindowEnabled(m_hEdtWepK2) && nKMatLen == 0) { // user just deleted all of the key material - switching to
// "The key is provided for me automatically"
::SetWindowText(m_hEdtWepK2, L""); ::EnableWindow(m_hLblWepK2, FALSE); ::EnableWindow(m_hEdtWepK2, FALSE); // auto key suggests 802.1X
if (::IsWindowEnabled(m_hChkOneX)) CheckDlgButton(IDC_WZCQCFG_CHK_ONEX, BST_CHECKED); } }
return 0; }
LRESULT CWZCQuickCfg::OnCheckConfirmNoWep(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { ::EnableWindow(m_hBtnConnect, IsDlgButtonChecked(IDC_WZCQCFG_CHK_NOWK) == BST_CHECKED); return 0; }
|