/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation **/ /**********************************************************************/ /* dlgdial.cpp This files contains the implementation of class CDlgRasDialin which is the class to represent the property page appears on user object property sheet as tab "RAS dial-in" FILE HISTORY: */ #include "stdafx.h" #include #include #include #include #include "helper.h" #include "resource.h" #include "DlgDial.h" #include "DlgRoute.h" #include "profsht.h" #include "helptable.h" #include "rasprof.h" #include "commctrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif const wchar_t* ALLOW_DIALIN_NAME = L"msNPAllowDialin"; const wchar_t* NP_CALLING_STATION_ID_NAME = L"msNPCallingStationID"; const wchar_t* CALLBACK_NUMBER_NAME = L"msRADIUSCallbackNumber"; const wchar_t* FRAMED_IP_ADDRESS_NAME = L"msRADIUSFramedIPAddress"; const wchar_t* FRAMED_ROUTE_NAME = L"msRADIUSFramedRoute"; const wchar_t* SERVICE_TYPE_NAME = L"msRADIUSServiceType"; ///////////////////////////////////////////////////////////////////////////// // CDlgRASDialinMerge dialog IMPLEMENT_DYNAMIC(CDlgRASDialinMerge, CPropertyPage) CDlgRASDialinMerge::~CDlgRASDialinMerge() { Reset(); } CDlgRASDialinMerge::CDlgRASDialinMerge() : CPropertyPage(CDlgRASDialinMerge::IDD), CRASUserMerge(RASUSER_ENV_LOCAL, NULL, NULL) { // initialize the memebers Reset(); } CDlgRASDialinMerge::CDlgRASDialinMerge( RasEnvType type, LPCWSTR location, LPCWSTR userPath, HWND notifyObj ) : CPropertyPage(CDlgRASDialinMerge::IDD), CRASUserMerge(type, location, userPath) { if (type == RASUSER_ENV_DS) { ADSPROPINITPARAMS initParams; initParams.dwSize = sizeof (ADSPROPINITPARAMS); if (!ADsPropGetInitInfo(notifyObj, &initParams)) { AfxThrowOleException(E_FAIL); } if (FAILED(initParams.hr)) { AfxThrowOleException(initParams.hr); } m_pWritableAttrs = initParams.pWritableAttrs; } else { m_pWritableAttrs = NULL; } // initialize the memebers Reset(); } void CDlgRASDialinMerge::Reset() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); //{{AFX_DATA_INIT(CDlgRASDialinMerge) m_bApplyStaticRoutes = FALSE; m_nCurrentProfileIndex = 0; m_bCallingStationId = FALSE; m_bOverride = FALSE; m_nDialinPermit = -1; //}}AFX_DATA_INIT // Need to save the original callback pointer because we are replacing // it with our own m_pfnOriginalCallback = m_psp.pfnCallback; m_pEditIPAddress = NULL; // init for using IPAddress common control INITCOMMONCONTROLSEX INITEX; INITEX.dwSize = sizeof(INITCOMMONCONTROLSEX); INITEX.dwICC = ICC_INTERNET_CLASSES; ::InitCommonControlsEx(&INITEX); m_bInitFailed = FALSE; m_bModified = FALSE; } void CDlgRASDialinMerge::DoDataExchange(CDataExchange* pDX) { if(m_bInitFailed) return; /* USHORT WINAPI CompressPhoneNumber( IN LPWSTR Uncompressed, OUT LPWSTR Compressed ); */ CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDlgRASDialinMerge) DDX_Control(pDX, IDC_CHECKSTATICIPADDRESS, m_CheckStaticIPAddress); DDX_Control(pDX, IDC_CHECKCALLERID, m_CheckCallerId); DDX_Control(pDX, IDC_CHECKAPPLYSTATICROUTES, m_CheckApplyStaticRoutes); DDX_Control(pDX, IDC_RADIONOCALLBACK, m_RadioNoCallback); DDX_Control(pDX, IDC_RADIOSETBYCALLER, m_RadioSetByCaller); DDX_Control(pDX, IDC_RADIOSECURECALLBACKTO, m_RadioSecureCallbackTo); DDX_Control(pDX, IDC_EDITCALLERID, m_EditCallerId); DDX_Control(pDX, IDC_EDITCALLBACK, m_EditCallback); DDX_Control(pDX, IDC_BUTTONSTATICROUTES, m_ButtonStaticRoutes); DDX_Check(pDX, IDC_CHECKAPPLYSTATICROUTES, m_bApplyStaticRoutes); DDX_Radio(pDX, IDC_RADIONOCALLBACK, m_nCallbackPolicy); DDX_Check(pDX, IDC_CHECKCALLERID, m_bCallingStationId); DDX_Check(pDX, IDC_CHECKSTATICIPADDRESS, m_bOverride); DDX_Radio(pDX, IDC_PERMIT_ALLOW, m_nDialinPermit); //}}AFX_DATA_MAP DDX_Text(pDX, IDC_EDITCALLERID, m_strCallingStationId); DDX_Text(pDX, IDC_EDITCALLBACK, m_strCallbackNumber); if(S_OK == HrIsInMixedDomain() || m_type == RASUSER_ENV_LOCAL) // user in mixed domain { DWORD dwErr = 0; typedef USHORT (WINAPI *COMPRESSCALLBACKFUNC)( IN LPWSTR Uncompressed, OUT LPWSTR Compressed); WCHAR tempBuf[RAS_CALLBACK_NUMBER_LEN_NT4 + 2]; DDV_MaxChars(pDX, m_strCallbackNumber, RAS_CALLBACK_NUMBER_LEN_NT4); COMPRESSCALLBACKFUNC pfnCompressCallback = NULL; HMODULE hMprApiDLL = NULL; hMprApiDLL = LoadLibrary(_T("mprapi.dll")); if ( NULL != hMprApiDLL ) { // load the API pointer pfnCompressCallback = (COMPRESSCALLBACKFUNC) GetProcAddress(hMprApiDLL, "CompressPhoneNumber"); if(NULL != pfnCompressCallback) { dwErr = pfnCompressCallback((LPTSTR)(LPCTSTR)m_strCallbackNumber, tempBuf); switch(dwErr) { case ERROR_BAD_LENGTH: AfxMessageBox(IDS_ERR_CALLBACK_TOO_LONG); pDX->Fail(); break; case ERROR_BAD_CALLBACK_NUMBER: AfxMessageBox(IDS_ERR_CALLBACK_INVALID); pDX->Fail(); break; } } } } else { DDV_MaxChars(pDX, m_strCallbackNumber, RAS_CALLBACK_NUMBER_LEN); } if(pDX->m_bSaveAndValidate) // save data to this class { // ip adress control if(m_pEditIPAddress->SendMessage(IPM_GETADDRESS, 0, (LPARAM)&m_dwFramedIPAddress)) m_bStaticIPAddress = TRUE; else m_bStaticIPAddress = FALSE; } else // put to dialog { // ip adress control if(m_bStaticIPAddress) m_pEditIPAddress->SendMessage(IPM_SETADDRESS, 0, m_dwFramedIPAddress); else m_pEditIPAddress->SendMessage(IPM_CLEARADDRESS, 0, m_dwFramedIPAddress); } } BEGIN_MESSAGE_MAP(CDlgRASDialinMerge, CPropertyPage) //{{AFX_MSG_MAP(CDlgRASDialinMerge) ON_BN_CLICKED(IDC_BUTTONSTATICROUTES, OnButtonStaticRoutes) ON_BN_CLICKED(IDC_CHECKAPPLYSTATICROUTES, OnCheckApplyStaticRoutes) ON_BN_CLICKED(IDC_CHECKCALLERID, OnCheckCallerId) ON_BN_CLICKED(IDC_RADIOSECURECALLBACKTO, OnRadioSecureCallbackTo) ON_BN_CLICKED(IDC_RADIONOCALLBACK, OnRadioNoCallback) ON_BN_CLICKED(IDC_RADIOSETBYCALLER, OnRadioSetByCaller) ON_BN_CLICKED(IDC_CHECKSTATICIPADDRESS, OnCheckStaticIPAddress) ON_WM_HELPINFO() ON_WM_CONTEXTMENU() ON_EN_CHANGE(IDC_EDITCALLBACK, OnChangeEditcallback) ON_EN_CHANGE(IDC_EDITCALLERID, OnChangeEditcallerid) ON_WM_CREATE() ON_BN_CLICKED(IDC_PERMIT_ALLOW, OnPermitAllow) ON_BN_CLICKED(IDC_PERMIT_DENY, OnPermitDeny) ON_BN_CLICKED(IDC_PERMIT_POLICY, OnPermitPolicy) ON_WM_DESTROY() ON_NOTIFY(IPN_FIELDCHANGED, IDC_EDITIPADDRESS, OnFieldchangedEditipaddress) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDlgRASDialinMerge message handlers // called when static routes button is pressed void CDlgRASDialinMerge::OnButtonStaticRoutes() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CDlgStaticRoutes DlgRoutes(m_strArrayFramedRoute, this); try{ if(DlgRoutes.DoModal() == IDOK) { SetModified(); }; } catch(CMemoryException* pException) { pException->Delete(); } // uncheck the checkbox if it's empty if(m_strArrayFramedRoute.GetSize() == 0) { m_CheckApplyStaticRoutes.SetCheck(FALSE); OnCheckApplyStaticRoutes(); } } // when checkbox -- apply static routes is clicked void CDlgRASDialinMerge::OnCheckApplyStaticRoutes() { SetModified(); // if checkbox "Apply static routes" is checked m_bApplyStaticRoutes = m_CheckApplyStaticRoutes.GetCheck(); // Enable / Disable the push button for editing static routes m_ButtonStaticRoutes.EnableWindow(m_bApplyStaticRoutes); if(m_bApplyStaticRoutes && m_strArrayFramedRoute.GetSize() == 0) OnButtonStaticRoutes(); } // when checkbox -- callerId is clicked void CDlgRASDialinMerge::OnCheckCallerId() { SetModified(); // Disable or enable the edit box for caller id m_EditCallerId.EnableWindow(m_CheckCallerId.GetCheck()); } // enable / disable the each items accroding to current state void CDlgRASDialinMerge::EnableDialinSettings() { BOOL bEnable; bEnable = IsPropertyWritable(ALLOW_DIALIN_NAME); EnableAccessControl(bEnable); // related to caller Id bEnable = IsPropertyWritable(NP_CALLING_STATION_ID_NAME); EnableCallerId(bEnable); // related to callback bEnable = IsPropertyWritable(CALLBACK_NUMBER_NAME) && IsPropertyWritable(SERVICE_TYPE_NAME); EnableCallback(bEnable); // related to Ip address bEnable = IsPropertyWritable(FRAMED_IP_ADDRESS_NAME); EnableIPAddress(bEnable); // related to static routes bEnable = IsPropertyWritable(FRAMED_ROUTE_NAME); EnableStaticRoutes(bEnable); // if user in mixed domain, only allow to set dialin bit and callback options if(S_OK == HrIsInMixedDomain()) // user in mixed domain { GetDlgItem(IDC_PERMIT_POLICY)->EnableWindow(FALSE); // calling station id GetDlgItem(IDC_CHECKCALLERID)->EnableWindow(FALSE); GetDlgItem(IDC_EDITCALLERID)->EnableWindow(FALSE); // framed IP address GetDlgItem(IDC_CHECKSTATICIPADDRESS)->EnableWindow(FALSE); GetDlgItem(IDC_EDITIPADDRESS)->EnableWindow(FALSE); // framed route GetDlgItem(IDC_CHECKAPPLYSTATICROUTES)->EnableWindow(FALSE); GetDlgItem(IDC_BUTTONSTATICROUTES)->EnableWindow(FALSE); } } // called when clicked on NoCallback radio button void CDlgRASDialinMerge::OnRadioNoCallback() { SetModified(); // disable the edit box for callback m_EditCallback.EnableWindow(false); } void CDlgRASDialinMerge::OnRadioSetByCaller() { SetModified(); // disable the edit box for callback m_EditCallback.EnableWindow(false); } void CDlgRASDialinMerge::OnRadioSecureCallbackTo() { SetModified(); // enable the edit box for callback m_EditCallback.EnableWindow(true); } BOOL CDlgRASDialinMerge::IsPropertyWritable( const wchar_t* propName ) const throw () { return IsFocusOnLocalUser() || ADsPropCheckIfWritable( const_cast(propName), m_pWritableAttrs ); } void CDlgRASDialinMerge::EnableAccessControl(BOOL bEnable) { GetDlgItem(IDC_PERMIT_ALLOW)->EnableWindow(bEnable); GetDlgItem(IDC_PERMIT_DENY)->EnableWindow(bEnable); GetDlgItem(IDC_PERMIT_POLICY)->EnableWindow(bEnable); } void CDlgRASDialinMerge::EnableCallerId(BOOL bEnable) { // checkbox -- caller id m_CheckCallerId.EnableWindow(bEnable); // edit box -- caller id m_EditCallerId.EnableWindow(bEnable && m_CheckCallerId.GetCheck()); } void CDlgRASDialinMerge::EnableCallback(BOOL bEnable) { // radio button -- no call back m_RadioNoCallback.EnableWindow(bEnable); // radio button -- set by caller m_RadioSetByCaller.EnableWindow(bEnable); // radio button -- secure callback to m_RadioSecureCallbackTo.EnableWindow(bEnable); // edit box -- callback m_EditCallback.EnableWindow(m_RadioSecureCallbackTo.GetCheck()); } void CDlgRASDialinMerge::EnableIPAddress(BOOL bEnable) { m_CheckStaticIPAddress.SetCheck(m_bOverride); m_CheckStaticIPAddress.EnableWindow(bEnable); m_pEditIPAddress->EnableWindow(bEnable && m_bOverride); } void CDlgRASDialinMerge::EnableStaticRoutes(BOOL bEnable) { // check box -- apply static routes m_CheckApplyStaticRoutes.EnableWindow(bEnable); if(!m_bApplyStaticRoutes) bEnable = false; // push button -- static routes m_ButtonStaticRoutes.EnableWindow(bEnable); } int CDlgRASDialinMerge::OnCreate(LPCREATESTRUCT lpCreateStruct) { return CPropertyPage::OnCreate(lpCreateStruct); } // called when dialog is created BOOL CDlgRASDialinMerge::OnInitDialog() { HRESULT hr = Load(); if FAILED(hr) { ReportError(hr, IDS_ERR_LOADUSER, m_hWnd); } else if (hr == S_FALSE) // Not the right OS to run { AfxMessageBox(IDS_ERR_NOTNT5SRV); } if(hr != S_OK) { EnableChildControls(GetSafeHwnd(), PROPPAGE_CHILD_HIDE | PROPPAGE_CHILD_DISABLE); GetDlgItem(IDC_FAILED_TO_INIT)->ShowWindow(SW_SHOW); GetDlgItem(IDC_FAILED_TO_INIT)->EnableWindow(TRUE); m_bInitFailed = TRUE; return TRUE; } if(m_strArrayCallingStationId.GetSize()) m_strCallingStationId = *m_strArrayCallingStationId[(INT_PTR)0]; AFX_MANAGE_STATE(AfxGetStaticModuleState()); m_pEditIPAddress = GetDlgItem(IDC_EDITIPADDRESS); CPropertyPage::OnInitDialog(); SetModified(FALSE); EnableDialinSettings(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } // called when click on OK or Apply button, if modify flag is set BOOL CDlgRASDialinMerge::OnApply() { HRESULT hr = S_OK; if(m_bInitFailed) goto L_Exit; if (!GetModified()) return CPropertyPage::OnApply(); m_dwDefinedAttribMask = 0; // dialin bit switch(m_nDialinPermit) { case 0: // allow m_dwDialinPermit = 1; break; case 1: // deny m_dwDialinPermit = 0; break; case 2: // policy decide -- remove the attribute from user object m_dwDialinPermit = -1; break; } // caller id if(m_bCallingStationId && !m_strCallingStationId.IsEmpty()) m_dwDefinedAttribMask |= RAS_USE_CALLERID; m_strArrayCallingStationId.DeleteAll(); if(!m_strCallingStationId.IsEmpty()) { CString* pStr = new CString(m_strCallingStationId); if(pStr) m_strArrayCallingStationId.Add(pStr); } // callback option switch(m_nCallbackPolicy) { case 0: // no callback m_dwDefinedAttribMask |= RAS_CALLBACK_NOCALLBACK; break; case 1: // set by caller m_dwDefinedAttribMask |= RAS_CALLBACK_CALLERSET; break; case 2: // secure callback m_dwDefinedAttribMask |= RAS_CALLBACK_SECURE; break; } // Ip Address if(m_bOverride && m_dwFramedIPAddress) m_dwDefinedAttribMask |= RAS_USE_STATICIP; // Static Routes if(m_bApplyStaticRoutes && m_strArrayFramedRoute.GetSize()) m_dwDefinedAttribMask |= RAS_USE_STATICROUTES; // save the user object hr = Save(); L_Exit: if (FAILED(hr)) { ReportError(hr, IDS_ERR_SAVEUSER, m_hWnd); } return CPropertyPage::OnApply(); } void CDlgRASDialinMerge::OnCheckStaticIPAddress() { SetModified(); m_bStaticIPAddress = m_CheckStaticIPAddress.GetCheck(); m_pEditIPAddress->EnableWindow(m_bStaticIPAddress); } HRESULT CDlgRASDialinMerge::Load() { HRESULT hr = S_OK; // Load the data from DS CHECK_HR(hr = CRASUserMerge::Load()); if(hr != S_OK) return hr; // dialin bit if(m_dwDialinPermit == 1) //allow dialin m_nDialinPermit = 0; else if(m_dwDialinPermit == -1) // Policy defines dialin bit -- not defined per user m_nDialinPermit = 2; else m_nDialinPermit = 1; //deny dialin // in the case of Local User Manager, the Policy defined by profile is disableed if(S_OK == HrIsInMixedDomain() && m_nDialinPermit == 2) // Local case { m_nDialinPermit = 1; // deny } // callback policy if(!(m_dwDefinedAttribMask & RAS_CALLBACK_MASK)) m_nCallbackPolicy = 0; else if(m_dwDefinedAttribMask & RAS_CALLBACK_CALLERSET) m_nCallbackPolicy = 1; else if(m_dwDefinedAttribMask & RAS_CALLBACK_SECURE) m_nCallbackPolicy = 2; else if(m_dwDefinedAttribMask & RAS_CALLBACK_NOCALLBACK) m_nCallbackPolicy = 0; //============================================================================= // change to use dwAllowDialin to hold if static Route, calling station id // if ras user object required there is a staic ip if(m_dwDefinedAttribMask & RAS_USE_STATICIP) m_bOverride = TRUE; m_bStaticIPAddress = (m_dwFramedIPAddress != 0); // static routes m_bApplyStaticRoutes = (m_dwDefinedAttribMask & RAS_USE_STATICROUTES) && (m_strArrayFramedRoute.GetSize() != 0); // calling station m_bCallingStationId = (m_dwDefinedAttribMask & RAS_USE_CALLERID) && m_strArrayCallingStationId.GetSize() && (m_strArrayCallingStationId[(INT_PTR)0]->GetLength() != 0); L_ERR: return hr; } BOOL CDlgRASDialinMerge::OnHelpInfo(HELPINFO* pHelpInfo) { ::WinHelp ((HWND)pHelpInfo->hItemHandle, AfxGetApp()->m_pszHelpFilePath, HELP_WM_HELP, (DWORD_PTR)(LPVOID)g_aHelpIDs_IDD_RASDIALIN_MERGE); return CPropertyPage::OnHelpInfo(pHelpInfo); } void CDlgRASDialinMerge::OnContextMenu(CWnd* pWnd, CPoint point) { ::WinHelp (pWnd->m_hWnd, AfxGetApp()->m_pszHelpFilePath, HELP_CONTEXTMENU, (DWORD_PTR)(LPVOID)g_aHelpIDs_IDD_RASDIALIN_MERGE); } BOOL CDlgRASDialinMerge::OnKillActive() { UINT ids = 0; if(m_bInitFailed) return CPropertyPage::OnKillActive(); if(FALSE == CPropertyPage::OnKillActive()) return FALSE; if(m_bCallingStationId && m_strCallingStationId.IsEmpty()) { GotoDlgCtrl( &m_EditCallerId ); ids = IDS_NEED_CALLER_ID; goto L_ERR; } // callback option // always callback to if(m_nCallbackPolicy == 2 && m_strCallbackNumber.IsEmpty()) { GotoDlgCtrl( &m_EditCallback ); ids = IDS_NEED_CALLBACK_NUMBER; goto L_ERR; } // Ip Address if(m_bOverride && !m_bStaticIPAddress ) { GotoDlgCtrl( m_pEditIPAddress ); ids = IDS_NEED_IPADDRESS; goto L_ERR; } // Static Routes if(m_bApplyStaticRoutes && m_strArrayFramedRoute.GetSize() == 0) { GotoDlgCtrl( &m_CheckApplyStaticRoutes ); goto L_ERR; } return TRUE; L_ERR: if (ids != 0) AfxMessageBox(ids); return FALSE; } //--------------------------------------------------------------------------- // This is our self deleting callback function. If you have more than a // a few property sheets, it might be a good idea to implement this in a // base class and derive your MFC property sheets from the base class // UINT CALLBACK CDlgRASDialinMerge::PropSheetPageProc ( HWND hWnd, // [in] Window handle - always null UINT uMsg, // [in,out] Either the create or delete message LPPROPSHEETPAGE pPsp // [in,out] Pointer to the property sheet struct ) { ASSERT( NULL != pPsp ); // We need to recover a pointer to the current instance. We can't just use // "this" because we are in a static function CDlgRASDialinMerge* pMe = reinterpret_cast(pPsp->lParam); ASSERT( NULL != pMe ); switch( uMsg ) { case PSPCB_CREATE: break; case PSPCB_RELEASE: // Since we are deleting ourselves, save a callback on the stack // so we can callback the base class LPFNPSPCALLBACK pfnOrig = pMe->m_pfnOriginalCallback; delete pMe; return 1; //(pfnOrig)(hWnd, uMsg, pPsp); } // Must call the base class callback function or none of the MFC // message map stuff will work return (pMe->m_pfnOriginalCallback)(hWnd, uMsg, pPsp); } // end PropSheetPageProc() void CDlgRASDialinMerge::OnChangeEditcallback() { // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CPropertyPage::OnInitDialog() // function to send the EM_SETEVENTMASK message to the control // with the ENM_CHANGE flag ORed into the lParam mask. // TODO: Add your control notification handler code here SetModified(); } void CDlgRASDialinMerge::OnChangeEditcallerid() { SetModified(); // TODO: If this is a RICHEDIT control, the control will not // send this notification unless you override the CPropertyPage::OnInitDialog() // function to send the EM_SETEVENTMASK message to the control // with the ENM_CHANGE flag ORed into the lParam mask. // TODO: Add your control notification handler code here } void CDlgRASDialinMerge::OnPermitAllow() { SetModified(); } void CDlgRASDialinMerge::OnPermitDeny() { SetModified(); } void CDlgRASDialinMerge::OnPermitPolicy() { SetModified(); } void CDlgRASDialinMerge::OnFieldchangedEditipaddress(NMHDR* pNMHDR, LRESULT* pResult) { SetModified(); *pResult = 0; }