Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

598 lines
21 KiB

#include "pch.h"
#pragma hdrstop
#include "ncnetcon.h"
#include "ncperms.h"
#include "ncui.h"
#include "lanui.h"
#include "xpsp1res.h"
#include "lanhelp.h"
#include "eapolui.h"
#include "wzcpage.h"
#include "wzcui.h"
#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0]))
////////////////////////////////////////////////////////////////////////
// CWZCConfigPage related stuff
//
// 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};
//+---------------------------------------------------------------------------
// automatically enable/disable state for all the WepK related controls
DWORD
CWZCConfigPage::EnableWepKControls()
{
BOOL bEnable;
// allow changing the Wep Key settings only if they are needed (i.e. privacy and/or shared auth)
// It is so for several reasons:
// - we allow all the params to change, but the SSID & the infra mode (these are
// the key info for a configuration and determines the position of the configuration
// in the preferred list - messing with these involves a whole work to readjust
// the position of the configuration)
// - for the long term future we could allow any params of a configuration to change
// including the key info. This will involve changing the position of this configuration
// in the preferred list, but we should do it some time.
bEnable = (m_dwFlags & WZCDLG_PROPS_RWWEP);
bEnable = bEnable && ((BST_CHECKED == ::SendMessage(m_hwndUsePW, BM_GETCHECK, 0, 0)) ||
(BST_CHECKED == ::SendMessage(m_hwndChkShared, BM_GETCHECK, 0, 0)));
::EnableWindow(m_hwndUseHardwarePW, bEnable);
bEnable = bEnable && (BST_UNCHECKED == IsDlgButtonChecked(IDC_USEHARDWAREPW));
::EnableWindow(m_hwndLblKMat, bEnable);
::EnableWindow(m_hwndEdKMat, bEnable);
::EnableWindow(m_hwndLblKMat2, bEnable && m_bKMatTouched);
::EnableWindow(m_hwndEdKMat2, bEnable && m_bKMatTouched);
::EnableWindow(m_hwndLblKIdx, bEnable);
::EnableWindow(m_hwndEdKIdx, bEnable);
return ERROR_SUCCESS;
}
//+---------------------------------------------------------------------------
// initializes WEP controls
DWORD
CWZCConfigPage::InitWepKControls()
{
UINT nWepKLen = 0;
// check whether the key is provided automatically or not
CheckDlgButton(IDC_USEHARDWAREPW,
(m_wzcConfig.dwCtlFlags & WZCCTL_WEPK_PRESENT) ? BST_UNCHECKED : BST_CHECKED);
if (m_wzcConfig.KeyLength == 0)
{
nWepKLen = 0;
m_bKMatTouched = TRUE;
}
//--- when a password is to be displayed as hidden chars, don't put in
//--- its actual length, but just 8 bulled chars.
else
{
nWepKLen = 8;
}
g_wszHiddWepK[nWepKLen] = L'\0';
::SetWindowText(m_hwndEdKMat, g_wszHiddWepK);
::SetWindowText(m_hwndEdKMat2, g_wszHiddWepK);
g_wszHiddWepK[nWepKLen] = 0x25cf; // Hidden password char (bullet)
// the index edit control shouldn't accept more than exactly one char
::SendMessage(m_hwndEdKIdx, EM_LIMITTEXT, 1, 0);
// show the current key index, if valid. Otherwise, default to the min valid value.
if (m_wzcConfig.KeyIndex + 1 >= WZC_WEPKIDX_MIN &&
m_wzcConfig.KeyIndex + 1 <= WZC_WEPKIDX_MAX)
{
CHAR szIdx[WZC_WEPKIDX_NDIGITS];
::SetWindowTextA(m_hwndEdKIdx, _itoa(m_wzcConfig.KeyIndex + 1, szIdx, 10));
}
else
m_wzcConfig.KeyIndex = 0;
return ERROR_SUCCESS;
}
//+---------------------------------------------------------------------------
// 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
CWZCConfigPage::CheckWepKMaterial(LPSTR *ppszKMat, DWORD *pdwKeyFlags)
{
DWORD dwErr = ERROR_SUCCESS;
DWORD dwKeyFlags = 0;
UINT nMatLen = ::GetWindowTextLength(m_hwndEdKMat);
LPSTR pszCrtMat = NULL;
UINT nSelIdx = 0;
switch(nMatLen)
{
case WZC_WEPKMAT_40_ASC: // 5 chars
case WZC_WEPKMAT_104_ASC: // 13 chars
case WZC_WEPKMAT_128_ASC: // 16 chars
break;
case WZC_WEPKMAT_40_HEX: // 10 hexadecimal digits
case WZC_WEPKMAT_104_HEX: // 26 hexadecimal digits
case WZC_WEPKMAT_128_HEX: // 32 hexadecimal digits
dwKeyFlags |= WZCCTL_WEPK_XFORMAT;
break;
default:
dwErr = ERROR_BAD_FORMAT;
}
// allocate space for the current key material
if (dwErr == ERROR_SUCCESS)
{
pszCrtMat = new CHAR[nMatLen + 1];
if (pszCrtMat == NULL)
dwErr = ERROR_NOT_ENOUGH_MEMORY;
}
// get the current key material from the edit control
if (dwErr == ERROR_SUCCESS)
{
if (nMatLen != ::GetWindowTextA(m_hwndEdKMat, pszCrtMat, nMatLen+1))
dwErr = GetLastError();
}
// we have now all the data. We should select the text in the Key material
// edit control from the first one of the two:
// - the nNewLen to the end (if the current content exceeds the specified length)
// - the first non hexa digit to the end (if current format is hexa)
if (dwErr == ERROR_SUCCESS && (dwKeyFlags & WZCCTL_WEPK_XFORMAT))
{
UINT nNonXIdx;
for (nNonXIdx = 0; nNonXIdx < nMatLen; nNonXIdx++)
{
if (!isxdigit(pszCrtMat[nNonXIdx]))
{
dwErr = ERROR_BAD_FORMAT;
break;
}
}
}
if (dwErr != ERROR_SUCCESS)
{
::SetWindowText(m_hwndEdKMat2, L"");
::SendMessage(m_hwndEdKMat, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
// and set the focus on the key material edit control
::SetFocus(m_hwndEdKMat);
// clean up whatever memory we allocated since we're not passing it up
if (pszCrtMat != NULL)
delete [] pszCrtMat;
}
else
{
*ppszKMat = pszCrtMat;
*pdwKeyFlags = dwKeyFlags;
}
return dwErr;
}
//+---------------------------------------------------------------------------
// parses & copies the WEP Key material from the parameter into the m_wzcConfig object
// The length should be already the good one, the format is given by m_wzcConfig.dwCtlFlags
// Since we assume a valid key material it means its length is non-zero and it is fitting in
// the configurations key material buffer, and if the formatting is hexadecimal, it
// contains an even number of hexa digits.
DWORD
CWZCConfigPage::CopyWepKMaterial(LPSTR szKMat)
{
BYTE chFakeKeyMaterial[] = {0x56, 0x09, 0x08, 0x98, 0x4D, 0x08, 0x11, 0x66, 0x42, 0x03, 0x01, 0x67, 0x66};
if (m_wzcConfig.dwCtlFlags & WZCCTL_WEPK_XFORMAT)
{
UINT nKMatIdx = 0;
// we know here we have a valid hexadecimal formatting
// this implies the string has an even number of digits
while(*szKMat != '\0')
{
m_wzcConfig.KeyMaterial[nKMatIdx] = HEX(*szKMat) << 4;
szKMat++;
m_wzcConfig.KeyMaterial[nKMatIdx] |= HEX(*szKMat);
szKMat++;
nKMatIdx++;
}
m_wzcConfig.KeyLength = nKMatIdx;
}
else
{
// the key is not in Hex format, so just copy over the bytes
// we know the length is good so no worries about overwritting the buffer
m_wzcConfig.KeyLength = strlen(szKMat);
memcpy(m_wzcConfig.KeyMaterial, szKMat, m_wzcConfig.KeyLength);
}
return ERROR_SUCCESS;
}
//+---------------------------------------------------------------------------
// sets the EAPOL Locked bit
DWORD
CWZCConfigPage::SetEapolAllowedState()
{
if (m_pEapolConfig != NULL)
{
// EAPOL shouldn't be even allowed on networks not requesting privacy or on
// ad hoc networks.
if (BST_UNCHECKED == ::SendMessage(m_hwndUsePW, BM_GETCHECK, 0, 0) ||
BST_CHECKED == ::SendMessage(m_hwndChkAdhoc, BM_GETCHECK, 0, 0))
{
// lock the Eapol configuration page
m_pEapolConfig->m_dwCtlFlags |= EAPOL_CTL_LOCKED;
}
else // for Infrastructure networks requiring privacy..
{
// unlock the Eapol configuration page (users are allowed to enable / disable 802.1X)
m_pEapolConfig->m_dwCtlFlags &= ~EAPOL_CTL_LOCKED;
// if asked to correlate onex state with the presence of an explicit key, fix this here
if (m_dwFlags & WZCDLG_PROPS_ONEX_CHECK)
{
if (BST_CHECKED == ::SendMessage(m_hwndUseHardwarePW, BM_GETCHECK, 0, 0))
m_pEapolConfig->m_EapolIntfParams.dwEapFlags |= EAPOL_ENABLED;
else
m_pEapolConfig->m_EapolIntfParams.dwEapFlags &= ~EAPOL_ENABLED;
}
}
}
return ERROR_SUCCESS;
}
//+---------------------------------------------------------------------------
// class constructor
CWZCConfigPage::CWZCConfigPage(DWORD dwFlags)
{
m_dwFlags = dwFlags;
m_bKMatTouched = FALSE;
m_pEapolConfig = NULL;
ZeroMemory(&m_wzcConfig, sizeof(WZC_WLAN_CONFIG));
m_wzcConfig.Length = sizeof(WZC_WLAN_CONFIG);
m_wzcConfig.InfrastructureMode = Ndis802_11Infrastructure;
m_wzcConfig.Privacy = 1;
}
//+---------------------------------------------------------------------------
// Uploads the configuration into the dialog's internal data
DWORD
CWZCConfigPage::UploadWzcConfig(CWZCConfig *pwzcConfig)
{
// if the configuration being uploaded is already a preferred one, reset the
// ONEX check flag (don't control the ONEX setting since it has already been
// chosen by the user at the moment the configuration was first created)
if (pwzcConfig->m_dwFlags & WZC_DESCR_PREFRD)
m_dwFlags &= ~WZCDLG_PROPS_ONEX_CHECK;
CopyMemory(&m_wzcConfig, &(pwzcConfig->m_wzcConfig), sizeof(WZC_WLAN_CONFIG));
return ERROR_SUCCESS;
}
//+---------------------------------------------------------------------------
// copy a reference to the EAPOL configuration object
DWORD
CWZCConfigPage::UploadEapolConfig(CEapolConfig *pEapolConfig)
{
// this member is never to be freed in this class
m_pEapolConfig = pEapolConfig;
return ERROR_SUCCESS;
}
//+---------------------------------------------------------------------------
// Sets the dialog flags. Returns the entire current set of flags
DWORD
CWZCConfigPage::SetFlags(DWORD dwMask, DWORD dwNewFlags)
{
m_dwFlags &= ~dwMask;
m_dwFlags |= (dwNewFlags & dwMask);
return m_dwFlags;
}
//+---------------------------------------------------------------------------
// INIT_DIALOG handler
LRESULT
CWZCConfigPage::OnInitDialog (UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DWORD dwStyle;
HRESULT hr = S_OK;
// get all the controls handles
m_hwndEdSSID = GetDlgItem(IDC_WZC_EDIT_SSID);
m_hwndChkAdhoc = GetDlgItem(IDC_ADHOC);
m_hwndChkShared = GetDlgItem(IDC_SHAREDMODE);
m_hwndUsePW = GetDlgItem(IDC_USEPW);
// wep key related controls
m_hwndUseHardwarePW = GetDlgItem(IDC_USEHARDWAREPW);
m_hwndLblKMat = GetDlgItem(IDC_WZC_LBL_KMat);
m_hwndEdKMat = GetDlgItem(IDC_WZC_EDIT_KMat);
m_hwndLblKMat2 = GetDlgItem(IDC_WZC_LBL_KMat2);
m_hwndEdKMat2 = GetDlgItem(IDC_WZC_EDIT_KMat2);
m_hwndLblKIdx = GetDlgItem(IDC_WZC_LBL_KIdx);
m_hwndEdKIdx = GetDlgItem(IDC_WZC_EDIT_KIdx);
// initialize the SSID field with the SSID, if one is given
if (m_wzcConfig.Ssid.SsidLength != 0)
{
// 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)
nLenSSID = MultiByteToWideChar(
CP_ACP,
0,
(LPCSTR)m_wzcConfig.Ssid.Ssid,
m_wzcConfig.Ssid.SsidLength,
wszSSID,
celems(wszSSID));
if (nLenSSID != 0)
{
wszSSID[nLenSSID] = L'\0';
::SetWindowText(m_hwndEdSSID, wszSSID);
}
}
// Check the "this network is adhoc" box if neccessary.
::SendMessage(m_hwndChkAdhoc, BM_SETCHECK, (m_wzcConfig.InfrastructureMode == Ndis802_11IBSS) ? BST_CHECKED : BST_UNCHECKED, 0);
// Check the "Use the network key to access this network" checkbox if necessary
// Checking this corresponds to "Shared" auth mode. Unchecked corresponds to "Open" (dsheldon)
::SendMessage(m_hwndChkShared, BM_SETCHECK, m_wzcConfig.AuthenticationMode ? BST_CHECKED : BST_UNCHECKED, 0);
// the SSID can't be under any circumstances larger than 32 chars
::SendMessage(m_hwndEdSSID, EM_LIMITTEXT, 32, 0);
// create the spin control
CreateUpDownControl(
WS_CHILD|WS_VISIBLE|WS_BORDER|UDS_SETBUDDYINT|UDS_ALIGNRIGHT|UDS_NOTHOUSANDS|UDS_ARROWKEYS,
0, 0, 0, 0,
m_hWnd,
-1,
_Module.GetResourceInstance(),
m_hwndEdKIdx,
WZC_WEPKIDX_MAX,
WZC_WEPKIDX_MIN,
WZC_WEPKIDX_MIN);
::SendMessage(m_hwndUsePW, BM_SETCHECK, (m_wzcConfig.Privacy == 1) ? BST_CHECKED : BST_UNCHECKED, 0);
// at this point we can say the WEP key is untouched
m_bKMatTouched = FALSE;
// fill in the WepK controls
InitWepKControls();
// enable or disable the controls based on how the dialog is called
::EnableWindow(m_hwndEdSSID, m_dwFlags & WZCDLG_PROPS_RWSSID);
::EnableWindow(m_hwndChkAdhoc, m_dwFlags & WZCDLG_PROPS_RWINFR);
::EnableWindow(m_hwndChkShared, m_dwFlags & WZCDLG_PROPS_RWAUTH);
::EnableWindow(m_hwndUsePW, m_dwFlags & WZCDLG_PROPS_RWWEP);
// enable or disable all the wep key related controls
EnableWepKControls();
SetEapolAllowedState();
return LresFromHr(hr);
}
//+---------------------------------------------------------------------------
// OK button handler
LRESULT
CWZCConfigPage::OnOK(UINT idCtrl, LPNMHDR pnmh, BOOL& bHandled)
{
UINT nSSIDLen;
CHAR szSSID[33];
DWORD dwKeyFlags = 0;
UINT nKeyIdx;
LPSTR szWepKMat = NULL;
// variables used for prompting the user with warning/error messages
UINT nWarnStringID = 0;
WCHAR wszBuff[48];
m_wzcConfig.Length = sizeof(WZC_WLAN_CONFIG);
// get the basic 802.11 parameters
m_wzcConfig.InfrastructureMode = (BST_CHECKED == ::SendMessage(m_hwndChkAdhoc, BM_GETCHECK, 0, 0)) ? Ndis802_11IBSS : Ndis802_11Infrastructure;
m_wzcConfig.AuthenticationMode = (BST_CHECKED == ::SendMessage(m_hwndChkShared, BM_GETCHECK, 0, 0)) ? Ndis802_11AuthModeShared : Ndis802_11AuthModeOpen;
m_wzcConfig.Privacy = (BYTE) (BST_CHECKED == ::SendMessage(m_hwndUsePW, BM_GETCHECK, 0, 0)) ? 1 : 0;
// get the SSID (max 32 chars)
nSSIDLen = ::GetWindowTextA(
m_hwndEdSSID,
szSSID,
sizeof(szSSID));
m_wzcConfig.Ssid.SsidLength = nSSIDLen;
if (nSSIDLen > 0)
CopyMemory(m_wzcConfig.Ssid.Ssid, szSSID, nSSIDLen);
// mark whether a WEP key is provided (not defaulted) or not (defaulted to whatever the hdw might have)
if (IsDlgButtonChecked(IDC_USEHARDWAREPW))
m_wzcConfig.dwCtlFlags &= ~WZCCTL_WEPK_PRESENT;
else
m_wzcConfig.dwCtlFlags |= WZCCTL_WEPK_PRESENT;
// get the key index in a local variable
wszBuff[0] = L'\0';
::GetWindowText(m_hwndEdKIdx, wszBuff, sizeof(wszBuff)/sizeof(WCHAR));
nKeyIdx = _wtoi(wszBuff) - 1;
if (nKeyIdx + 1 < WZC_WEPKIDX_MIN || nKeyIdx + 1 > WZC_WEPKIDX_MAX)
{
nWarnStringID = IDS_WZC_KERR_IDX;
nKeyIdx = m_wzcConfig.KeyIndex;
::SendMessage(m_hwndEdKIdx, EM_SETSEL, 0, -1);
::SetFocus(m_hwndEdKIdx);
}
// get the key material in a local variable.
// If the key is incorrect, the local storage is not changed.
if (m_bKMatTouched)
{
if (CheckWepKMaterial(&szWepKMat, &dwKeyFlags) != ERROR_SUCCESS)
{
nWarnStringID = IDS_WZC_KERR_MAT;
}
else
{
CHAR szBuff[WZC_WEPKMAT_128_HEX + 1]; // maximum key length
// verify whether the key is confirmed correctly. We do this only if nWarnString is
// 0, which means the key is formatted correctly, hence less than 32 chars.
szBuff[0] = '\0';
::GetWindowTextA( m_hwndEdKMat2, szBuff, sizeof(szBuff));
if (strcmp(szBuff, szWepKMat) != 0)
{
nWarnStringID = IDS_WZCERR_MISMATCHED_WEPK;
// no wep key to be saved, hence delete whatever was read so far
delete szWepKMat;
szWepKMat = NULL;
::SetWindowText(m_hwndEdKMat2, L"");
::SetFocus(m_hwndEdKMat2);
}
}
}
// check whether we actually need the wep key settings entered by the user
if ((m_wzcConfig.AuthenticationMode == Ndis802_11AuthModeOpen && !m_wzcConfig.Privacy) ||
!(m_wzcConfig.dwCtlFlags & WZCCTL_WEPK_PRESENT))
{
// no, we don't actually need the key, so we won't prompt the user if he entered an incorrect
// key material or index. In this case whatever the user entered is simply ignored.
// However, if the user entered a correct index / material, they will be saved.
nWarnStringID = 0;
}
// if there is no error to be prompted, just copy over the key settings (regardless they are needed
// or not).
if (nWarnStringID == 0)
{
m_wzcConfig.KeyIndex = nKeyIdx;
if (szWepKMat != NULL)
{
m_wzcConfig.dwCtlFlags &= ~(WZCCTL_WEPK_XFORMAT);
m_wzcConfig.dwCtlFlags |= dwKeyFlags;
CopyWepKMaterial(szWepKMat);
}
}
else
{
//NcMsgBox(
// WZCGetSPResModule(),
// m_hWnd,
// IDS_LANUI_ERROR_CAPTION,
// nWarnStringID,
// MB_ICONSTOP|MB_OK);
WCHAR pszCaption[256];
WCHAR pszText[1024];
LoadString(WZCGetSPResModule(), IDS_LANUI_ERROR_CAPTION, pszCaption, celems(pszCaption));
LoadString(nWarnStringID == IDS_WZC_KERR_MAT ? WZCGetDlgResModule() : WZCGetSPResModule(),
nWarnStringID == IDS_WZC_KERR_MAT ? 5002 : nWarnStringID,
pszText,
celems(pszText));
::MessageBox (m_hWnd, pszText, pszCaption, MB_ICONSTOP|MB_OK);
}
if (szWepKMat != NULL)
delete szWepKMat;
bHandled = TRUE;
if (nWarnStringID == 0)
{
return PSNRET_NOERROR;
}
else
{
return PSNRET_INVALID_NOCHANGEPAGE;
}
}
//+---------------------------------------------------------------------------
// Context sensitive help handler
extern const WCHAR c_szNetCfgHelpFile[];
LRESULT
CWZCConfigPage::OnContextMenu(
UINT uMsg,
WPARAM wParam,
LPARAM lParam,
BOOL& fHandled)
{
::WinHelp(m_hWnd,
c_szNetCfgHelpFile,
HELP_CONTEXTMENU,
(ULONG_PTR)g_aHelpIDs_IDC_WZC_DLG_PROPS);
return 0;
}
LRESULT
CWZCConfigPage::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_szNetCfgHelpFile,
HELP_WM_HELP,
(ULONG_PTR)g_aHelpIDs_IDC_WZC_DLG_PROPS);
}
return 0;
}
//+---------------------------------------------------------------------------
// Handler for enabling/disabling WEP
LRESULT
CWZCConfigPage::OnUsePW(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
EnableWepKControls();
SetEapolAllowedState();
return 0;
}
//+---------------------------------------------------------------------------
// Handler for enabling controls if the user wants to specify key material (password) explicitly
LRESULT
CWZCConfigPage::OnUseHWPassword(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
EnableWepKControls();
SetEapolAllowedState();
return 0;
}
//+---------------------------------------------------------------------------
// Handler for detecting changes in the key material
LRESULT
CWZCConfigPage::OnWepKMatCmd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
if (wNotifyCode == EN_SETFOCUS)
{
if (!m_bKMatTouched)
{
::SetWindowText(m_hwndEdKMat, L"");
::SetWindowText(m_hwndEdKMat2, L"");
::EnableWindow(m_hwndLblKMat2, TRUE);
::EnableWindow(m_hwndEdKMat2, TRUE);
m_bKMatTouched = TRUE;
}
}
return 0;
}
//+---------------------------------------------------------------------------
LRESULT
CWZCConfigPage::OnCheckEapolAllowed(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
return SetEapolAllowedState();
}